2015-12-15 46 views
6

Angenommen, ich habe diesen DatensatzLöschen bestimmte Zeilen in einer Gruppe von Zeilen 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 

ich für Sales Zeilen mit Nullen löschen mag, und Profit Spalt von Id Gruppe Also für ein bestimmtes Id, wenn zwei oder mehr aufeinander folgende Zeilen haben Nullwerte für sales und profit diese Zeilen werden gelöscht. Also wird dieser Datensatz so aussehen.

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 

kann ich alle Zeilen entfernen, wenn sie für Sales Nullwerte haben und Profit mit

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

Aber wie Zeilen nur in bestimmten Gruppe von Id in diesem Fall löschen

PS Die Idee ist, Einträge für diese Produkte zu löschen, wenn sie nach einigen Monaten zu verkaufen begonnen haben oder nach einigen Monaten in einem Jahr aufgegeben wurden.

+0

Schreiben Sie eine einfache Funktion, die die Löschung durchführt und schließt/schließt die gewünschten Gruppen ein. Dann benutze irgendeinen von 'lapply' a' for' loop, 'data.table' oder '(d) plyr' zu split-apply-combine –

Antwort

5

: mein

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 
+0

Fehler in eval (expr, envir, enclos): Funktion konnte nicht gefunden werden " rleid " habe diesen Fehler, ich habe data.table Paket installiert und geladen. –

+0

@Jaykhan, welche Version von "data.table" benutzt du? Auf welchem ​​Betriebssystem bist du? – A5C1D2H2I1M1N2O1R2T1

+0

Datentabelle von 1.9.6 und mit OSX El Captain –

1

kann ich es nicht in einer Linie, aber hier ist es in drei:

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 

Dies funktioniert, indem zunächst alle Zeilen zu identifizieren, wo sales und Profit beide 0 (x). Die Variable y gruppiert aufeinanderfolgende Werte TRUE und FALSE. Die Funktion ave() teilt die erste Eingangsvariable (x) entsprechend den nachfolgenden Eingangsvariablen (df$Id und y) auf und wendet die Funktion dann gruppenweise an. Da die Funktion sum() ist, wird es alle TRUE Werte in x addieren, dann es einen Vektor der gleichen Länge wie x zurückkehrt, so brauchen wir nur alle Zeilen zu halten, wo das Ergebnis kleiner als 2.

+0

Als ich versuchte, den Code auf Originaldaten von mehr als 500.000 Zeilen anzuwenden, bricht es mit dem Fehler zusammen, dass lange Vektoren noch nicht unterstützt werden: –

3

So geht's mit dplyr. Im Grunde behalte ich nur Zeilen, die nicht Null sind oder dass die vorherigen/folgenden Zeilen nicht Null sind.

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 

Daten

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 Um auf mehr als eine Spalte mit diesen Kriterien zu filtern, ist hier, wie es zu tun. Im vorliegenden Fall ist das Ergebnis das gleiche, weil, wenn Verkäufe 0 sind, Gewinne auch mit rleid von „data.table“ Hier ist ein Ansatz sind 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) 
+0

Übrigens, das ist nicht ganz das, was das OP will. Sehen Sie sich die 8. Zeile des gewünschten Ergebnisses an. – DatamineR

+0

Ich habe meine Antwort bearbeitet, um sie zu beheben. –

+0

@PLapointe sein Löschen basierend auf einer Variablen Umsatz, richtig? Ich möchte Zeilen mit Null basierend auf 2 oder mehr Variablen Wert löschen. Wie geht das? –

1

Hier Lösung :

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 
+0

Als ich versuchte, den Code auf Originaldaten von mehr als 500.000 Zeilen anzuwenden, bricht es mit dem Fehler zusammen, dass lange Vektoren noch nicht unterstützt werden: –

Verwandte Themen