【问题标题】:Merge, cbind: How to merge better? [duplicate]合并,cbind:如何更好地合并? [复制]
【发布时间】:2016-03-06 18:08:52
【问题描述】:

我想将多个向量合并到一个数据框中。有两个变量 cityid 将用于将向量与数据框匹配。

df <- data.frame(array(NA, dim =c(10*50, 2)))
names(df)<-c("city", "id")
df[,1]<-rep(1:50, each=10)
df[,2]<-rep(1:10, 50)

我创建了一个这样的数据框。对于这个数据框,我想合并 50 个向量,每个向量对应 50 个城市。问题是每个城市只有6个obs。每个城市将有 4 个 NA。

举个例子,城市 1 的数据如下所示:

seed(1234) 
cbind(city=1,id=sample(1:10,6),obs=rnorm(6))

我有 50 个城市数据,我想将它们合并到 df 中的一列。我试过以下代码:

for(i in 1:50){
citydata<-cbind(city=i,id=sample(1:10,6),obs=rnorm(6))   # each city data
df<-merge(df,citydata, by=c("city", "id"), all=TRUE)}    # merge to df

但如果我运行它,循环会显示如下警告:

In merge.data.frame(df, citydata, by = c("city", "id"),  ... :
  column names ‘obs.x’, ‘obs.y’ are duplicated in the result

它将创建 50 列,而不是一长列。

如何将cbind(city=i,id=sample(1:10,6),obs=rnorm(6))df 合并到一个又好又长的列中?看来cbindmerge 都不是办法。


如果有 50 个 citydata(每个有 6 行),我可以将 rbind 作为一个长数据并使用 data.table 方法或 expand.gird+merge 方法作为 PhilipJaap 建议。

我想知道我是否可以通过一个循环将每个citydata一个一个地合并,而不是rbind他们合并到df

【问题讨论】:

    标签: r merge cbind


    【解决方案1】:

    data.table 很适合这个:

    library(data.table)
    df <- data.table(df)
    > df
         city id
      1:    1  1
      2:    1  2
      3:    1  3
      4:    1  4
      5:    1  5
     ---
    496:   50  6
    497:   50  7
    498:   50  8
    499:   50  9
    500:   50 10
    

    我正在使用 CJ 而不是你的 for 循环来制作一些虚拟数据。 CJ 将每一列与其他列的每个值交叉连接,因此它创建了一个包含cityid 的每对可能值对的两列表。 [,obs:=rnorm(.N)] 命令添加了第三列,该列绘制随机值(不会像在CJ 中那样回收它们)--.N 在此上下文中表示“此表的# 行”。

    citydata <- CJ(city=1:50,id=1:6)[,obs:=rnorm(.N)]
    > citydata
         city id         obs
      1:    1  1  0.19168335
      2:    1  2  0.35753229
      3:    1  3  1.35707865
      4:    1  4  1.91871907
      5:    1  5 -0.56961647
     ---
    296:   50  2  0.30592659
    297:   50  3 -0.44989646
    298:   50  4  0.05359738
    299:   50  5 -0.57494269
    300:   50  6  0.09565473
    
    setkey(df,city,id)
    setkey(citydata,city,id)
    

    由于这两个表具有相同的键列,以下通过citydata 中的键列查找df 的行,然后通过查找citydata 中的值在df 中定义obs。因此,生成的对象是原始的 df,但在 citydata 中定义的任何地方都定义了 obs

    df[citydata,obs:=i.obs]
    > df
         city id         obs
      1:    1  1  0.19168335
      2:    1  2  0.35753229
      3:    1  3  1.35707865
      4:    1  4  1.91871907
      5:    1  5 -0.56961647
     ---
    496:   50  6  0.09565473
    497:   50  7          NA
    498:   50  8          NA
    499:   50  9          NA
    500:   50 10          NA
    

    【讨论】:

    • 或一气呵成:setDT(df)[CJ(city=1:50,id=1:6)[,obs:=rnorm(.N)], obs:=i.obs, on = c("city","id")][]
    • 不错的一个。 (但我也猜测 OP 已经存在真实的城市数据,因此连接表的创建更多是为了展示合并的工作原理,而不是作为实际解决方案工作流程的一部分。)
    • 谢谢。看看这个问题,我认为citydata 很可能是已经存在的数据,df 必须用CJ 构造才能获得所需的结果。
    【解决方案2】:

    在基础 R 中,您可以结合使用 expand.gridmerge

    citydata <- expand.grid(city=1:50,id=1:6)
    citydata$obs <- rnorm(nrow(citydata))
    
    res <- merge(df, citydata, by = c("city","id"), all.x = TRUE)
    

    给出:

    > head(res,12)
        city id        obs
     1:    1  1 -0.3121133
     2:    1  2 -1.3554576
     3:    1  3 -0.9056468
     4:    1  4 -0.6511869
     5:    1  5 -1.0447499
     6:    1  6  1.5939187
     7:    1  7         NA
     8:    1  8         NA
     9:    1  9         NA
    10:    1 10         NA
    11:    2  1  0.5423479
    12:    2  2 -2.3663335
    

    dplyrtidyr 的类似方法:

    library(dplyr)
    library(tidyr)
    
    res <- crossing(city=1:50,id=1:6) %>% 
      mutate(obs = rnorm(n())) %>%
      right_join(., df, by = c("city","id"))
    

    给出:

    > res
    Source: local data frame [500 x 3]
    
        city    id        obs
       (int) (int)      (dbl)
    1      1     1 -0.5335660
    2      1     2  1.0582001
    3      1     3 -1.3888310
    4      1     4  1.8519262
    5      1     5 -0.9971686
    6      1     6  1.3508046
    7      1     7         NA
    8      1     8         NA
    9      1     9         NA
    10     1    10         NA
    ..   ...   ...        ...
    

    【讨论】:

      猜你喜欢
      • 2019-01-24
      • 2011-02-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多