提问人:user2380782 提问时间:11/16/2023 更新时间:11/17/2023 访问量:57
在 R 中切换 DataFrame 中的列值,基于两列的组合
switch column values in dataframe in R based in combination of two columns
问:
我有一个关于根据基于两列的组合更改 data.frame 中的字符值的问题。我将尝试举一个例子来说明 de data.frame 的外观
data <- data.frame(A1 = c("A", "T", "C"), A2 = c("C", "G", "T"),
Ind1 = c("AA", "TG", "TT"), Ind2 = c("CA", "GT", "CT"),
Ind3 = c("AC", "GG", "TC"))
> data
A1 A2 Ind1 Ind2 Ind3
1 A C AA CA AC
2 T G TG GT GG
3 C T TT CT TC
我想将列中的值从 Ind1 更改为 Ind3,这些值与列和 和 的可能组合不匹配,例如在第一行中,是 和 是 ,因此可能的组合将是 、 (组合基于 和 按该顺序)。因此,Ind2 应代替 .A1
A2
A1
A
A2
C
AA
AC
CC
A1
A2
AC
CA
所需的输出将是这样的:
> data
A1 A2 Ind1 Ind2 Ind3
1 A C AA AC AC
2 T G TG TG GG
3 C T TT CT CT
我试过了,但它不起作用。任何帮助将不胜感激。
谢谢switch
答:
5赞
Peter
11/16/2023
#1
如果我正确理解了这个问题,并且假设您只有两个字母要处理,那么只有一个情况需要编辑;也就是说,当字母的顺序相反时,即“A2A1”。所有其他情况都是正确的。所以你可以通过一个简单的突变来管理它。ifelse
data <- data.frame(A1 = c("A", "T", "C"), A2 = c("C", "G", "T"),
Ind1 = c("AA", "TG", "TT"), Ind2 = c("CA", "GT", "CT"),
Ind3 = c("AC", "GG", "TC"))
library(dplyr)
data |>
mutate(across(starts_with("Ind"), ~ ifelse(.x == paste0(A2, A1), paste0(A1, A2), .x)))
#> A1 A2 Ind1 Ind2 Ind3
#> 1 A C AA AC AC
#> 2 T G TG TG GG
#> 3 C T TT CT CT
作为对OP评论的回应,使用“真实”数据:
df2 <- structure(list(chr = "chr11", pos = "74565122", snp_id = "chr11_74565122_C_T_b38", Allele1 = "C", Allele2 = "T", GTEX_111CU = "TT", GTEX_111YS = "CT", GTEX_1122O = "TC", GTEX_117XS = "TC", GTEX_117YX = "TC"), class = "data.frame", row.names = c(NA, -1L))
df2
#> chr pos snp_id Allele1 Allele2 GTEX_111CU GTEX_111YS
#> 1 chr11 74565122 chr11_74565122_C_T_b38 C T TT CT
#> GTEX_1122O GTEX_117XS GTEX_117YX
#> 1 TC TC TC
mutate(df2, across(starts_with("GTEX"), ~ ifelse(.x %in% paste0(Allele2, Allele1), paste0(Allele1, Allele2), .x)))
#> chr pos snp_id Allele1 Allele2 GTEX_111CU GTEX_111YS
#> 1 chr11 74565122 chr11_74565122_C_T_b38 C T TT CT
#> GTEX_1122O GTEX_117XS GTEX_117YX
#> 1 CT CT CT
评论
0赞
user2380782
11/17/2023
谢谢@Peter,我尝试了一些真实数据,但它似乎不起作用,我不知道为什么。一个真实的例子是 GTEX-111CU' = “TT”, = “CT”, = “TC”, = “TC”, = “TC”, = “CC”), class = “data.frame”, row.names = c(NA, -1L))df2 %>% mutate(across(starts_with(“GTEX”), ~ ifelse(.x %in% paste0(Allele2, Allele1), paste0(Allele1, Allele2), .x)))'dput(df2) structure(list(chr = "chr11", pos = "74565122", snp_id = "chr11_74565122_C_T_b38", Allele1 = "C", Allele2 = "T",
GTEX-111YS
GTEX-1122O
GTEX-117XS
GTEX-117YX
GTEX-11DXX
GTEX-11DXZ
, I have tried:
0赞
Peter
11/17/2023
对不起,评论中的对我不起作用。我收到“错误:意外的符号......”dput(df2)
0赞
user2380782
11/17/2023
请试试这个:structure(list(chr = "chr11", pos = "74565122", snp_id = "chr11_74565122_C_T_b38", Allele1 = "C", Allele2 = "T", GTEX_111CU = "TT", GTEX_111YS = "CT", GTEX_1122O = "TC", GTEX_117XS = "TC", GTEX_117YX = "TC"), class = "data.frame", row.names = c(NA, -1L))
0赞
Peter
11/17/2023
似乎对我来说工作得很好。请参阅更新的答案。
0赞
user2380782
11/17/2023
谢谢@Peter,它奏效了。这是一些软件包冲突的问题。我重新启动了 R 会话并像魅力一样工作
3赞
Maël
11/16/2023
#2
除了 Peter 非常聪明的技巧之外,如果你想在 base R 中寻求一个更硬编码的解决方案,你可以按照 A1 和 A2 中的顺序逐行处理字符串,然后返回。这与要订购的字母数量无关:split
sort
paste
cols <- grep("Ind", colnames(data))
data[cols] <-
apply(data, 1, \(x){
strsplit(x[cols], "") |>
sapply(\(y) factor(y, levels = x[-cols]) |>
sort() |>
paste(collapse = ""))
})) |>
t()
# A1 A2 Ind1 Ind2 Ind3
# 1 A C AA AC AC
# 2 T G TG TG GG
# 3 C T TT CT CT
3赞
Gregor Thomas
11/16/2023
#3
我们可以使用正则表达式模式来测试组合的有效性,如果字符串无效,则反转字符串:
library(dplyr)
library(stringr)
data |>
mutate(across(starts_with("Ind"), \(x) ifelse(
str_detect(x, pattern = sprintf("^%s{0,2}%s{0,2}$", A1, A2)),
x,
stringi::stri_reverse(x))
))
# A1 A2 Ind1 Ind2 Ind3
# 1 A C AA AC AC
# 2 T G TG TG GG
# 3 C T TT CT CT
下一个:按多列对数据框行进行排序(排序)
评论