簡體   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