将列表中的数据框相互合并

5

我需要的:

我有一个非常大的数据框,其中包含以下列(还有一些其他列,但这些不重要)。以下是一个示例:

    user_id video_id group_id    x   y
1         1        0        0   39 108
2         1        0        0   39 108
3         1       10        0  135 180
4         2        0        0   20 123

当然,用户、视频和组ID是重要因素。例如,有20个视频,但每个视频都有每个用户和组的多个“观察结果”。

我想将此数据框转换为以下格式,其中有与用户数量(N)相同数量的x.Ny.N

video_id  x.1   y.1  x.2  y.2  …
       0   39   108   20  123

因此,对于视频0,用户1的x和y值分别在列x.1y.1中。对于用户2,他们的值在列x.2y.2等中。

我尝试过的方法:

我制作了一个数据框列表,该列表仅由每个video_id的所有x,y观察值组成:

summaryList = dlply(allData, .(user_id), function(x) unique(x[c("video_id","x","y")]) )

这就是它的外观:

List of 15
 $ 1 :'data.frame': 20 obs. of  3 variables:
  ..$ video_id: Factor w/ 20 levels "0","1","2","3",..: 1 11 8 5 12 9 20 13 7 10 ...
  ..$ x       : int [1:20] 39 135 86 122 28 167 203 433 549 490 ...
  ..$ y       : int [1:20] 108 180 164 103 187 128 185 355 360 368 ...
 $ 2 :'data.frame': 20 obs. of  3 variables:
  ..$ video_id: Factor w/ 20 levels "0","1","2","3",..: 2 14 15 4 20 6 19 3 13 18 ...
  ..$ x       : int [1:20] 128 688 435 218 528 362 299 134 83 417 ...
  ..$ y       : int [1:20] 165 117 135 179 96 328 332 563 623 476 ...

我遇到的问题:

还需要完成的任务包括:

  • Merge each data frame from the summaryList with each other, based on the video_id. I can't find a nice way to access the actual data frames in the list, which are summaryList[1]$`1`, summaryList[2]$`2`, et cetera.

    @James found out a partial solution:

    Reduce(function(x,y) merge(x,y,by="video_id"),summaryList)
    
  • Ensure the column names are renamed after the user ID and not kept as-is. Right now my summaryList doesn't contain any info about the user ID, and the output of Reduce has duplicate column names like x.x y.x x.y y.y x.x y.x and so on.

我该如何开始实现这个?或者有没有比我当前做法更简单的方法获得结果?

1
你能提供数据的子集吗?我在想 Reduce(function(x,y) merge(x,y,by="video_id"),summaryList) 可能会起作用。 - James
1
你能提供一个(简化的)输入数据框的例子和期望的输出吗?我很难理解你想做什么。 - Roland
@Roland 我添加了一个小例子。这是整个数据集,以防万一。 - slhck
@James,那个几乎可以工作,只是列名是video_id x.x y.x x.y y.y x.x y.x等,而不是以用户ID命名的。 - slhck
@slhck 之后尝试使用names(reducedData)[-1] <- do.call(function(...) paste(...,sep="."),expand.grid(letters[24:25],names(summaryList))) - James
@James 完成了这个技巧。随意将您的代码行作为答案发布。 - slhck
2个回答

4

我还是有些困惑。不过,我猜你只是想使用meltdcast

library(reshape2)
d <- melt(allData,id.vars=c("user_id","video_id"), measure.vars=c("x","y"))
dcast(d,video_id~user_id+variable,value.var="value",fun.aggregate=mean)

导致:
 video_id  1_x 1_y  2_x 2_y  3_x 3_y  4_x 4_y  5_x 5_y  6_x 6_y  7_x 7_y  8_x 8_y  9_x 9_y 10_x 10_y 11_x 11_y 12_x 12_y 14_x 14_y 15_x 15_y 16_x 16_y
1         0   39 108  899 132   61 357  149 298 1105 415  148 208  442 200  210 134   58 244  910  403  152   52 1092  617 1012  114 1105  424  548  394
2         1 1125  70  128 165 1151 390  171 587  623 623   80 643  866 310  994 114  854 129  781  306  672   -1 1096  354  525  524  150 

我不得不删除一些额外的列,请查看您的帖子进行编辑,但这也可以正常工作,谢谢!我对reshape有些不熟悉,所以您能否解释一下dcast在这里的作用或为什么它首先创建这些列? - slhck
dcast 简单地将数据从长格式(在统计软件中最常用)转换为宽格式(Excel 用户喜欢的格式)。公式定义了哪些变量成为列标题。melt 是其逆转换。 - Roland

3

Reduce能搞定这个问题:

reducedData <- Reduce(function(x,y) merge(x,y,by="video_id"),summaryList)

...但之后您需要修复names

names(reducedData)[-1] <- do.call(function(...) paste(...,sep="."),expand.grid(letters[24:25],names(summaryList)))

结果是:
   video_id  x.1 y.1  x.2 y.2  x.3 y.3  x.4 y.4  x.5 y.5  x.6 y.6  x.7 y.7  x.8
1         0   39 108  899 132   61 357  149 298 1105 415  148 208  442 200  210
2         1 1125  70  128 165 1151 390  171 587  623 623   80 643  866 310  994

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接