我想知道是否可以使用dplyr根据每行中的条件扩展data.frame的行。如果在dplyr中不可能,我会为任何解决方案感到高兴!
以下是我的数据样本
data.frame(plot=rep(c(6,7),each=4),
trans=rep(c("0,0","0,100","100,100","100,0"),2),
length_m=c(350,200,200,50,45,200,125,75) )
plot trans length_m
6 0,0 350
6 0,100 200
6 100,100 200
6 100,0 50
7 0,0 45
7 0,100 200
7 100,100 125
7 100,0 75
以上数据代表两个图。一般来说,我的每个地块都有1到4个横断面,由0,0标识; 0,100; 100,100;或者100,0(上面的图都有四个可能的横断面)。每个样带的长度由length_m给出。我想做的是将每个横断面除以长度L,并为每个新横断面划一行。如果最终横断面是< L,然后应将该距离添加到上一个横断面。
因此,如果L = 100,则上述数据集看起来像这样
plot trans length_m
6 0,0_0 100
6 0,0_100 100
6 0,0_200 150
6 0,100_0 100
6 0,100_100 100
6 100,100_0 100
6 100,100_100 100
6 100,0_0 50
7 0,0_0 45
7 0_100_0 100
7 0,100_100 100
7 100,100_0 125
7 100,0_0 75
请注意,长度为350米的6,0,0分为0,100和0,100。 200,长度100,100& 150,而长度为50米的6,100,0只是一个0区,仍然是50米长。
我尝试了几种不同的方法来完成这项工作,但没有什么值得发布的,所以任何帮助都会非常感激!
答案 0 :(得分:2)
这是一个数据表解决方案,假设您的原始数据位于数据框df
中。
df$trans <- as.character(df$trans) # need trans to be char, not factor
library(data.table)
dt <- data.table(df)
L <- 100
f <- function(x) { # implements the partitioning
if (x<L) return(x)
y <- rep(L,as.integer(x/L))
y[length(y)] <- y[length(y)]+x-sum(y)
return(y)
}
result <- dt[,list(length_m=f(length_m)),by=list(plot,trans)]
result[,trans:=paste(trans,L*(0:(.N-1)),sep="_"),by=list(plot,trans)]
result
# plot trans length_m
# 1: 6 0,0_0 100
# 2: 6 0,0_100 100
# 3: 6 0,0_200 150
# 4: 6 0,100_0 100
# 5: 6 0,100_100 100
# 6: 6 100,100_0 100
# 7: 6 100,100_100 100
# 8: 6 100,0_0 50
# 9: 7 0,0_0 45
# 10: 7 0,100_0 100
# 11: 7 0,100_100 100
# 12: 7 100,100_0 125
# 13: 7 100,0_0 75
答案 1 :(得分:0)
这是一个dplyr解决方案 - 虽然不是很优雅。
df <- data.frame(plot=rep(c(6,7),each=4),
trans=rep(c("0,0","0,100","100,100","100,0"),2),
length_m=c(350,200,200,50,45,200,125,75) )
df %>%
mutate(rnum = row_number(),
freq = pmax(floor(length_m/100),1)) %>%
group_by(rnum) %>% complete(
freq = 1:freq
) %>% mutate_all(
funs(last(.))
) %>% mutate(
within.rnum = row_number(),
trans = paste0(trans,"_",100*(within.rnum-1)),
length_m = ifelse(within.rnum==n(),(length_m - 100*(floor(length_m/100))) + 100*(length_m>100),100)
) %>% ungroup %>% select(-rnum,-within.rnum,-freq)
# Source: local data frame [13 x 4]
# Groups: rnum [6]
#
# rnum freq x y
# <int> <dbl> <dbl> <dbl>
# 1 1 1 0.8894632 1.4368569
# 2 2 1 0.4325821 0.9366039
# 3 3 2 0.2039089 0.6234862
# 4 3 2 0.2039089 0.6234862
# 5 4 2 0.9493441 1.5977998
# 6 4 2 0.9493441 1.5977998
# 7 5 3 0.9806209 1.7840731
# 8 5 3 0.9806209 1.7840731
# 9 5 3 0.9806209 1.7840731
# 10 6 4 0.8778605 1.4682580
# 11 6 4 0.8778605 1.4682580
# 12 6 4 0.8778605 1.4682580
# 13 6 4 0.8778605 1.4682580
对于dplyr中的“扩展”数据集,我发现以下group_by row_number()然后应用complete()结构,例如:
df <- data_frame(x=runif(n=6),y=x+runif(n=6),freq=c(1,1,2,2,3,4))
df %>% mutate(rnum = row_number()) %>%
group_by(rnum) %>% complete(
freq = 1:freq
) %>% mutate_all(
funs(last(.))
)
# Source: local data frame [13 x 4]
# Groups: rnum [6]
#
# rnum freq x y
# <int> <dbl> <dbl> <dbl>
# 1 1 1 0.8894632 1.4368569
# 2 2 1 0.4325821 0.9366039
# 3 3 2 0.2039089 0.6234862
# 4 3 2 0.2039089 0.6234862
# 5 4 2 0.9493441 1.5977998
# 6 4 2 0.9493441 1.5977998
# 7 5 3 0.9806209 1.7840731
# 8 5 3 0.9806209 1.7840731
# 9 5 3 0.9806209 1.7840731
# 10 6 4 0.8778605 1.4682580
# 11 6 4 0.8778605 1.4682580
# 12 6 4 0.8778605 1.4682580
# 13 6 4 0.8778605 1.4682580
虽然我认为有很简单的方法可以使用基数R(例如Replicate each row of data.frame and specify the number of replications for each row的答案)。