我有两个大数据框,我使用“1”将它们关联起来以指示它们之间的匹配。例如:
Name<-c("N1", "N2", "N3")
A1<-c(1, NA, 1)
A2<-c(NA, 1, NA)
A3<-c(NA, 1, 1)
df1<-data.frame(Name, A1, A2, A3)
> df1
Name A1 A2 A3
1 N1 1 NA NA
2 N2 NA 1 1
3 N3 1 NA 1
Var<-c("A1", "A2", "A3")
Detail<-c("Red", "Red, Blue", "Green, Red")
df2<-data.frame(Var, Detail)
> df2
Var Detail
1 A1 Red
2 A2 Red, Blue
3 A3 Green, Red
我正在尝试汇总与 df2 中每个变量关联的所有详细信息,其中每个名称都标有 df1 中该特定变量的“1”。最后,我希望将“详细信息”的所有唯一条目作为单独的列,如果名称与它们相关联,则为 1。 df3 将是所需结果的示例。
Red<-c(1,1,1)
Blue<-c(0,1,0)
Green<-c(0,1,1)
df3<-data.frame(Name, Red, Blue, Green)
> df3
Name Red Blue Green
1 N1 1 0 0
2 N2 1 1 1
3 N3 1 0 1
在经历了类似的问题并尝试了很长时间之后,这就是我想要做的:
我用列名替换了 df1 中带有“1”的单元格,以便它们能够与 df2 中的相应行匹配
ones <- which(df1=="1", arr.ind=T)
df1[ones]<-colnames(df1)[ones[,2]]
df1;
我知道最好避免循环,但我想不出其他方法。我试图循环遍历列和行,将它们与 df2 中的 Var 名称进行比较,并使用“which”将相应的详细信息复制到该单元格中回到 df1。但是我不断收到错误消息...
for(i in 2:ncol(df1)){
for(j in 1:nrow(df1)){
+ tmp <- df2[which(df2[,1]==df1[j,i]),]
+ df1[j,i] <- tmp[which(tmp[j,]==df1[j,i]),4]
}
}
如果我尝试单独替换它,我也不会得到想要的结果
tmp <- df2[which(df2[,1]==df1[1,2]),]
df1[1,2] <- tmp[which(tmp[1,1]==df1[1,2]),2]
这就是我被困的地方。在这一步之后,我会将所有详细信息聚合到单个单元格中的单个逗号分隔字符串中,列出所有唯一的详细信息并将它们分别变成一列,然后进行另一个循环以将“1”添加到每个实例中具有详细信息的字符串与新列标题相匹配。
可能有一种更简单的方法可以避免一半(或全部)这些步骤,如果这是一个基本问题,我们深表歉意。非常感谢任何建议!
最佳答案
使用 tidyverse
套件。
library(tidyverse)
Name<-c("N1", "N2", "N3")
A1<-c(1, NA, 1)
A2<-c(NA, 1, NA)
A3<-c(NA, 1, 1)
df1<-data.frame(Name, A1, A2, A3)
Var<-c("A1", "A2", "A3")
Detail<-c("Red", "Red, Blue", "Green, Red")
df2<-data.frame(Var, Detail)
# The pipe operator (%>%) makes df1 the first argument of the next function.
# It lets us look at this "in order" not nested
df3 <- df1 %>%
gather(Var, value, -Name) %>%
merge(df2) %>%
filter(!is.na(value)) %>%
separate(Detail, into = paste0("color",1:2), fill = "right") %>%
gather(value, color, color1:color2) %>%
select(-value) %>%
filter(!is.na(color)) %>%
mutate(
one = 1L
) %>%
spread(color, one, fill = 0) %>%
group_by(Name) %>%
summarize_at(vars(Red, Blue, Green),
~ as.integer(sum(.) > 0))
如果您不熟悉管道运算符或我正在使用的其他函数,我会一次调用它,这样您就可以看到它在做什么(所有这些都记录在 https://www.tidyverse.org/ 中)。例如,
df1 %>%
gather(Var, value, -Name)
那个特别的部分很像 reshape(df1, direction = 'long',...)
,但它对我来说更容易记住。如果您的完整数据集有超过 2 种颜色,您需要对 paste0 和 gather 命令进行调整。我不确定是否有等同于“单独”的东西,它会根据需要为所有颜色添加尽可能多的数字,但只要你知道,这应该不是问题。如果没有,你可以通过做得到它
num_colors <- max(sapply(strsplit(as.character(df2$Detail), ", "), length))
或(演示管道提高易读性的程度):
num_colors <- df2$Detail %>%
as.character() %>%
str_split(", ") %>% # almost the same as strsplit, but within a tidyverse package
sapply(length) %>%
max()
关于r - 使用 "1"链接两个数据帧并提取相应的值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49594811/