合并,cbind:如何更好地合并?
Merge, cbind: How to merge better?
我想将多个向量合并到一个数据框中。有两个变量 city
和 id
将用于将向量与数据框匹配。
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
一个又好又长的列中?看来cbind
和merge
都不是办法。
如果有 50 个 citydata
(每个有 6 行),我可以 rbind
它们作为一个长数据并使用 data.table
方法或 expand.gird
+merge
Philip 和 Jaap 建议的方法。
我想知道我是否可以通过循环将每个城市数据一个一个地合并,而不是 rbind
它们然后合并到 df
。
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
将每列与其他列的每个值进行交叉连接,因此它使用每对可能的值 city
和 id
构成一个双列 table。 [,obs:=rnorm(.N)]
命令添加了第三列,用于绘制随机值(不会像在 CJ
中那样回收它们)--.N
表示“# rows of this table”在这种情况下。
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)
由于这两个 table 具有相同的键列,因此以下通过 citydata
中的键列查找 df
的行,然后在 obs
中定义 obs
=21=] 通过查找 citydata
中的值。因此,生成的对象是原始的 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
在 base R 中,您可以结合使用 expand.grid
和 merge
:
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
dplyr 和 tidyr 的类似方法:
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
.. ... ... ...
我想将多个向量合并到一个数据框中。有两个变量 city
和 id
将用于将向量与数据框匹配。
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
一个又好又长的列中?看来cbind
和merge
都不是办法。
如果有 50 个 citydata
(每个有 6 行),我可以 rbind
它们作为一个长数据并使用 data.table
方法或 expand.gird
+merge
Philip 和 Jaap 建议的方法。
我想知道我是否可以通过循环将每个城市数据一个一个地合并,而不是 rbind
它们然后合并到 df
。
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
将每列与其他列的每个值进行交叉连接,因此它使用每对可能的值 city
和 id
构成一个双列 table。 [,obs:=rnorm(.N)]
命令添加了第三列,用于绘制随机值(不会像在 CJ
中那样回收它们)--.N
表示“# rows of this table”在这种情况下。
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)
由于这两个 table 具有相同的键列,因此以下通过 citydata
中的键列查找 df
的行,然后在 obs
中定义 obs
=21=] 通过查找 citydata
中的值。因此,生成的对象是原始的 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
在 base R 中,您可以结合使用 expand.grid
和 merge
:
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
dplyr 和 tidyr 的类似方法:
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
.. ... ... ...