Ste*_*edy 28 r bioinformatics dataframe
我有一个大型的data.frame字符数据,我想根据其他语言中通常称为字典的内容进行转换.
目前我正在这样做:
foo <- data.frame(snp1 = c("AA", "AG", "AA", "AA"), snp2 = c("AA", "AT", "AG", "AA"), snp3 = c(NA, "GG", "GG", "GC"), stringsAsFactors=FALSE)
foo <- replace(foo, foo == "AA", "0101")
foo <- replace(foo, foo == "AC", "0102")
foo <- replace(foo, foo == "AG", "0103")
Run Code Online (Sandbox Code Playgroud)
这样可以正常工作,但是replace
每次我想要替换data.frame中的一个项目时,重复该语句显然不是很漂亮并且看起来很愚蠢.
有没有更好的方法来实现这一点,因为我有一个大约25个键/值对的字典?
c.g*_*rez 30
如果您愿意使用包,那么它plyr
是一个非常受欢迎的包,并且具有这个方便的mapvalues()函数,可以满足您的需求:
foo <- mapvalues(foo, from=c("AA", "AC", "AG"), to=c("0101", "0102", "0103"))
Run Code Online (Sandbox Code Playgroud)
请注意,它适用于所有类型的数据类型,而不仅仅是字符串.
Mar*_*gan 27
map = setNames(c("0101", "0102", "0103"), c("AA", "AC", "AG"))
foo[] <- map[unlist(foo)]
Run Code Online (Sandbox Code Playgroud)
假设map
涵盖了所有案例foo
.如果foo
是一个矩阵(字符()),这会感觉不像'黑客',在空间和时间上都更有效率,然后
matrix(map[foo], nrow=nrow(foo), dimnames=dimnames(foo))
Run Code Online (Sandbox Code Playgroud)
当存在数百万个SNP和数千个样本时,矩阵和数据帧变体都与R 2的矢量大小限制相差2 ^ 31-1.
Ram*_*ath 14
这是一个快速的解决方案
dict = list(AA = '0101', AC = '0102', AG = '0103')
foo2 = foo
for (i in 1:3){foo2 <- replace(foo2, foo2 == names(dict[i]), dict[i])}
Run Code Online (Sandbox Code Playgroud)
用字典替换字符串或字符串向量中的值的最易读的方法之一是stringr::str_replace_all
,来自stringr
包。所需的模式str_replace_all
可以是字典,例如,
# 1. Made your dictionnary
dictio_replace= c("AA"= "0101",
"AC"= "0102",
"AG"= "0103") # short example of dictionnary.
# 2. Replace all pattern, according to the dictionary-values (only a single vector of string, or a single string)
foo$snp1 <- stringr::str_replace_all(string = foo$snp1,
pattern= dictio_replace) # we only use the 'pattern' option here: 'replacement' is useless since we provide a dictionnary.
Run Code Online (Sandbox Code Playgroud)
使用 foo$snp2 和 foo$snp3 重复步骤 2。如果您有更多的向量要转换,最好使用另一个 func',以便在不重复的情况下替换数据帧中每个列/向量中的值。
这是可以完成工作的简单方法:
key <- c('AA','AC','AG')
val <- c('0101','0102','0103')
lapply(1:3,FUN = function(i){foo[foo == key[i]] <<- val[i]})
foo
snp1 snp2 snp3
1 0101 0101 <NA>
2 0103 AT GG
3 0101 0103 GG
4 0101 0101 GC
Run Code Online (Sandbox Code Playgroud)
lapply
在这种情况下,将输出我们实际上并不关心的列表。您可以根据需要将结果分配给某些内容,然后将其丢弃。我在这里遍历索引,但是您也可以轻松地将键/值本身放在列表中并直接遍历它们。注意将全局赋值与配合使用<<-
。
我想办法解决这个问题,mapply
但是第一次尝试没有成功,所以我改了。我怀疑有解决方案mapply
,但是。
使用dplyr::recode:
library(dplyr)
mutate_all(foo, funs(recode(., "AA" = "0101", "AC" = "0102", "AG" = "0103",
.default = NA_character_)))
# snp1 snp2 snp3
# 1 0101 0101 <NA>
# 2 0103 <NA> <NA>
# 3 0101 0103 <NA>
# 4 0101 0101 <NA>
Run Code Online (Sandbox Code Playgroud)
我们也可以使用 dplyr::case_when
library(dplyr)
foo %>%
mutate_all(~case_when(. == "AA" ~ "0101",
. == "AC" ~ "0102",
. == "AG" ~ "0103",
TRUE ~ .))
# snp1 snp2 snp3
#1 0101 0101 <NA>
#2 0103 AT GG
#3 0101 0103 GG
#4 0101 0101 GC
Run Code Online (Sandbox Code Playgroud)
它检查条件并在条件为 时替换为相应的值TRUE
。如果需要,我们可以添加更多条件TRUE ~ .
,如果没有任何条件匹配,我们将保持原样。如果我们想将它们NA
改为,我们可以删除最后一行。
foo %>%
mutate_all(~case_when(. == "AA" ~ "0101",
. == "AC" ~ "0102",
. == "AG" ~ "0103"))
# snp1 snp2 snp3
#1 0101 0101 <NA>
#2 0103 <NA> <NA>
#3 0101 0103 <NA>
#4 0101 0101 <NA>
Run Code Online (Sandbox Code Playgroud)
NA
如果上述条件都不满足,这会将值更改为。
仅使用基 R 的另一种选择是创建一个lookup
具有旧值和新值unlist
的数据框,数据框,match
它们具有旧值,获取相应的新值并替换。
lookup <- data.frame(old_val = c("AA", "AC", "AG"),
new_val = c("0101", "0102", "0103"))
foo[] <- lookup$new_val[match(unlist(foo), lookup$old_val)]
Run Code Online (Sandbox Code Playgroud)
请注意,此答案的开始是为了解决在如何使用值向量替换数据框中的所有值中发布的更简单的问题?.不幸的是,这个问题被视为实际问题的重复.因此,我将尝试在此处建议基于替换两种情况的因子水平的解决方案.
如果只有一个向量(或一个数据框列)的值需要替换,并且没有对使用因素的反对意见,我们可以强制对向量进行因子分析并根据需要更改因子级别:
x <- c(1, 1, 4, 4, 5, 5, 1, 1, 2)
x <- factor(x)
x
#[1] 1 1 4 4 5 5 1 1 2
#Levels: 1 2 4 5
replacement_vec <- c("A", "T", "C", "G")
levels(x) <- replacement_vec
x
#[1] A A C C G G A A T
#Levels: A T C G
Run Code Online (Sandbox Code Playgroud)
使用这个forcats
包可以在一个单行中完成:
x <- c(1, 1, 4, 4, 5, 5, 1, 1, 2)
forcats::lvls_revalue(factor(x), replacement_vec)
#[1] A A C C G G A A T
#Levels: A T C G
Run Code Online (Sandbox Code Playgroud)
如果需要替换数据帧的多列的所有值,则可以扩展该方法.
foo <- data.frame(snp1 = c("AA", "AG", "AA", "AA"),
snp2 = c("AA", "AT", "AG", "AA"),
snp3 = c(NA, "GG", "GG", "GC"),
stringsAsFactors=FALSE)
level_vec <- c("AA", "AC", "AG", "AT", "GC", "GG")
replacement_vec <- c("0101", "0102", "0103", "0104", "0302", "0303")
foo[] <- lapply(foo, function(x) forcats::lvls_revalue(factor(x, levels = level_vec),
replacement_vec))
foo
# snp1 snp2 snp3
#1 0101 0101 <NA>
#2 0103 0104 0303
#3 0101 0103 0303
#4 0101 0101 0302
Run Code Online (Sandbox Code Playgroud)
请注意,level_vec
并且replacement_vec
必须具有相同的长度.
更重要的是,level_vec
应该是完整的,即包括原始数据框的受影响列中的所有可能值.(unique(sort(unlist(foo)))
用于验证).否则,将强制执行任何缺失值<NA>
.请注意,这也是Martin Morgans答案的要求.
因此,如果只有少数不同的值需要替换,那么其他一个答案可能会更好,例如Ramnath的.
归档时间: |
|
查看次数: |
22952 次 |
最近记录: |