【问题标题】:Sum up two dataframes partly部分总结两个数据框
【发布时间】:2019-01-30 15:38:15
【问题描述】:

我有两个数据框。对于 df1 的某些行,df2 中有匹配的行。现在应该对 df1 的某些列进行操作,以便它们包含它们自己的值与 df2 中的等效值之和。

在以下示例中,列 'count1' 和 'count2' 应该相加,而不是列 'type'。

df1 <- data.frame(id = c("one_a", "two_a", "three_a", "four_a"), type = c(8,7,6,5), count1 = c(1,2,1,NA), count2 = c(NA,0,1,0), id_df2 = c("one", "two", "three", "four"))
df2 <- data.frame(id = c("one", "two", "four"), type = c(8,7,5), count1 = c(0,1,1), count2 = c(0,0,1))
result <- data.frame(id = c("one_a", "two_a", "three_a", "four_a"), type = c(8,7,6,5), count1 = c(1,3,1,1), count2 = c(0,0,1,1))

> df1
       id type count1 count2 id_df2
1   one_a    8      1     NA     one
2   two_a    7      2      0     two
3 three_a    6      1      1   three
4  four_a    5     NA      0    four

> df2
    id type count1 count2
1  one    8      0      0
2  two    7      1      0
3 four    5      1      1

> result
       id type count1 count2
1   one_a    8      1      0
2   two_a    7      3      0
3 three_a    6      1      1
4  four_a    5      1      1

有类似的问题,我试图通过将数据框分开并在之后合并它们来找到解决方案。我只是想知道是否有更优雅的方式来做到这一点。我的原始数据集大约有 300 列,因此我正在寻找可扩展的解决方案。

提前致谢 查克莫里斯

【问题讨论】:

    标签: r


    【解决方案1】:

    你可以这样做:

    library(dplyr)
    
    df1 %>% select(-id_df2) %>%
      bind_rows(df2) %>%
      mutate(id = gsub("_.*", "", id)) %>%
      replace(., is.na(.), 0) %>%
      group_by(id, type) %>%
      summarise_at(vars(contains("count")), funs(sum))
    

    输出在哪里:

    # A tibble: 4 x 4
    # Groups:   id [?]
      id     type count1 count2
      <chr> <dbl>  <dbl>  <dbl>
    1 four      5      1      1
    2 one       8      1      0
    3 three     6      1      1
    4 two       7      3      0
    

    还有:

    df1 %>% select(-id_df2) %>%
      bind_rows(df2) %>%
      mutate(id = ifelse(grepl("_", id), id, paste0(id, "_a"))) %>%
      replace(., is.na(.), 0) %>%
      group_by(id, type) %>%
      summarise_at(vars(contains("count")), funs(sum))
    

    如果您有兴趣保留 _a 部分。

    另一种方法是使用连接,转换为长,然后向后传播,例如:

    library(tidyverse)
    
    df1 %>% 
      left_join(df2, by = c("id_df2" = "id")) %>%
      gather(var, val, -id) %>%
      mutate(var = gsub("\\..*", "", var)) %>%
      distinct(id, var, val) %>%
      filter(!var == "id_df2") %>%
      group_by(id, var) %>%
      summarise(val = sum(as.numeric(val), na.rm = T)) %>%
      spread(var, val) 
    

    给予:

    # A tibble: 4 x 4
    # Groups:   id [4]
      id      count1 count2  type
      <fct>    <dbl>  <dbl> <dbl>
    1 four_a       1      1     5
    2 one_a        1      0     8
    3 three_a      1      1     6
    4 two_a        3      0     7
    

    如果_a 结尾有特殊目的,这可能会很有趣,例如还有_b_c等的组(在这种情况下上述方法会失败)。

    【讨论】:

    • 我可以使用“id_df2”列以某种方式做到这一点吗? - 原始数据集上的某些“类型”列在 df1 和 df2 中包含不同的值 -“id”字段最初看起来像“thr_a_ee”
    • 看帖子的结尾,已经添加了一种可能的方法。
    【解决方案2】:

    稍微不那么优雅,但仍然有效:

    result_2 <- df2 %>% 
      mutate(id = paste0(id, "_a")) %>%
      bind_rows(df1) %>% 
      select(-id_df2) %>% 
      replace(., is.na(.), 0) %>%
      group_by(id) %>% 
      summarise(count1 = sum(count1), count2 = sum(count2), type = max(type)) %>% 
      mutate(id_df2 = as.factor(id)) %>% 
      select(c(id_df2, type, count1, count2), -id)
    

    【讨论】:

      猜你喜欢
      • 2016-08-15
      • 1970-01-01
      • 2021-11-28
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多