2016-05-28 15 views
5
snp1 <- c("AA", "AT", "AA", "TT", "AA", "AT", "AA", "AA", "AA", "AT") 
snp2 <- c("GG", "GC", "GG", "CC", "CC", "GC", "GG", "GG", "GG", "GC") 
df1 <- data.frame(snp1, snp2) 

num1 <- c(1, 2, 1, 3, 1, 2, 1, 1, 1, 2) 
num2 <- c(1, 2, 1, 3, 3, 2, 1, 1, 1, 2) 
df2 <- data.frame(num1, num2) 

Điều này được thực hiện trong R. Tôi có đối tượng df1, mà tôi muốn chuyển thành df2. Đối với mỗi cột trong df1, giá trị phổ biến nhất được chuyển đổi thành 1, giá trị phổ biến thứ hai thành 2, v.v. Làm thế nào để tôi làm điều này một cách hiệu quả?Chuyển đổi khung dữ liệu của kiểu gen snp trong ma trận số

+0

'data.frame (lapply (df1, function (x) {as.numeric (yếu tố (x, mức = tên (loại (-table (x)))))))) ' – alistaire

Trả lời

3

giá trị phổ biến nhất được chuyển thành 1, giá trị phổ biến thứ hai thành 2, v.v.

Bạn có thể sử dụng table, sort, factor:

convert <- function(x) as.integer(factor(x, levels = names(sort(-table(x))))) 

num1 <- convert(df1$snp1) 
num2 <- convert(df$2snp2) 

áp dụng điều này cho tất cả các cột trong một cách tiện dụng?

Sử dụng lapply:

df2 <- as.data.frame(lapply(df1, FUN = convert)) 

Thảo luận:

@thelatemail đề cập đến khả năng sử dụng match(). Việc sử dụng levels() giả định rằng tất cả các cột của df1 là các yếu tố dễ dàng. Thường thì điều này là đúng, trừ khi một số người, như tôi, đã đặt options(stringsAsFactors = FALSE) trong tệp khởi động R. Tôi sẽ thay thế levels() bằng names(), vì vậy ý ​​tưởng của anh ấy sẽ hoạt động đối với cả đầu vào chuỗi và yếu tố đầu vào.

convert2 <- function(x) { 
    tab <- table(x) 
    match(x, names(tab)[order(-tab)]) 
    } 

câu hỏi đầu tiên của chúng tôi là, là convert2() nhanh hơn đáng kể so với convert()?

Chúng ta định nghĩa một hàm đồ chơi để đo lường hiệu suất giữa hai chức năng:

timing <- function(n, rep, FACTOR = FALSE, FUN1, FUN2) { 
    ## sample data 
    x <- c("AA", "AT", "TT")[sample(1:3, n, replace = TRUE)] 
    if (FACTOR) x <- factor(x) 
    ## method 1: as.integer(factor()) 
    t1 <- system.time(for (k in 1:rep) {tmp <- FUN1(x); tmp <- FUN1(x); tmp <- FUN1(x); tmp <- FUN1(x)}) 
    ## method 2: match() 
    t2 <- system.time(for (k in 1:rep) {tmp <- FUN2(x); tmp <- FUN2(x); tmp <- FUN2(x); tmp <- FUN2(x)}) 
    ## timing summary 
    cat("FUN1\n"); print(t1) 
    cat("FUN2\n"); print(t2) 
    } 

Đối với chuỗi đầu vào nhân vật ta có:

> timing(n = 20000, rep = 1000, FACTOR = FALSE, FUN1 = convert, FUN2 = convert2) 
FUN1 ## convert(), using as.integer(factor()) 
    user system elapsed 
18.772 0.212 19.052 
FUN2 ## convert2(), using match() 
    user system elapsed 
17.792 0.100 17.920 

Đối với đầu vào yếu tố, ta có:

> timing(n = 20000, rep = 1000, FACTOR = TRUE, FUN1 = convert, FUN2 = convert2) 
FUN1 ## convert(), using as.integer(factor()) 
    user system elapsed 
17.180 0.144 17.384 
FUN2 ## convert2(), using match() 
    user system elapsed 
15.500 0.168 15.693 

Vì vậy:

  • khi đầu vào là các yếu tố, cả hai phương pháp đều nhanh hơn;
  • convert2() nhanh hơn khoảng 5% - 10% so với convert1().

Bây giờ hãy hạn chế rằng chúng tôi có yếu tố đầu vào, chúng tôi thực sự có thể thực hiện nhanh hơn convert2(). Hãy xem xét:

## only works for factor input!! 
convert3 <- function(x) { 
    tab <- table(x) 
    match(as.integer(x), (seq_along(tab))[order(-tab)]) 
    } 

Ở đây, chúng tôi đã sử dụng đối sánh số nguyên.Hãy so sánh convert2()convert3():

> timing(n = 20000, rep = 1000, FACTOR = TRUE, FUN1 = convert2, FUN2 = convert3) 
FUN1 ## convert2(), using string match 
    user system elapsed 
15.168 0.156 15.351 
FUN2 ## convert3(), using integer match 
    user system elapsed 
14.032 0.116 14.174 
6

Biến thể về một chủ đề:

lapply(df1, function(x) match(x, levels(x)[order(-table(x))])) 
#$snp1 
# [1] 1 2 1 3 1 2 1 1 1 2 
# 
#$snp2 
# [1] 1 2 1 3 3 2 1 1 1 2 
Các vấn đề liên quan