我想基于与行变量匹配的列名替换数据框单元格中的值,如示例代码中所示。我知道,嵌套循环不是首选的方法(并且更有效的解决方案可能非常简单),但是却无法找到干净的矢量化方法。我一直在搞乱嵌套的应用,即在apply中调用的函数内部应用,但是没有成功,也不是这似乎是最好的方法。
输入:
test.df
Group G1 G2 G3
1 G1 0.63910462 0.5738143 0.97428347
2 G2 0.62578294 0.4653417 0.92010090
3 G3 0.01136336 0.3163722 0.20266664
4 G1 0.09054996 0.1984567 0.17488220
5 G2 0.74865266 0.9862222 0.80725355
6 G3 0.82855980 0.2668529 0.06786335
7 G1 0.74310410 0.8861169 0.44801963
8 G2 0.97329786 0.6682355 0.69658779
9 G3 0.68696020 0.7362139 0.77452962
输出:
test.df
Group G1 G2 G3
1 G1 NA 0.5738143 0.9742835
2 G2 0.62578294 NA 0.9201009
3 G3 0.01136336 0.3163722 NA
4 G1 NA 0.1984567 0.1748822
5 G2 0.74865266 NA 0.8072535
6 G3 0.82855980 0.2668529 NA
7 G1 NA 0.8861169 0.4480196
8 G2 0.97329786 NA 0.6965878
9 G3 0.68696020 0.7362139 NA
代码:
test.df <- data.frame("Group"=rep(c("G1", "G2", "G3"), 3), "G1"=runif(9, 0, 1), "G2"=runif(9, 0, 1), "G3" = runif(9,0,1))
for (j in 1:ncol(test.df)) {
for(i in 1:nrow(test.df)) {
if(colnames(test.df)[j] == test.df$Group[i]) {
test.df[i,j] <- NA
}
}
}
我想我可以使用dplyr过滤器来获取需要替换的值,替换它们,然后重新组装数据框,但我有兴趣学习其他选项。
答案 0 :(得分:3)
使用match()
对其进行矢量化。
idx <- cbind(seq_len(nrow(test.df)), match(test.df$Group, names(test.df)[-1]))
test.df[-1][idx] <- NA
idx
创建索引矩阵,用于收集我们想要转换为NA的值。第一部分只是行数长度的序列。第二部分将Group
列与其他列的名称相匹配。然后我们替换。
这会导致更新test.df
Group G1 G2 G3
1 G1 NA 0.5738143 0.9742835
2 G2 0.62578294 NA 0.9201009
3 G3 0.01136336 0.3163722 NA
4 G1 NA 0.1984567 0.1748822
5 G2 0.74865266 NA 0.8072535
6 G3 0.82855980 0.2668529 NA
7 G1 NA 0.8861169 0.4480196
8 G2 0.97329786 NA 0.6965878
9 G3 0.68696020 0.7362139 NA
注意:我在创建stringsAsFactors = FALSE
时遇到了test.df
,所以在您的test.df$Group <- as.character(test.df$Group)
中,您必须首先使用{{1}},因为您的示例将其作为因素
答案 1 :(得分:2)
您可以拆分行然后再分配:
s = split(seq_len(nrow(test.df)), test.df$Group)
for (k in names(s)) test.df[s[[k]], k] <- NA_real_
或者使用data.table:
library(data.table)
for (k in names(s)) set(test.df, i = s[[k]], j = k, v = NA_real_)
请注意,您实际上不必在此处使用data.table;我们在data.frame上使用set
。在这种情况下set
的优点是通过引用进行修改。
答案 2 :(得分:1)
传递接力棒:
test.df %>% mutate(G1 = ifelse(Group == "G1", NA, G1))
# Group G1 G2 G3
# 1 G1 NA 0.3337749 0.3999944
# 2 G2 0.25801678 0.4763512 0.3253522
# 3 G3 0.47854525 0.8921983 0.7570871
# 4 G1 NA 0.8643395 0.2026923
# 5 G2 0.08424691 0.3899895 0.7111212
# 6 G3 0.87532133 0.7773207 0.1216919
# 7 G1 NA 0.9606180 0.2454885
# 8 G2 0.83944035 0.4346595 0.1433044
# 9 G3 0.34668349 0.7125147 0.2396294
现在,我如何让mutate扫描所有列?