将多组测量列(宽格式)重新整理为单列(长格式)
我有一个宽格式的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.table
的melt
函数可以融合成多个列。 使用这个,我们可以简单地做:
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
你不需要任何幻想; 基地的R
function将做。
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)