简体   繁体   English

删除R中一组行中的某些行

[英]Delete certain rows in a group of rows in R

Suppose I have this dataset 假设我有这个数据集

Id Name Price sales Profit Month Category Mode Supplier
1    A     2     0      0     1        X    K     John
1    A     2     0      0     2        X    K     John
1    A     2     5      8     3        X    K     John
1    A     2     5      8     4        X    L      Sam
2    B     2     3      4     1        X    L      Sam
2    B     2     0      0     2        X    L      Sam
2    B     2     0      0     3        X    M     John
2    B     2     0      0     4        X    L     John
3    C     2     0      0     1        X    K     John
3    C     2     8     10     2        Y    M     John
3    C     2     8     10     3        Y    K     John
3    C     2     0      0     4        Y    K     John
5    E     2     0      0     1        Y    M      Sam
5    E     2     5      5     2        Y    L      Sam
5    E     2     5      9     3        Y    M      Sam
5    E     2     0      0     4        Z    M     Kyle
5    E     2     5      8     5        Z    L     Kyle
5    E     2     5      8     6        Z    M     Kyle

I want to delete rows with zeroes for Sales and Profit column by Id group So for a certain Id if two or more consecutive rows have zero values for sales and profit those rows will get delete. 我希望按Id组删除零和Sales for Profit列的行所以对于某个Id如果两个或多个连续行的salesprofit值为零,那么这些行将被删除。 So this dataset will become like this. 所以这个数据集将变成这样。

Id Name Price sales Profit Month Category Mode Supplier
1    A     2     5      8     3        X    K     John
1    A     2     5      8     4        X    L      Sam
2    B     2     3      4     1        X    L      Sam
3    C     2     0      0     1        X    K     John
3    C     2     8     10     2        Y    M     John
3    C     2     8     10     3        Y    K     John
3    C     2     0      0     4        Y    K     John
5    E     2     0      0     1        Y    M      Sam
5    E     2     5      5     2        Y    L      Sam
5    E     2     5      9     3        Y    M      Sam
5    E     2     0      0     4        Z    M     Kyle
5    E     2     5      8     5        Z    L     Kyle
5    E     2     5      8     6        Z    M     Kyle

I can remove all rows if they have zero values for Sales and Profit with 如果SalesProfit值为零,我可以删除所有行

df1 = df[!(df$sales==0 & test$Profit==0),]

But how to delete rows only in certain group in this case by Id 但是在这种情况下如何通过Id删除仅在某些组中的行

PS The idea is to delete entries for those products if they started selling after few months or got abandoned after few months in a year cycle. PS这个想法是删除这些产品的条目,如果它们在几个月后开始销售,或者在一年周期中几个月后被放弃。

Here's an approach using rleid from "data.table": 这是使用“data.table”中的rleid的方法:

library(data.table)
as.data.table(mydf)[, N := .N, by = .(Id, rleid(sales == 0 & Profit == 0))][
    !(sales == 0 & Profit == 0 & N >= 2)]
##     Id Name Price sales Profit Month Category Mode Supplier N
##  1:  1    A     2     5      8     3        X    K     John 2
##  2:  1    A     2     5      8     4        X    L      Sam 2
##  3:  2    B     2     3      4     1        X    L      Sam 1
##  4:  3    C     2     0      0     1        X    K     John 1
##  5:  3    C     2     8     10     2        Y    M     John 2
##  6:  3    C     2     8     10     3        Y    K     John 2
##  7:  3    C     2     0      0     4        Y    K     John 1
##  8:  5    E     2     0      0     1        Y    M      Sam 1
##  9:  5    E     2     5      5     2        Y    L      Sam 2
## 10:  5    E     2     5      9     3        Y    M      Sam 2
## 11:  5    E     2     0      0     4        Z    M     Kyle 1
## 12:  5    E     2     5      8     5        Z    L     Kyle 2
## 13:  5    E     2     5      8     6        Z    M     Kyle 2

Here's how to do it with dplyr . 以下是使用dplyr Basically, I'm only keeping lines that are not zero OR that the previous/following lines is not zero. 基本上,我只保留不为零的行或者前一行/后一行不为零。

table1 %>%
group_by(Id) %>%
mutate(Lag=lag(sales),Lead=lead(sales)) %>%
rowwise() %>%
mutate(Min=min(Lag,Lead,na.rm=TRUE)) %>%
filter(sales>0|Min>0)  %>%
select(-Lead,-Lag,-Min)

      Id  Name Price sales Profit Month Category  Mode Supplier
   (int) (chr) (int) (int)  (int) (int)    (chr) (chr)    (chr)
1      1     A     2     5      8     3        X     K     John
2      1     A     2     5      8     4        X     L      Sam
3      2     B     2     3      4     1        X     L      Sam
4      3     C     2     0      0     1        X     K     John
5      3     C     2     8     10     2        Y     M     John
6      3     C     2     8     10     3        Y     K     John
7      3     C     2     0      0     4        Y     K     John
8      5     E     2     0      0     1        Y     M      Sam
9      5     E     2     5      5     2        Y     L      Sam
10     5     E     2     5      9     3        Y     M      Sam
11     5     E     2     0      0     4        Z     M     Kyle
12     5     E     2     5      8     5        Z     L     Kyle
13     5     E     2     5      8     6        Z     M     Kyle

Data 数据

table1 <-read.table(text="
Id,Name,Price,sales,Profit,Month,Category,Mode,Supplier
1,A,2,0,0,1,X,K,John
1,A,2,0,0,2,X,K,John
1,A,2,5,8,3,X,K,John
1,A,2,5,8,4,X,L,Sam
2,B,2,3,4,1,X,L,Sam
2,B,2,0,0,2,X,L,Sam
2,B,2,0,0,3,X,M,John
2,B,2,0,0,4,X,L,John
3,C,2,0,0,1,X,K,John
3,C,2,8,10,2,Y,M,John
3,C,2,8,10,3,Y,K,John
3,C,2,0,0,4,Y,K,John
5,E,2,0,0,1,Y,M,Sam
5,E,2,5,5,2,Y,L,Sam
5,E,2,5,9,3,Y,M,Sam
5,E,2,0,0,4,Z,M,Kyle
5,E,2,5,8,5,Z,L,Kyle
5,E,2,5,8,6,Z,M,Kyle
",sep=",",stringsAsFactors =FALSE, header=TRUE)

UPDATE To filter on more than one column with these criteria, here's how to do it. 更新要使用这些条件筛选多个列,以下是如何执行此操作。 In the present case, the result is the same because when sales are 0, profits are also 0. 在目前的情况下,结果是相同的,因为当销售额为0时,利润也为0。

library(dplyr)
table1 %>%
group_by(Id) %>%
mutate(LagS=lag(sales),LeadS=lead(sales),LagP=lag(Profit),LeadP=lead(Profit)) %>%
rowwise() %>%
mutate(MinS=min(LagS,LeadS,na.rm=TRUE),MinP=min(LagP,LeadP,na.rm=TRUE)) %>%
filter(sales>0|MinS>0|Profit>0|MinP>0)  %>%         # "|" means OR
select(-LeadS,-LagS,-MinS,-LeadP,-LagP,-MinP)

I can't do it in one line, but here it is in three: 我不能在一行中做到这一点,但这里有三个:

x <- df$sales==0 & df$Profit==0
y <- cumsum(c(1,head(x,-1)!=tail(x,-1)))
df[ave(x,df$Id,y,FUN=sum)<2,]

#    Id Name Price sales Profit Month Category Mode Supplier
# 3   1    A     2     5      8     3        X    K     John
# 4   1    A     2     5      8     4        X    L      Sam
# 5   2    B     2     3      4     1        X    L      Sam
# 9   3    C     2     0      0     1        X    K     John
# 10  3    C     2     8     10     2        Y    M     John
# 11  3    C     2     8     10     3        Y    K     John
# 12  3    C     2     0      0     4        Y    K     John
# 13  5    E     2     0      0     1        Y    M      Sam
# 14  5    E     2     5      5     2        Y    L      Sam
# 15  5    E     2     5      9     3        Y    M      Sam
# 16  5    E     2     0      0     4        Z    M     Kyle
# 17  5    E     2     5      8     5        Z    L     Kyle
# 18  5    E     2     5      8     6        Z    M     Kyle

This works by first identifying all rows where sales and Profit are both 0 ( x ). 这通过首先识别salesProfit均为0( x )的所有行来工作。 The variable y groups consecutive TRUE and FALSE values. 变量y将连续的TRUEFALSE值分组。 The ave() function splits the first input variable ( x ) according to the subsequent input variables ( df$Id and y ) then applies the function within groups. ave()函数根据后续输入变量( df$Idy )拆分第一个输入变量( x ),然后在组内应用该函数。 Since the function is sum() , it will add up all the TRUE values in x , then it returns a vector of the same length as x , so we just need to keep all the rows where the result is less than 2. 由于函数是sum() ,它将把x所有TRUE值相加,然后它返回一个与x长度相同的向量,所以我们只需要保留结果小于2的所有行。

Here my solution: 我的解决方案:

aux <- lapply(tapply(df$sales + df$Profit, df$Id, rle), function(x) 
       with(x, cbind(rep(values, lengths), rep(lengths, lengths))))

df[!(do.call(rbind, aux)[,1]==0 & do.call(rbind, aux)[,2] >= 2),]

   Id Name Price sales Profit Month Category Mode Supplier
3   1    A     2     5      8     3        X    K     John
4   1    A     2     5      8     4        X    L      Sam
5   2    B     2     3      4     1        X    L      Sam
9   3    C     2     0      0     1        X    K     John
10  3    C     2     8     10     2        Y    M     John
11  3    C     2     8     10     3        Y    K     John
12  3    C     2     0      0     4        Y    K     John
13  5    E     2     0      0     1        Y    M      Sam
14  5    E     2     5      5     2        Y    L      Sam
15  5    E     2     5      9     3        Y    M      Sam
16  5    E     2     0      0     4        Z    M     Kyle
17  5    E     2     5      8     5        Z    L     Kyle
18  5    E     2     5      8     6        Z    M     Kyle

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM