将多组测量列(宽格式)重新整理为单列(长格式)

我有一个宽格式的dataframe,在不同的date范围内进行重复测量。 在我的例子中,有三个不同的时期,都有相应的价值。 例如,在从“DateRange1Start”到“DateRange1End”期间测量的第一个度量('Value1'):

ID DateRange1Start DateRange1End Value1 DateRange2Start DateRange2End Value2 DateRange3Start DateRange3End Value3 1 1/1/90 3/1/90 4.4 4/5/91 6/7/91 6.2 5/5/95 6/6/96 3.3 

我正在寻找重塑的数据到一个长的格式,使DateRangeXStart和DateRangeXEnd列分组。 因此,原表中的1行在新表中成为3行:

 ID DateRangeStart DateRangeEnd Value 1 1/1/90 3/1/90 4.4 1 4/5/91 6/7/91 6.2 1 5/5/95 6/6/96 3.3 

我知道必须有一种方法来处理reshape2 / melt / tidyr / tidyr ,但我似乎无法弄清楚如何以这种特殊的方式将多组度量variables映射到一组值列中。

 reshape(dat, idvar="ID", direction="long", varying=list(Start=c(2,5,8), End=c(3,6,9), Value=c(4,7,10)), v.names = c("DateRangeStart", "DateRangeEnd", "Value") ) #------------- ID time DateRangeStart DateRangeEnd Value 1.1 1 1 1/1/90 3/1/90 4.4 1.2 1 2 4/5/91 6/7/91 6.2 1.3 1 3 5/5/95 6/6/96 3.3 

(每Josh的build议增加了v.names。)

data.tablemelt函数可以融合成多个列。 使用这个,我们可以简单地做:

 require(data.table) melt(setDT(dat), id=1L, measure=patterns("Start$", "End$", "^Value"), value.name=c("DateRangeStart", "DateRangeEnd", "Value")) # ID variable DateRangeStart DateRangeEnd Value # 1: 1 1 1/1/90 3/1/90 4.4 # 2: 1 2 4/5/91 6/7/91 6.2 # 3: 1 3 5/5/95 6/6/96 3.3 

或者,也可以通过列位置引用三组度量值:

 melt(setDT(dat), id = 1L, measure = list(c(2,5,8), c(3,6,9), c(4,7,10)), value.name = c("DateRangeStart", "DateRangeEnd", "Value")) 

这是一个使用tidyr的问题的方法。 对于函数extract_numeric() ,这是一个有趣的用例,我用它从列名称中提取出组

 library(dplyr) library(tidyr) a <- read.table(textConnection(" ID DateRange1Start DateRange1End Value1 DateRange2Start DateRange2End Value2 DateRange3Start DateRange3End Value3 1 1/1/90 3/1/90 4.4 4/5/91 6/7/91 6.2 5/5/95 6/6/96 3.3 "),header=TRUE) a %>% gather(variable,value,-ID) %>% mutate(group = extract_numeric(variable)) %>% mutate(variable = gsub("\\d","",x = variable)) %>% spread(variable,value) ID group DateRangeEnd DateRangeStart Value 1 1 1 3/1/90 1/1/90 4.4 2 1 2 6/7/91 4/5/91 6.2 3 1 3 6/6/96 5/5/95 3.3 

你不需要任何幻想; 基地的Rfunction将做。

 a <- read.table(textConnection(" ID DateRange1Start DateRange1End Value1 DateRange2Start DateRange2End Value2 DateRange3Start DateRange3End Value3 1 1/1/90 3/1/90 4.4 4/5/91 6/7/91 6.2 5/5/95 6/6/96 3.3 "),header=TRUE) b1 <- a[,c(1:4)]; b2 <- a[,c(1,5:7)]; b3 <- a[,c(1,8:10)] colnames(b1) <- colnames(b2) <- colnames(b3) <- c("ID","DateRangeStart","DateRangeEnd","Value") b <- rbind(b1,b2,b3)