r - 使用 "1"链接两个数据帧并提取相应的值

标签 r dataframe

我有两个大数据框,我使用“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/

相关文章:

python - Pandas 截断不完整的时间序列

R 中的正则表达式 - 以 "OR"方式组合两种模式。无法发现错误。

r - 使用 rollmean 计算不包括 R 中第一个观察值的移动平均值

python - Pandas 数据框中多列的聚合

在 R 中按所需顺序重新排列数据框的列

python - 过滤一个 Excel 工作表中的数据框并导出到另一个 Excel 工作表

python - 如果值是第一次出现并且最近一年出现在 Pandas 中,如何创建 0 或 1

r - 使用ggplot2,如何从值中获取颜色?

java - 服务器端的R计算

r - 当我指定的列中所有单元格都有 NA 时,如何删除 NA?