【问题标题】:Join/merge two dataframes in R by columns with list entries通过具有列表条目的列加入/合并 R 中的两个数据框
【发布时间】:2016-10-08 21:39:14
【问题描述】:

使用数据框时,将list 类型的条目存储在列中有时会很有帮助。我想按该类型的列连接两个数据框。这是两个此类数据框的示例

dfm1 <- structure(list(val1 = 1:5, id = list(c(0.4, 0.5), c(0.4, 0.5), c(0.1, 0.5), 0.4, 0.4)), .Names = c("val1", "id"), row.names = c(NA, -5L), class = "data.frame")

dfm2 <- structure(list(val2 = 7:9, id = list(c(0.4, 0.5), c(0.1, 0.5), 0.4)), .Names = c("val2", "id"), row.names = c(NA, -3L), class = "data.frame")

我想通过名为id 的列合并/加入它们,其中包含list 条目。在这种情况下,每个list 都包含一个vector(但它可以包含一个模型对象或任何东西,因为列表非常灵活)。例如,

> dfm2$id[1]
[[1]]
[1] 0.4 0.5
> class(dfm2$id[1][[1]])
[1] "numeric"
> is.vector(dfm2$id[1][[1]])
[1] TRUE

我想不出如何将id 列连接在一起,以使来自dfm1val1 和来自dfm2val2 位于同一个data.frame 中。当我尝试使用 dplyr 时,我得到:

dplyr::left_join(dfm1, dfm2, by = "id")

错误:无法加入列“id”x“id”:由于类型不兼容(列表/列表),无法加入“id”x“id”

我也没有使用data.table 包:

 dt1 <- as.data.table(dfm1)
 dt2 <- as.data.table(dfm2)

 dt1[dt2, on = "id"]

forderv(x, by = rightcols) 中的错误: 排序的第一列是“列表”类型,尚不支持

这是我想要的输出:

desired_dfm <- structure(list(val1 = 1:5, id = list(c(0.4, 0.5), c(0.4, 0.5), c(0.1, 0.5), 0.4, 0.4), val2 = c(7, 7, 8, 9, 9)), .Names = c("val1", "id", "val2"), row.names = c(NA, -5L), class = "data.frame")

> desired_dfm
  val1       id val2
1    1 0.4, 0.5    7
2    2 0.4, 0.5    7
3    3 0.1, 0.5    8
4    4      0.4    9
5    5      0.4    9

感谢您的帮助!如果您对“使用一列列表条目很愚蠢 - 避免这样做并改用 XXX”有任何建议,当然,这可能会有所帮助,但我也在寻找这个问题的答案正如我设置的那样:-)

edit 我将dfm2$id[3] 中的条目从c(0.1,0.2) 更改为c(0.1,0.5)

澄清编辑 评论指出,可以将这个id 变量分散到两列中,然后加入它们。我同意这是可能的,但这是一个简单的示例,在更复杂的情况下,这种方法可能不起作用。

【问题讨论】:

  • 也许left_join(tidyr::unnest(dfm1), tidyr::unnest(dfm2)) ?
  • 想展示你想要的输出吗?
  • 使用多列而不是全部放在一个列表中。
  • @Abdou 是的;好主意。我编辑了它,它应该很快就会出现。
  • @BarkleyBG,答案对您有帮助吗?否则,您能否添加评论以说明如何改进?

标签: r join merge data.table dplyr


【解决方案1】:

以下是获得所需输出的一种非常基本且没有灵感的方法。仅当您的 listsfloatsintegersstring 字符时,它才有效。但我认为它会帮助您入门:

数据

dfm1 <- structure(list(val1 = 1:5, id = list(c(0.4, 0.5), c(0.4, 0.5), c(0.1, 0.5), 0.4, 0.4)), .Names = c("val1", "id"), row.names = c(NA, -5L), class = "data.frame")

dfm2 <- structure(list(val2 = 7:9, id = list(c(0.4, 0.5), c(0.1, 0.5), 0.4)), .Names = c("val2", "id"), row.names = c(NA, -3L), class = "data.frame")

流程

library(magrittr)

#You need to create new columns of the same name for both of your datasets

dfm1$newcol <- do.call('rbind',lapply(dfm1$id,function(x) paste(x,sep="",collapse="")))

dfm2$newcol <- do.call('rbind',lapply(dfm2$id,function(x) paste(x,sep="",collapse="")))

这里的想法是为您的id 列创建代理并使用这些代理来合并数据集。这里的代理是通过concatenating(或pasting一起)id列中每一行的元素获得的。

#Merge the datasets by 'newcol' and select the needed columns

merged_df <- merge(dfm1, dfm2, by = "newcol", sort=F) %>% subset(.,select=c("val1","id.x","val2"))


merged_df

 val1     id.x val2
    1 0.4, 0.5    7
    2 0.4, 0.5    7
    3 0.1, 0.5    8
    4      0.4    9
    5      0.4    9

如果需要,您可以将 id.x 列重命名为 id 以反映您的原始数据框。

另外,根据str 函数,输出的数据帧仍然有id.x 类型list

str(merged_df)
'data.frame':   4 obs. of  3 variables:
 $ val1: int  1 2 4 5
 $ id.x:List of 4
  ..$ : num  0.4 0.5
  ..$ : num  0.4 0.5
  ..$ : num 0.4
  ..$ : num 0.4
 $ val2: int  7 7 9 9

我希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 2014-10-10
    • 2018-05-20
    • 1970-01-01
    • 2015-07-20
    • 1970-01-01
    • 2018-01-09
    • 2012-11-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多