Han*_*upe 4 group-by r run-length-encoding dataframe
我没有找到R中这个常见分组问题的解决方案:
这是我的原始数据集
ID State
1 A
2 A
3 B
4 B
5 B
6 A
7 A
8 A
9 C
10 C
Run Code Online (Sandbox Code Playgroud)
这应该是我的分组结果数据集
State min(ID) max(ID)
A 1 2
B 3 5
A 6 8
C 9 10
Run Code Online (Sandbox Code Playgroud)
因此,我们的想法是首先按ID列(或时间戳列)对数据集进行排序.然后,应将没有间隙的所有连接状态组合在一起,并返回最小和最大ID值.它与rle方法有关,但这不允许计算组的最小值,最大值.
有任何想法吗?
你可以尝试:
library(dplyr)
df %>%
mutate(rleid = cumsum(State != lag(State, default = ""))) %>%
group_by(rleid) %>%
summarise(State = first(State), min = min(ID), max = max(ID)) %>%
select(-rleid)
Run Code Online (Sandbox Code Playgroud)
或者按照@alistaire在评论中提到的,你实际上可以group_by()使用相同的语法进行变异,结合前两个步骤.窃取data.table::rleid()和使用summarise_all()简化:
df %>%
group_by(State, rleid = data.table::rleid(State)) %>%
summarise_all(funs(min, max)) %>%
select(-rleid)
Run Code Online (Sandbox Code Playgroud)
这使:
## A tibble: 4 × 3
# State min max
# <fctr> <int> <int>
#1 A 1 2
#2 B 3 5
#3 A 6 8
#4 C 9 10
Run Code Online (Sandbox Code Playgroud)
这是一个方法,它使用rle基数R中的函数为您提供的数据集.
# get the run length encoding
temp <- rle(df$State)
# construct the data.frame
newDF <- data.frame(State=temp$values,
min.ID=c(1, head(cumsum(temp$lengths) + 1, -1)),
max.ID=cumsum(temp$lengths))
Run Code Online (Sandbox Code Playgroud)
返回
newDF
State min.ID max.ID
1 A 1 2
2 B 3 5
3 A 6 8
4 C 9 10
Run Code Online (Sandbox Code Playgroud)
注意,rle需要一个字符向量而不是一个因子,所以我使用下面的as.is参数.
正如@ cryo111在下面的注释中所述,数据集可能是无序的时间戳,与时间计算的长度不对应rle.要使此方法起作用,您需要首先将时间戳转换为日期时间格式,使用类似函数as.POSIXct,使用df <- df[order(df$ID),],然后对上述方法稍作修改:
# get the run length encoding
temp <- rle(df$State)
# construct the data.frame
newDF <- data.frame(State=temp$values,
min.ID=df$ID[c(1, head(cumsum(temp$lengths) + 1, -1))],
max.ID=df$ID[cumsum(temp$lengths)])
Run Code Online (Sandbox Code Playgroud)
数据
df <- read.table(header=TRUE, as.is=TRUE, text="ID State
1 A
2 A
3 B
4 B
5 B
6 A
7 A
8 A
9 C
10 C")
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
220 次 |
| 最近记录: |