根据列中的字符和数据框中出现的顺序为每个组设置子集行

Subset rows for each group based on a character in a column and order of occurrence in a data frame

我有一个类似的数据

B <- data.frame(State = c(rep("Arizona", 8), rep("California", 8), rep("Texas", 8)), 
  Account = rep(c("Balance", "Balance", "In the Bimester", "In the Bimester", "Expenses",  
  "Expenses", "In the Bimester", "In the Bimester"), 3), Value = runif(24))

您可以看到 Account 出现了 4 次元素 "In the Bimester"两次 "chunks" 每个状态的两个元素,"Expenses" 在他们之间。

这里的顺序很重要,因为第一个块与第二个块指的不是同一个东西。

我的数据其实比较复杂,它有第4个变量,表示Account每一行的意思。每个 Account 元素的元素数量(因子本身)可以改变。例如,在某些状态下,"In the Bimester" 的第一个 "chunk" 可以有 6 行,第二个可以有 7 行;但是,我无法通过这第四个变量来区分。

期望: 我想对我的数据进行子集化,将这两个 "In the Bimester" 按每个州拆分,仅对第一个 "chunks" 的行进行子集化每个州或第二个 "chunks".

我有一个使用 data.table 包的解决方案,但我发现它有点差。有什么想法吗?

library(data.table)
B <- as.data.table(B)
B <- B[, .(Account, Value, index = 1:.N), by = .(State)]
x <- B[Account == "Expenses", .(min_ind = min(index)), by = .(State)]
B <- merge(B, x, by = "State")
B <- B[index < min_ind & Account == "In the Bimester", .(Value), by = .(State)]

您可以使用 dplyr 包:

library(dplyr)
B %>% mutate(helper = data.table::rleid(Account)) %>% 
      filter(Account == "In the Bimester") %>% 
      group_by(State) %>% filter(helper == min(helper)) %>% select(-helper)

# # A tibble: 6 x 3
# # Groups:   State [3]
#        State         Account      Value
#       <fctr>          <fctr>      <dbl>
# 1    Arizona In the Bimester 0.17730148
# 2    Arizona In the Bimester 0.05695585
# 3 California In the Bimester 0.29089678
# 4 California In the Bimester 0.86952723
# 5      Texas In the Bimester 0.54076144
# 6      Texas In the Bimester 0.59168138

如果您使用 max 而不是 min,您将得到每个 State 最后出现的 "In the Bimester"。您还可以通过将最后一个管道更改为 select(-helper,-Account).

来排除 Account

p.s. 如果你不想使用 data.table 中的 rleid 而只是使用 dplyr 函数看看这个 .