繁体   English   中英

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

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

假设我有这个数据集

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

我希望按Id组删除零和Sales for Profit列的行所以对于某个Id如果两个或多个连续行的salesprofit值为零,那么这些行将被删除。 所以这个数据集将变成这样。

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

如果SalesProfit值为零,我可以删除所有行

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

但是在这种情况下如何通过Id删除仅在某些组中的行

PS这个想法是删除这些产品的条目,如果它们在几个月后开始销售,或者在一年周期中几个月后被放弃。

这是使用“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

以下是使用dplyr 基本上,我只保留不为零的行或者前一行/后一行不为零。

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

数据

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)

更新要使用这些条件筛选多个列,以下是如何执行此操作。 在目前的情况下,结果是相同的,因为当销售额为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)

我不能在一行中做到这一点,但这里有三个:

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

这通过首先识别salesProfit均为0( x )的所有行来工作。 变量y将连续的TRUEFALSE值分组。 ave()函数根据后续输入变量( df$Idy )拆分第一个输入变量( x ),然后在组内应用该函数。 由于函数是sum() ,它将把x所有TRUE值相加,然后它返回一个与x长度相同的向量,所以我们只需要保留结果小于2的所有行。

我的解决方案:

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