R代码:根据一个数据的一列和另一个数据的一个变量名称中的信息合并两个数据

时间:2014-12-22 03:24:53

标签: r merge dataframe reshape

我有一个庞大的数据集,但要问我的问题,我创建简化的数据..

我想根据一个数据的一列信息和其他数据的变量名称合并两个不同的数据库。

  d1 <- data.frame(subject = c(1,1,1,1,1,1,2,2,2,2,2,2),stime=c('4/16/2012','4/17/2012','4/18/2012','4/19/2012','4/20/2012','4/21/2012','4/16/2012','4/17/2012','4/18/2012','4/19/2012','4/20/2012','4/21/2012'))
  d2 <- data.frame(x1 = c(11.5,12.3,22,34,25,35),x2=c(4,16,23,25,33,45),stime=c('4/16/2012','4/17/2012','4/18/2012','4/19/2012','4/20/2012','4/21/2012'))


> d1
   subject     stime
1        1 4/16/2012
2        1 4/17/2012
3        1 4/18/2012
4        1 4/19/2012
5        1 4/20/2012
6        1 4/21/2012
7        2 4/16/2012
8        2 4/17/2012
9        2 4/18/2012
10       2 4/19/2012
11       2 4/20/2012
12       2 4/21/2012

> d2
    x1 x2     stime
1 11.5  4 4/16/2012
2 12.3 16 4/17/2012
3 22.0 23 4/18/2012
4 34.0 25 4/19/2012
5 25.0 33 4/20/2012
6 35.0 45 4/21/2012

基本上,我想创建这样的数据.. 这意味着我想基于d2的变量名称合并这些数据,例如x1,x2和来自d1的“主题”的信息。 可能吗?请帮帮我..非常感谢你!

   subject     stime Variable
1        1 4/16/2012  11.5
2        1 4/17/2012  12.3 
3        1 4/18/2012  22.0
4        1 4/19/2012  34.0
5        1 4/20/2012  25.0
6        1 4/21/2012  35.0
7        2 4/16/2012  4
8        2 4/17/2012  16
9        2 4/18/2012  23
10       2 4/19/2012  25
11       2 4/20/2012  33
12       2 4/21/2012  45

4 个答案:

答案 0 :(得分:4)

到目前为止,所有答案都以某种方式将d2转换为长格式然后执行合并。这导致为(中间)熔融数据分配内存,并再次为最终merge/join分配内存。既然你提到巨大的数据(但没有提到维度),我假设优化速度 内存是最理想的。

以下是:

require(data.table) ## 1.9.4+
setkey(setDT(d2), stime)
setDT(d1)
get_cols = function(d1_subject, d1_time) {
    d2[J(d1_time), list(stime, var = if (d1_subject==1) x1 else x2)]
}
d1[, get_cols(subject, stime), by=subject]
#     subject     stime  var
#  1:       1 4/16/2012 11.5
#  2:       1 4/17/2012 12.3
#  3:       1 4/18/2012 22.0
#  4:       1 4/19/2012 34.0
#  5:       1 4/20/2012 25.0
#  6:       1 4/21/2012 35.0
#  7:       2 4/16/2012  4.0
#  8:       2 4/17/2012 16.0
#  9:       2 4/18/2012 23.0
# 10:       2 4/19/2012 25.0
# 11:       2 4/20/2012 33.0
# 12:       2 4/21/2012 45.0

我们首先使用setDT()函数将data.frames转换为data.tables。然后我们 d2的关键列设置为stime按行按顺序对 d2进行排序,并标记为列为键列,我们将在下一步中加入。

在下一步中,我们首先按d1分组subject,为每个分组分组,我们调用get_cols函数subject来自stime的{​​和d1值与 组相对应。对于每个群组,我们使用与d2对应的stime对应的值d1_timed1$stime的关键列subject上执行加入 {1}}我们根据x1提取列x2subject == 1 or 2

这里,来自melt的中间结果从未实现,因此内存效率很高,并且使用二进制搜索快速连接。

答案 1 :(得分:3)

使用tidyrdplyr

来自@docendodiscimus关于更惯用解决方案的建议

library(tidyr)
library(dplyr)

gather(d2, subject, value, x1:x2) %>% 
  mutate(subject = as.numeric(gsub("^x", "", subject))) %>%
  inner_join(., d1)

#Joining by: c("stime", "subject")
#       stime subject value
#1  4/16/2012       1  11.5
#2  4/17/2012       1  12.3
#3  4/18/2012       1  22.0
#4  4/19/2012       1  34.0
#5  4/20/2012       1  25.0
#6  4/21/2012       1  35.0
#7  4/16/2012       2   4.0
#8  4/17/2012       2  16.0
#9  4/18/2012       2  23.0
#10 4/19/2012       2  25.0
#11 4/20/2012       2  33.0
#12 4/21/2012       2  45.0

答案 2 :(得分:2)

你正在做的事情是融合和融合的结合。真的只是融化d2似乎回归你想要的

library(reshape2)
melt(d2)

当然你会得到专栏&#34;变量&#34;子集名称与&#34; x&#34;结合使用。但您可以将其他ID转换为包含&#34; x&#34;然后合并

mm <- merge(transform(d1, variable=paste0("x",subject)), melt(d2))
mm

#        stime variable subject value
# 1  4/16/2012       x1       1  11.5
# 2  4/16/2012       x2       2   4.0
# 3  4/17/2012       x1       1  12.3
# 4  4/17/2012       x2       2  16.0
# 5  4/18/2012       x1       1  22.0
# 6  4/18/2012       x2       2  23.0
# 7  4/19/2012       x1       1  34.0
# 8  4/19/2012       x2       2  25.0
# 9  4/20/2012       x1       1  25.0
# 10 4/20/2012       x2       2  33.0
# 11 4/21/2012       x1       1  35.0
# 12 4/21/2012       x2       2  45.0

如果你想借助并删除额外的列,你可以

subset(mm[order(mm$subject),], select=-variable)

答案 3 :(得分:1)

使用meltmerge的组合可以实现所需的结果。

library(reshape)
colnames(d2)<-c("1","2","stime") #change the column names from "x1","x2" to "1","2" 

我们在melt上使用d2id变量stime保持不变,而使用其他列形成新列subject

x2 <- melt(d2,id=c("stime"),variable_name="subject")  
#>x2
#       stime subject value
#1  4/16/2012       1  11.5
#2  4/17/2012       1  12.3
#3  4/18/2012       1  22.0
#4  4/19/2012       1  34.0
#5  4/20/2012       1  25.0
#6  4/21/2012       1  35.0
#7  4/16/2012       2   4.0
#8  4/17/2012       2  16.0
#9  4/18/2012       2  23.0
#10 4/19/2012       2  25.0
#11 4/20/2012       2  33.0
#12 4/21/2012       2  45.0 

我们现在可以通过公共变量merged1 x2 subjectstime来获得所需的结果。

dd2 <- merge(d1, x2, by=c("subject","stime"))        
#> dd2
#   subject     stime value
#1        1 4/16/2012  11.5
#2        1 4/17/2012  12.3
#3        1 4/18/2012  22.0
#4        1 4/19/2012  34.0
#5        1 4/20/2012  25.0
#6        1 4/21/2012  35.0
#7        2 4/16/2012   4.0
#8        2 4/17/2012  16.0
#9        2 4/18/2012  23.0
#10       2 4/19/2012  25.0
#11       2 4/20/2012  33.0
#12       2 4/21/2012  45.0