【问题标题】:How do I conditionally combine some rows (but not others) in R data frames?如何有条件地组合 R 数据框中的某些行(但不是其他行)?
【发布时间】:2021-05-22 01:27:55
【问题描述】:

我试图弄清楚如何合并/连接两个数据帧,如果满足某个条件,R 将两个数据帧中的两行合并为一行,但如果条件不满足, R 在原始数据框中不存在的列中添加一个新行,其中包含 NA。我不清楚这是否比我想象的更简单,但我一直无法弄清楚如何做到这一点,即使在阅读了一些堆栈溢出结果(e.g.e.g.)之后。

以下是两个示例数据框:

df1 <- data.frame(Name_df1 = c("Alan", "Steve", "Melanie", "Steve", "Melanie"),
                  Date_df1 = c("02/18/2008", "02/18/2008", "03/14/2009", "04/19/2009", "03/16/2009"),
                  Job_df1 = c("Cook", "Security", "Greeter", "Security", "Greeter"),
                  Hours_df1 = c(8.5, 7.0, 6.0, 7.0, 6.0))

df2 <- data.frame(Name_df2 = c("Steve", "Alan", "Melanie", "Melanie", "Steve", "Carter"),
                  Date_df2 = c("02/18/2008", "02/18/2008", "03/14/2009", "03/17/2009","04/25/2009", "08/15/2011"),
                  Job_df2 = c("Police", "Chef", "Greeter", "Greeter", "Security", "Doorman"),
                  Hours_df2 = c(8.5, 7.0, 6.0, 7.0, 7.0, 6.5),
                  Wage_df2 = c(80, 77, 127.5, 90, 145, 100))

df1 和 df2 都描述了某些个人的工作日期、他们的职位、姓名和在指定日期的工作时间, df2 还包含工资信息。我想要做的是将 df1 和 df2 加入到具有以下列的 df3 中:

  • “Name_df1”
  • “名称_df2”
  • “日期_df1”
  • “日期_df2”
  • “Job_df1”
  • “Job_df2”
  • “Hours_df1”
  • “Hours_df2”
  • “Wage_df2”

具体来说,我想加入 df1 和 df2,这样对于 df1 或 df2 中的每一行,如果 both 与“Name_df1”/“Name_df2”列中的值完全匹配,并且相对数据框中相应列中的“Date_df1”/“Date_df2”列中的值(即在 df1 中,如果“Date_df1”列和“Name_df1”列中的值在“Date_df2”中都具有完全匹配df2) 的列和“Name_df2”列:

  • 在 df3 中创建了一行,其中填充了“Name_df1”、“Name_df2”、“Date_df1”、“Date_df2”、“Job_df1”、“Job_df2”、“Hours_df1”、“Hours_df2”和“Wage”列与来自 d​​f1 和 df2 的相关值。 “Job_df1”、“Job_df2”、“Hours_df1”和“Hours_df2”中的值可能相同,也可能不同。

但是,如果完全匹配both“Name_df1”/“Name_df2”列中的值和“Date_df1”/”中的值Date_df2" 列,然后 df3 应该得到一行,其中仅包含来自“Name_df1”、“Date_df1”、“Job_df1”和“Hours_df1”中的 df1 的信息,以及“Name_df2”、“Date_df2”、“Job_df2”中的 NAs, “Hours_df2”和“Wage_df2”。或者,如果原始行来自 df2,则 df3 应获取仅包含“Name_df2”、“Date_df2”、“Job_df2”、“Hours_df2”和“Wage_df2”中来自 df2 的信息以及“Name_df1”中的 NA 的行"、"Date_df1"、"Job_df1" 和 "Hours_df1"。

我知道这很拗口,但根据上面指定的 df1 和 df2,这就是 df3 的样子:

df3 <- data.frame(Name_df1 = c("Alan", "Steve", "Melanie", "Steve", "Melanie", NA, NA, NA),
                  Name_df2 = c("Alan", "Steve", "Melanie", NA, NA, "Melanie", "Steve", "Carter"),
                  Date_df1 = c("02/18/2008", "02/18/2008", "03/14/2009", "04/19/2009", "03/16/2009", NA, NA, NA),
                  Date_df2 = c("02/18/2008", "02/18/2008", "03/14/2009", NA, NA, "03/17/2009", "04/25/2009", "08/15/2011"),
                  Job_df1 = c("Cook", "Security", "Greeter", "Security", "Greeter", NA, NA, NA),
                  Job_df2 = c("Chef", "Police", "Greeter", NA, NA, "Greeter", "Security", "Doorman"),
                  Hours_df1 = c(7.0, 7.0, 6.0, 7.0, 6.0, NA, NA, NA),
                  Hours_df2 = c(7.0, 8.5, 6.0, NA, NA, 7.0, 7.0, 6.5),
                  Wage_df2 = c(77.0, 80, 127.5, NA, NA, 90.0, 145.0, 100))

谁能帮我解决这个问题?

【问题讨论】:

  • '我如何有条件地组合一些行(但不是其他行)'你没有。交叉连接给出每个表中一行的所有组合,然后保留满足条件的组合。了解加入的基础知识。
  • 我知道交叉连接,只是不确定这些特定条件的过滤会是什么样子

标签: r join dplyr merge conditional-statements


【解决方案1】:

您似乎正在寻找full_join,但要获得所需的确切输出 (df3),您需要执行一些操作。

library(dplyr)

full_join(df1, df2, by = c('Name_df1' = 'Name_df2', 'Date_df1' = 'Date_df2')) %>%
  mutate(Name_df2 = ifelse(is.na(Job_df2), NA, Name_df1),
         Name_df1 = ifelse(is.na(Job_df1), NA, Name_df1), 
         Date_df2 = ifelse(is.na(Job_df2), NA, Date_df1),
         Date_df1 = ifelse(is.na(Job_df1), NA, Date_df1)) %>%
  select(starts_with('Name'), starts_with('Date'), starts_with('Job'), everything())

#  Name_df1 Name_df2   Date_df1   Date_df2  Job_df1  Job_df2 Hours_df1 Hours_df2 Wage_df2
#1     Alan     Alan 02/18/2008 02/18/2008     Cook     Chef       8.5       7.0     77.0
#2    Steve    Steve 02/18/2008 02/18/2008 Security   Police       7.0       8.5     80.0
#3  Melanie  Melanie 03/14/2009 03/14/2009  Greeter  Greeter       6.0       6.0    127.5
#4    Steve     <NA> 04/19/2009       <NA> Security     <NA>       7.0        NA       NA
#5  Melanie     <NA> 03/16/2009       <NA>  Greeter     <NA>       6.0        NA       NA
#6     <NA>  Melanie       <NA> 03/17/2009     <NA>  Greeter        NA       7.0     90.0
#7     <NA>    Steve       <NA> 04/25/2009     <NA> Security        NA       7.0    145.0
#8     <NA>   Carter       <NA> 08/15/2011     <NA>  Doorman        NA       6.5    100.0

【讨论】:

  • 谢谢,这与我正在寻找的非常接近。但是,当名称和日期对同时出现在 df1 和 df2 中时,我希望将 Name_df1 和 Name_df2 以及 Date_df1 和 Date_df2 列全部填充到 df3 中。因此,在您的代码结果中,我希望第 1 行中的 Name_df2 说“Alan”,第 1 行中的 Date_df2 说“2/18/2008”。这同样适用于第 2 行和第 3 行(Steve 和 Melanie 的日期分别为 2008 年 2 月 18 日和 2009 年 3 月 14 日),因为这些对在 df1 和 df2 中的日期和名称列中匹配。你知道我是怎么做到的吗?
  • 是的,你是对的。这需要答案的微小变化。查看我的更新答案@ben_p_4370
  • 这是完美的,谢谢。您知道如何阻止 ifelse 将日期转换为数字(例如 17266)吗?
  • if_else代替ifelse
  • 完美。感谢您的帮助
【解决方案2】:

也许这可能是连接这两个数据框的一种方式:

库(dplyr) df3 % full_join(df2, by="Name", suffix= c(".df1", ".df2"))

结果:

Table

【讨论】:

    【解决方案3】:

    我认为您希望完全加入 keep = TRUE

    library(dplyr)
    full_join(df1, df2, by = c(Name_df1 = "Name_df2", Date_df1 = "Date_df2"), keep = TRUE)
    #>   Name_df1   Date_df1  Job_df1 Hours_df1 Name_df2   Date_df2  Job_df2 Hours_df2
    #> 1     Alan 02/18/2008     Cook       8.5     Alan 02/18/2008     Chef       7.0
    #> 2    Steve 02/18/2008 Security       7.0    Steve 02/18/2008   Police       8.5
    #> 3  Melanie 03/14/2009  Greeter       6.0  Melanie 03/14/2009  Greeter       6.0
    #> 4    Steve 04/19/2009 Security       7.0     <NA>       <NA>     <NA>        NA
    #> 5  Melanie 03/16/2009  Greeter       6.0     <NA>       <NA>     <NA>        NA
    #> 6     <NA>       <NA>     <NA>        NA  Melanie 03/17/2009  Greeter       7.0
    #> 7     <NA>       <NA>     <NA>        NA    Steve 04/25/2009 Security       7.0
    #> 8     <NA>       <NA>     <NA>        NA   Carter 08/15/2011  Doorman       6.5
    #>   Wage_df2
    #> 1     77.0
    #> 2     80.0
    #> 3    127.5
    #> 4       NA
    #> 5       NA
    #> 6     90.0
    #> 7    145.0
    #> 8    100.0
    

    reprex package (v2.0.1) 于 2022-01-17 创建

    【讨论】:

      猜你喜欢
      • 2021-11-28
      • 2015-05-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-07-16
      • 2020-08-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多