我有一个这样的数据框:
id y1 y2 y3 y4
--+--+--+--+--
a |12|13|14|
b |12|18| |
c |13| | |
d |13|14|15|16
我想以这样的方式重塑,以两列结束。上面的例子将成为:
id from to
--+----+---
a |12 |13
a |13 |14
a |14 |
b |12 |18
b |18 |
c |13 |
d |13 |14
d |14 |15
d |15 |16
每个id
都有一个'来自'和'到'每对年份的价值。
有人知道一个简单的方法吗?我尝试使用reshape2
。我也看了Combine Multiple Columns Into Tidy Data,但我认为我的情况有所不同。
答案 0 :(得分:5)
您可以使用lapply
循环列对和rbind
来结合它们:
do.call(rbind,
lapply(2:(length(df)-1),
function(x) setNames(df[!is.na(df[,x]),c(1,x,x+1)],
c("id", "from", "to"))))
id from to
1 a 12 13
2 b 12 18
3 c 13 NA
4 d 13 14
11 a 13 14
21 b 18 NA
41 d 14 15
12 a 14 NA
42 d 15 16
答案 1 :(得分:5)
解决方案使用dplyr
和tidyr
。 dt2
是最终输出。
# Create example data frame
dt <- data.frame(id = c("a", "b", "c", "d"),
y1 = c(12, 12, 13, 13),
y2 = c(13, 18, NA, 14),
y3 = c(14, NA, NA, 15),
y4 = c(NA, NA, NA, 16),
stringsAsFactors = FALSE)
# Load packages
library(dplyr)
library(tidyr)
# Process the data
dt2 <- dt %>%
gather(STEP, from, -id) %>%
drop_na(from) %>%
arrange(id, STEP) %>%
group_by(id) %>%
mutate(to = lead(from)) %>%
select(-STEP)
答案 2 :(得分:4)
在基础R中,stack
并将每个组中的所有内容移回一行。使用@ ycw的示例数据dt
:
tmp <- na.omit(cbind(dt[1], stack(dt[-1])[-2]))
names(tmp)[2] <- "from"
tmp$to <- with(tmp, ave(from, id, FUN=function(x) c(tail(x,-1),NA) ))
tmp[order(tmp$id),]
# id from to
#1 a 12 13
#5 a 13 14
#9 a 14 NA
#2 b 12 18
#6 b 18 NA
#3 c 13 NA
#4 d 13 14
#8 d 14 15
#12 d 15 16
#16 d 16 NA
在data.table
的世界中,同样的逻辑适用。 melt
,然后是shift
by=
id:
library(data.table)
dt <- as.data.table(dt)
melt(dt, id.vars="id", value.name="from")[
!is.na(from),-"variable"][, to := shift(from,1,type="lead"), by=id
][order(id)]