【问题标题】:Merge df1, df2, df3 dataframes in R on a specified column在指定列上合并 R 中的 df1、df2、df3 数据帧
【发布时间】:2013-12-20 09:52:40
【问题描述】:

在 R 中,我有代表闪电风暴的 df1、df2 和 df3。每个 df 有两列,“city”和“injuries”。

df1 = data.frame(city=c("atlanta", "new york"), injuries=c(5,8))
df2 = data.frame(city=c("chicago", "new york"), injuries=c(2,3))
df3 = data.frame(city=c("los angeles", "atlanta"), injuries=c(1,7))

我想在城市列的一种外连接上合并所有 3 个数据框,以便所有城市都显示在合并的数据框中,并且伤害计数将按如下方式求和:

combined.df

city         df1.freq   df2.freq   df3.freq
atlanta      5          0          7
new york     8          3          0
chicago      0          2          0
los angeles  0          0          1

【问题讨论】:

  • 您可能需要更新您的问题以表明您正在寻找适用于 8 个数据帧的解决方案。

标签: r join merge outer-join


【解决方案1】:

这是我使用reshape::cast 的解决方案(感谢@thelatemail!)。将id变量添加到每个数据框,行绑定它们然后转换为宽格式:

df1$id <- 'df1.freq'
df2$id <- 'df2.freq'
df3$id <- 'df3.freq'

rb <- rbind(df1,df2,df3)
library(reshape)
cast(rb, city ~ id, value='injuries')

结果:

         city df1.freq df2.freq df3.freq
1     atlanta        5       NA        7
2    new york        8        3       NA
3     chicago       NA        2       NA
4 los angeles       NA       NA        1

【讨论】:

  • reshape 库在这种情况下,而不是 R 中包含的 reshape 函数。
  • 糟糕,看来我应该在提交之前刷新页面...大家辛苦了!
  • 我的意思是包,而不是库。我很惊讶我还没有被闪电击中。
【解决方案2】:

使用基本 R reshape 函数替代 @flodel 的版本:

dat <- list(df1,df2,df3)
intm <- data.frame(do.call(rbind,dat),val=rep(seq_along(dat),sapply(dat,nrow)))
reshape(intm, idvar="city", timevar="val", direction="wide")

#         city injuries.1 injuries.2 injuries.3
#1     atlanta          5         NA          7
#2    new york          8          3         NA
#3     chicago         NA          2         NA
#5 los angeles         NA         NA          1

【讨论】:

    【解决方案3】:

    这对于任意数量的 data.frames 都是通用的:

    library(functional)
    Reduce(Curry(merge, by = "city", all = TRUE), list(df1, df2, df3))
    #          city injuries.x injuries.y injuries
    # 1     atlanta          5         NA        7
    # 2    new york          8          3       NA
    # 3     chicago         NA          2       NA
    # 4 los angeles         NA         NA        1
    

    但是,多次合并可能会很慢。另一种方法是将你的 data.frames 堆叠成一个长的:

    df.long <- do.call(rbind, Map(transform, list(df1, df2, df3),
                                             name = c("df1", "df2", "df3")))
    #          city injuries name
    # 1     atlanta        5  df1
    # 2    new york        8  df1
    # 3     chicago        2  df2
    # 4    new york        3  df2
    # 5 los angeles        1  df3
    # 6     atlanta        7  df3
    

    然后使用 xtabs 重塑该数据,例如:

    xtabs(injuries ~ city + name, df.long)
    #              name
    # city          df1 df2 df3
    #   atlanta       5   0   7
    #   new york      8   3   0
    #   chicago       0   2   0
    #   los angeles   0   0   1
    

    reshape 函数可能对最后一步也有用,但我对它不是很熟悉。)

    【讨论】:

    • 出于某种原因相同的情况 - 适用于三个,但对于 4+ data.frames 给出以下错误: match.names(clabs, names(xi)) 中的错误:名称与以前的名称不匹配
    • 可能与具有相同“injuries”列名的所有 data.frames 相关。不值得修复,我看到你有很多不使用 merge 的好替代品。
    【解决方案4】:

    merge 是你的朋友。输入?merge了解更多详情。

    > merge(merge(df1, df2, by = "city", all = TRUE), df3, by = "city", all = TRUE)
             city injuries.x injuries.y injuries
    1     atlanta          5         NA        7
    2     chicago         NA          2       NA
    3 los angeles         NA         NA        1
    4    new york          8          3       NA
    

    编辑。虽然我喜欢@flodel 的解决方案,但这里有一个更直接的解决方案,可能更容易理解:

     Reduce(function(d1, d2) merge(d1, d2, all = TRUE, by = "city"), list(df1, df2, df3))
    

    【讨论】:

    • 好吧,我撒了谎。我需要合并 8 个这样的数据帧,虽然这种方法适用于三个,但它似乎不适用于四个 df...
    • 见下面@flodel 的解决方案。
    • 出于某种原因相同的情况 - 适用于三个,但对于 4+ data.frames 给出以下错误: match.names(clabs, names(xi)) 中的错误:名称与以前的名称不匹配
    • 您确定您的数据框具有相同的名称?
    猜你喜欢
    • 1970-01-01
    • 2021-04-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-17
    • 1970-01-01
    • 2021-06-21
    • 2014-12-20
    相关资源
    最近更新 更多