2017-12-07 4 views
1

ich eine große Datenmenge haben, aber hier habe ich eine Beispieldaten erschaffe, die gleichen Daten Gerangel Problem hatdplyr | group_by vs anti_join | effizienteste Weg

Daten

brand=c('MS', 'Google', 'Apple', 'MS', 'FB', 'Apple', 'Oracle') 
product=c('Window', 'Search', 'Iphone', 'Window', 'Network', 'Iphone', 'DB') 
isExist=c('Yes', 'Yes', NA, 'No', NA, 'Yes', NA) 
df= data.frame(brand, product, isExist) 

sehen diese Daten wie diese

brand product isExist 
1  MS Window  Yes 
2 Google Search  Yes 
3 Apple Iphone <NA> 
4  MS Window  No 
5  FB Network <NA> 
6 Apple Iphone  Yes 
7 Oracle  DB <NA> 

jetzt Ich möchte die Zeilen basierend auf Marke und Produkt (zusammengesetzter Schlüssel), die NA-Einträge für isExist und keine anderen Zeilen für den gleichen zusammengesetzten Schlüssel, der Werte hat, dh es sollte FB, Oracle, aber nicht Apple als eine der Zeile (ro w no 6) Wert in isExist

Ich bin es zu erreichen anti_join verwenden, hier der Code

library(dplyr) 
testWithData <- df %>% filter(!is.na(isExist)) 
testWithoutData <- df %>% filter(is.na(isExist)) 
final <- unique(anti_join(testWithoutData, testWithData, by = c('brand', 'product'))) 

Ausgabe

brand product isExist 
1  FB Network <NA> 
2 Oracle  DB <NA> 

Diese Lösung funktioniert, aber es ist zu viel Zeit in Anspruch nimmt, ich weiß, es ist nicht der effizienteste Weg. Ich fühle mich GROUP_BY und Filter kann etwas Magie tun, aber ich bin nicht sicher, wie ich die Abfrage zu schreiben, kann mir bitte jemand in dieser Hinsicht helfen

+0

ich habe keine Zeit, es gerade jetzt zu arbeiten, aber ich bin ziemlich sicher, es ist eine elegante Lösung mit cumsum (x == 0), nachdem Sie die NA konvertieren zu einem zählbaren Wert (zB 1). Siehe Top Antwort auf meine Frage hier: https://stackoverflow.com/questions/47289543/modify-certain-values-in-a-data-frame-by-indirect-reference-to-the-columns/47310247?noredirect= 1 # comment81573872_47310247 – Stanwood

Antwort

3
brand=c('MS', 'Google', 'Apple', 'MS', 'FB', 'Apple', 'Oracle') 
product=c('Window', 'Search', 'Iphone', 'Window', 'Network', 'Iphone', 'DB') 
isExist=c('Yes', 'Yes', NA, 'No', NA, 'Yes', NA) 
df= data.frame(brand, product, isExist) 

library(dplyr) 

df %>% 
    group_by(brand) %>%      # for each brand 
    filter(sum(!is.na(isExist)) == 0) %>% # get sum of values that are not NA and keep rows where the sum is 0 
    ungroup() 

# # A tibble: 2 x 3 
#  brand product isExist 
#  <fctr> <fctr> <fctr> 
# 1  FB Network <NA> 
# 2 Oracle  DB <NA> 

Der obige Prozess verstanden werden kann, wenn Sie diesen Schritt für Schritt ausgeführt werden (erste 2 Zeilen, dann zuerst 3 usw.)

df %>% 
    arrange(brand) %>%       # order brands to have a better visualisation 
    group_by(brand) %>%       # group by brand and create (on the background) 5 sub-datasets based on each brand (see the Groups: brand [5]) 
    mutate(Counter = sum(!is.na(isExist))) %>% # count how many times you have non NA values, based on a brand, and add it as a column while keeping all rows (this is like counting and joining back to the original dataset at the same time) 
    filter(Counter == 0) %>%     # keep only rows with Counter = 0 (those are the ones with only NA values) 
    ungroup()         # forget the grouping 
+0

Danke, diese Abfrage funktioniert. Können Sie mir bitte helfen zu verstehen Nach Filter, es nur den Wert auswählen, die nicht NA so wie FB und Oracle kam im Bild, die NA-Werte hat – Vineet

+0

Ja, ich werde meine Antwort mit mehr Informationen aktualisieren. – AntoniosK

+0

ist es wie is.na funktioniert nur im Rahmen der Summe, so wird es keine Ausnahme geben und es filtert nicht die Hauptabfrage, ich bin von OOPS und SQL-Hintergrund so auf diese Weise denken, jetzt verstehe ich die Abfrage ... Ich bin beeindruckt die Art, wie Sie mit diesem Problem umgehen ..great – Vineet

Verwandte Themen