【问题标题】:R, delete previous rows based on values in seperate columnR,根据单独列中的值删除以前的行
【发布时间】:2020-10-19 10:16:05
【问题描述】:

我是 R 新手。我正在尝试根据另一列设置的条件删除之前的行。

我找到了带有 dplyr 和 data.table 的解决方案,我相信它们与我正在寻找的东西很接近,因为它们正好相反。

样本数据:

Cust_ID | Date                 | Value
500219  | 2016-04-11 12:00:00  | 0
500219  | 2016-04-12 16:00:00  | A
500219  | 2016-04-14 11:00:00  | A
500219  | 2016-04-15 12:00:00  | B
500219  | 2016-05-23 09:00:00  | B
500219  | 2016-05-02 19:00:00  | C
500220  | 2016-04-11 12:00:00  | C
500220  | 2016-04-14 11:00:00  | C
500220  | 2016-04-15 12:00:00  | A
500220  | 2016-05-23 09:00:00  | A
500220  | 2016-05-02 19:00:00  | A

对于每个 Cust_ID,我只想保留 Value == "A" 之后的行,包括该行。这应该会产生以下数据框:

Cust_ID | Date                 | Value
500219  | 2016-04-12 16:00:00  | A
500219  | 2016-04-14 11:00:00  | A
500219  | 2016-04-15 12:00:00  | B
500219  | 2016-05-23 09:00:00  | B
500219  | 2016-05-02 19:00:00  | C
500220  | 2016-04-15 12:00:00  | A
500220  | 2016-05-23 09:00:00  | A
500220  | 2016-05-02 19:00:00  | A

这些是我已经找到的解决方案 (R delete rows based on values in previous rows)

library(data.table)
setDT(df1)[df1[,  if(any(Value == "A")) .I[seq(max(which(Value == "A")))]
                                 else .I[1:.N] , by = Cust_ID]$V1]


library(dplyr)
df1 %>% 
     group_by(Cust_ID) %>% 
     slice(if(any(Value=="A")) seq(max(which(Value=="A"))) else row_number())

【问题讨论】:

  • 每个组里总有一些value == "A"吗?
  • 是的,但这可能会随着数据集的更新而改变。

标签: r dplyr data.table


【解决方案1】:

这行得通吗:

> library(dplyr)
> df %>% group_by(Cust_ID) %>% filter(row_number() >= min(which(Value == 'A')))
# A tibble: 8 x 3
# Groups:   Cust_ID [2]
  Cust_ID Date                Value
    <dbl> <chr>               <chr>
1  500219 2016-04-12 16:00:00 A    
2  500219 2016-04-14 11:00:00 A    
3  500219 2016-04-15 12:00:00 B    
4  500219 2016-05-23 09:00:00 B    
5  500219 2016-05-02 19:00:00 C    
6  500220 2016-04-15 12:00:00 A    
7  500220 2016-05-23 09:00:00 A    
8  500220 2016-05-02 19:00:00 A    
> 

【讨论】:

  • 这个解决方案会起作用,不幸的是我对数据的结构还不是很清楚。值列具有多个级别(分类变量)。我试图编辑数据框。抱歉耽误您的时间。
【解决方案2】:

也许subset + ave 的基本 R 选项会有所帮助

subset(df,ave(Value, Cust_ID, FUN = cumsum)>0)

给了

   Cust_ID                Date Value
3   500219 2016-04-14 11:00:00     1
4   500219 2016-04-15 12:00:00     1
5   500219 2016-05-23 09:00:00     0
6   500219 2016-05-02 19:00:00     0
8   500220 2016-04-14 11:00:00     1
9   500220 2016-04-15 12:00:00     1
10  500220 2016-05-23 09:00:00     0
11  500220 2016-05-02 19:00:00     0

【讨论】:

  • 这个解决方案会起作用,不幸的是我对数据的结构还不是很清楚。值列具有多个级别(分类变量)。我试图编辑数据框。抱歉耽误您的时间。
【解决方案3】:

这是另一个使用非等连接的选项:

df1[df1[Value=="A", Date[1L], Cust_ID], on=.(Cust_ID, Date>=V1)]

输出:

   Cust_ID                Date Value
1:  500219 2016-04-12 16:00:00     A
2:  500219 2016-04-12 16:00:00     A
3:  500219 2016-04-12 16:00:00     B
4:  500219 2016-04-12 16:00:00     B
5:  500219 2016-04-12 16:00:00     C
6:  500220 2016-04-15 12:00:00     A
7:  500220 2016-04-15 12:00:00     A
8:  500220 2016-04-15 12:00:00     A

数据:

df1 <- fread("Cust_ID | Date                 | Value
500219  | 2016-04-11 12:00:00  | 0
500219  | 2016-04-12 16:00:00  | A
500219  | 2016-04-14 11:00:00  | A
500219  | 2016-04-15 12:00:00  | B
500219  | 2016-05-23 09:00:00  | B
500219  | 2016-05-02 19:00:00  | C
500220  | 2016-04-11 12:00:00  | C
500220  | 2016-04-14 11:00:00  | C
500220  | 2016-04-15 12:00:00  | A
500220  | 2016-05-23 09:00:00  | A
500220  | 2016-05-02 19:00:00  | A")
df1[, Date := as.POSIXct(Date, format="%Y-%m-%d %T")]

【讨论】:

    猜你喜欢
    • 2012-05-02
    • 2021-01-22
    • 1970-01-01
    • 2023-03-21
    • 2016-05-01
    • 2021-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多