![](/img/trans.png)
[英]Updating rows of a data.frame with the rows of another data.frame
[英]Combining rows in a data.frame
我有一个data.frame
,看起来像下面的示例data.frame
:
df = data.frame(id = c("a","b","c","d","e","f","g"), start = c(10,20,30,40,50,60,70), end = c(15,25,35,45,55,65,75), flag = c(0,1,1,0,1,0,1))
> df
id start end flag
1 a 10 15 0
2 b 20 25 1
3 c 30 35 1
4 d 40 45 0
5 e 50 55 1
6 f 60 65 0
7 g 70 75 1
按df$start
升序排序,然后按df$end
升序排序。 我正在寻找一个函数,该函数将合并df$flag == 1
所有行,而不合并df$flag == 0
。 合并的行的df$id
应该用逗号分隔符连接起来,它们的df$start
应该是具有min
df$start
的行,而df$end
应该是具有max
df$end
。 最后,对于他们, df$flag
应该为1。
因此,对于此示例,返回的data.frame
应该为:
res.df = data.frame(id = c("a","b,c","d","e","f","g"), start = c(10,20,40,50,60,70), end = c(15,35,45,55,65,75), flag = c(0,1,0,1,0,1))
> res.df
id start end flag
1 a 10 15 0
2 b,c 20 35 1
3 d 40 45 0
4 e 50 55 1
5 f 60 65 0
6 g 70 75 1
对于aggregate
,很难做到这一点,因为将相同的功能依次应用于每个列。 多次调用aggregate
可以分段完成此任务,然后将其合并。 但是, data.table
在同一调用中允许使用不同的聚合函数:
library(data.table)
d <- data.table(df)
d[,list(id=paste(id, collapse=','), start=min(start), end=max(end)),
by=list(flag, cumsum(flag==0))
]
flag cumsum id start end
1: 0 1 a 10 15
2: 1 1 b,c 20 35
3: 0 2 d 40 45
4: 1 2 e 50 55
5: 0 3 f 60 65
6: 1 3 g 70 75
您最终会得到一个新列,如果需要,可以将其删除。 上的条件cumsum(flag==0)
防止任何行与flag==0
从骨料被组合,并且保持该非连续flag==1
值在结果中分离。
这是使用aggregate
和merge
base
解决方案:
merge(merge(aggregate(start ~ flag + cumsum(flag==0), data=df, FUN=min),
aggregate(end ~ flag + cumsum(flag==0), data=df, FUN=max)
),
aggregate(id ~ flag + cumsum(flag==0), data=df, FUN=paste, sep=',')
)
flag cumsum(flag == 0) start end id
1 0 1 10 15 a
2 0 2 40 45 d
3 0 3 60 65 f
4 1 1 20 35 b, c
5 1 2 50 55 e
6 1 3 70 75 g
如果使用Reduce
和数据帧列表进行合并,则代码更具可读性:
Reduce(merge, list(aggregate(start ~ flag + cumsum(flag==0), data=df, FUN=min),
aggregate(end ~ flag + cumsum(flag==0), data=df, FUN=max),
aggregate(id ~ flag + cumsum(flag==0), data=df, FUN=paste, sep=',')
)
)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.