首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >合并,合并:如何更好地合并?

合并,合并:如何更好地合并?
EN

Stack Overflow用户
提问于 2016-03-06 18:08:52
回答 2查看 3.7K关注 0票数 1

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

代码语言:javascript
复制
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个国家。每个城市将有4个国家。

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

代码语言:javascript
复制
seed(1234) 
cbind(city=1,id=sample(1:10,6),obs=rnorm(6))

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

代码语言:javascript
复制
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

但是,如果我运行这个,循环将显示如下警告:

代码语言:javascript
复制
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 df合并成一个漂亮而又长的专栏?看来cbind merge 都不是要走的路。

如果有50个citydata (每个都有6行),我可以将它们作为一个长数据使用,并按照Philip和Jaap的建议使用data.table方法或expand.gird+merge方法。

我想知道是否可以通过一个的循环来合并每个城市数据,而不是rbind,然后将它们合并到df中。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2016-03-06 18:16:32

data.table对此很有好处:

代码语言:javascript
复制
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在此上下文中的意思是“这个表的#行”。

代码语言:javascript
复制
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中的键列查找行,然后通过在citydata中查找值在df中定义obs。因此,生成的对象是原始的df,但是在citydata中定义的任何地方都定义了obs

代码语言:javascript
复制
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
票数 4
EN

Stack Overflow用户

发布于 2016-03-06 18:30:29

在基本R中,您可以使用expand.gridmerge的组合来实现这一点。

代码语言:javascript
复制
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)

这意味着:

代码语言:javascript
复制
> 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

与dplyr和tidyr类似的方法

代码语言:javascript
复制
library(dplyr)
library(tidyr)

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

这意味着:

代码语言:javascript
复制
> 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
..   ...   ...        ...
票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/35830532

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档