我在R中有一个包含SNP行的数据框,如下所示:
Column1 Column2 Column3 Column4
rs111 rs222 NA NA
rs333 rs444 rs555 rs666
rs777 rs888 rs999 NA
和另一个数据框:
SNP P value
RS111 0.21
RS222 0.02
RS333 0.80
RS444 0.55
RS555 0.10
RS666 0.07
RS777 0.99
RS888 0.33
RS999 0.45
我试图将第一个数据帧中每行的最低P值的SNP提取到新的列或列表中。实际数据框的尺寸为~15,000行×500列(包括大多数行中的大量NA)。我最初尝试用P值替换标签,使用apply for each row,然后尝试使用match函数替换P值的标签,但是无法获得类似的矩阵,并且我确定这不是最好的方法这样做。
有没有人知道如何做得更好?非常感谢你!
[R
答案 0 :(得分:1)
您可以使用dplyr
+ tidyr
:
library(tidyr)
library(dplyr)
df1$Col_min = df1 %>%
mutate(ID = row_number()) %>%
gather(var, SNP, -ID) %>%
left_join(df2 %>% mutate(SNP = tolower(SNP))) %>%
group_by(ID) %>%
slice(which.min(P_value)) %>%
pull(SNP)
如果速度是一个问题,这是使用hashmap
的另一个解决方案,这是非常快的。基本上,我将df2
存储为哈希表,并通过索引哈希表查找返回的值,为P_value
中的每一行提取具有最低df1
的元素:
library(hashmap)
lookup = hashmap(df2$SNP, df2$P_value)
df1$Col_min = apply(df1, 1, function(x) x[which.min(lookup[[toupper(x)]])])
<强>结果:强>
Column1 Column2 Column3 Column4 Col_min
1 rs111 rs222 <NA> <NA> rs222
2 rs333 rs444 rs555 rs666 rs666
3 rs777 rs888 rs999 <NA> rs888
<强>基准:强>
hash_func = function(){
apply(df1, 1, function(x) x[which.min(lookup[[toupper(x)]])])
}
dplyr_func = function(){
df1 %>%
mutate(ID = row_number()) %>%
gather(var, SNP, -ID) %>%
left_join(df2 %>% mutate(SNP = tolower(SNP))) %>%
group_by(ID) %>%
slice(which.min(P_value)) %>%
pull(SNP)
}
library(microbenchmark)
microbenchmark(dplyr_func(), hash_func())
# Unit: microseconds
# expr min lq mean median uq max neval
# dplyr_func() 16530.857 17780.660 20086.9777 19017.828 21500.2595 42734.06 100
# hash_func() 153.561 177.641 311.2788 268.633 298.0425 5254.22 100
数据:强>
df1 = read.table(text = "Column1 Column2 Column3 Column4
rs111 rs222 NA NA
rs333 rs444 rs555 rs666
rs777 rs888 rs999 NA", header = TRUE, stringsAsFactors = FALSE)
df2 = read.table(text = "SNP P_value
RS111 0.21
RS222 0.02
RS333 0.80
RS444 0.55
RS555 0.10
RS666 0.07
RS777 0.99
RS888 0.33
RS999 0.45", header = TRUE, stringsAsFactors = FALSE)
答案 1 :(得分:0)
我不确定我的解决方案在内存和性能方面是否是最好的,但至少它应该起作用。意见和建议表示赞赏!
假设矩阵被称为mat
,而data.frame被称为df
。首先定义一个函数find_min
:
find_min <- function(v){
temp <- filter(df, tolower(SNP) %in% v) %>% filter(P_value == min(P_value))
return(temp$SNP)
}
然后你可以做
result <- apply(mat, 1, find_min)
这将为您提供一个具有最小P值的SNP列,在mat
的每一行进行评估。
希望这有帮助。