从宽格式到长格式,结果包含多列

时间:2015-08-30 14:38:43

标签: r reshape2 tidyr

我的数据类似于以下数据框,但每个组合都有大约十个字段,从name1,adress1,city1等开始

   id name1  adress1 name2  adress2  name3  adress3
1  1  John street a  Burt street d  chris street 1
2  2  Jack street b   Ben street e connor street 2
3  3  Joey     <NA>   Bob street f   <NA>     <NA>  

现在我想重新排列这些数据,因此它更有用,它看起来应该是这样,但是它来自哪个条目的信息:

      id origin  names adresses
1  1      1   John street a
2  2      1   Jack street b
3  3      1   Joey     <NA>
4  1      2   Burt street d
5  2      2    Ben street e
6  3      2    Bob street f
7  1      3  chris street 1
8  2      3 connor street 2     

使用tidyr我可以得到一个长格式,但后来我有一个包含所有变量名的键列,name1,name2,name3,street1等。

我还尝试使用单独的数据帧,每个组合一个,例如一个数据框用于名称,一个用于街道等。但是然后将所有内容重新连接在一起会导致错误的记录,因为您只能加入id并以长格式复制此ID。我也一直在研究Reshape2,但这导致了同样的问题。

我所看到的所有转换为从长到长的转换都是在您要转换为一列时。我正在寻找10列的最终结果,或者如示例2列中那样。

是否有我忽视的功能?

#code to generete the dataframes:
df <- data.frame(id = c(1,2,3), 
                 name1 = c("John", "Jack", "Joey"), 
                 adress1 = c("street a", "street b", NA), 
                 name2 = c("Burt", "Ben", "Bob"),
                 adress2 = c("street d", "street e", "street f"),
                 name3 = c("chris", "connor", NA),
                 adress3 = c("street 1", "street 2", NA),
                 stringsAsFactors = FALSE)


expecteddf <- data.frame(id = c(1,2,3,1,2,3,1,2), 
                         origin = c(rep(1, 3), rep(2, 3), rep(3, 2)), 
                         names = c("John", "Jack", "Joey", "Burt", "Ben", "Bob", "chris", "connor"), 
                         adresses = c("street a", "street b", NA, "street d", "street e", "street f", "street 1", "street 2"),
                         stringsAsFactors = FALSE


                   )

1 个答案:

答案 0 :(得分:4)

我们可以使用melt版本的data.table中的devel,这可能会为patterns列带来多个measure。安装devel版本的'data.table'的说明是here

我们将'data.frame'转换为'data.table'(setDT(df)),melt,并在regex patterns中指定measure参数。删除“{name”和“address”列的NA行。

library(data.table)#v1.9.5+
dM <- melt(setDT(df), measure=patterns(c('^name', '^adress')),
          value.name=c('names', 'address') )
dM[!(is.na(names) & is.na(address))]
# id variable  names  address
#1:  1        1   John street a
#2:  2        1   Jack street b
#3:  3        1   Joey       NA
#4:  1        2   Burt street d
#5:  2        2    Ben street e
#6:  3        2    Bob street f
#7:  1        3  chris street 1
#8:  2        3 connor street 2

或者我们可以使用reshape中的base R

 dM2 <- reshape(df, idvar='id', varying=list(grep('name', names(df)), 
             grep('adress', names(df))), direction='long')

在我们使用NA创建逻辑索引后,使用标准的'data.frame'索引,可以像在data.table解决方案中一样删除is.na行。