R - 按数据框中的组识别行元素序列

标签 r dataframe dplyr

考虑以下示例数据帧:

> df
   id name time
1   1    b   10
2   1    b   12
3   1    a    0
4   2    a    5
5   2    b   11
6   2    a    9
7   2    b    7
8   1    a   15
9   2    b    1
10  1    a    3

df = structure(list(id = c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 1L, 2L, 1L), 
    name = c("b", "b", "a", "a", "b", "a", "b", "a", "b", "a"
    ), time = c(10L, 12L, 0L, 5L, 11L, 9L, 7L, 15L, 1L, 3L)), .Names = c("id", 
"name", "time"), row.names = c(NA, -10L), class = "data.frame")

我需要识别并记录所有序列 seq <- c("a","b") ,对于每个 id,根据“时间”列,“a”在“b”之前。不允许在“a”和“b”之间使用其他名称。实际序列长度至少为 5。
样本数据的预期结果是
  a  b
1 3 10
2 5  7
3 9 11

有一个类似的问题Finding rows in R dataframe where a column value follows a sequence .但是,在我的情况下,我不清楚如何处理“id”列。它是一种使用“dplyr”解决问题的方法吗?

最佳答案

library(dplyr); library(tidyr)

# sort data frame by id and time
df %>% arrange(id, time) %>% group_by(id) %>% 

       # get logical vector indicating rows of a followed by b and mark each pair as unique
       # by cumsum
       mutate(ab = name == "a" & lead(name) == "b", g = cumsum(ab)) %>% 

       # subset rows where conditions are met
       filter(ab | lag(ab)) %>% 

       # reshape your data frame to wide format
       select(-ab) %>% spread(name, time)


#Source: local data frame [3 x 4]
#Groups: id [2]

#     id     g     a     b
#* <int> <int> <int> <int>
#1     1     1     3    10
#2     2     1     5     7
#3     2     2     9    11

如果序列的长度大于 2,则需要检查多个滞后,其中一种选择是使用 shift来自 data.table 的函数(接受向量作为滞后/超前步长)结合 Reduce ,比如说我们是否需要检查模式 abb :
library(dplyr); library(tidyr); library(data.table)
pattern = c("a", "b", "b")
len_pattern = length(pattern)

df %>% arrange(id, time) %>% group_by(id) %>% 

       # same logic as before but use Reduce function to check multiple lags condition
       mutate(ab = Reduce("&", Map("==", shift(name, n = 0:(len_pattern - 1), type = "lead"), pattern)), 
              g = cumsum(ab)) %>% 

       # use reduce or to subset sequence rows having the same length as the pattern
       filter(Reduce("|", shift(ab, n = 0:(len_pattern - 1), type = "lag"))) %>% 

       # make unique names
       group_by(g, add = TRUE) %>% mutate(name = paste(name, 1:n(), sep = "_")) %>% 

       # pivoting the table to wide format
       select(-ab) %>% spread(name, time) 

#Source: local data frame [1 x 5]
#Groups: id, g [1]

#     id     g   a_1   b_2   b_3
#* <int> <int> <int> <int> <int>
#1     1     1     3    10    12

关于R - 按数据框中的组识别行元素序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41130912/

相关文章:

r - 创建一个 0 对角线排列的 5x5 矩阵

r - 在使用 R 查询之前从 SQLite 数据库附加两个表

python - 如何修复jupyter笔记本中的 'Key Error: Index'错误

python - Pandas 在给定多个条件的情况下计算多列的总和

python - 如果特定列范围内有任何缺失值,如何更新数据框中的列值?

Postgres 中的滚动连接 (LOCF)

r - 从一组集合中找到所有不相交(非重叠)的集合

r - 两组差异,数据处理

使用 fct_relevel 按组对因子重新排序仅更改第一组中的因子顺序

r - 同时修剪多个变量的因子标签