2017-03-05 3 views
0

Ich habe einen Datensatz mit einer Million Datensätze, die ich nach der ersten Unterteilung der Daten aggregieren muss. Es ist schwierig, eine gut reproduzierbare Probe zu liefern, weil in diesem Fall die Stichprobengröße ziemlich groß wäre - aber ich werde es trotzdem versuchen.Aggregation nach Teilmengen in dplyr

Eine Stichprobe der Daten, die ich mit wie folgt aussieht arbeite:

> df 
     auto_id user_id month 
164537 7124 240249 10 
151635 7358 226423  9 
117288 7376 172463  9 
177119 6085 199194 11 
128904 7110 141608  9 
157194 7143 241964  9 
71303  6090 141646  7 
72480  6808 175910  7 
108705 6602 213098  8 
97889  7379 185516  8 
184906 6405 212580 12 
37242  6057 197905  8 
157284 6548 162928  9 
17910  6885 194180 10 
70660  7162 161827  7 
8593  7375 207061  8 
28712  6311 176373 10 
144194 7324 142715  9 
73106  7196 176153  7 
67065  7392 171039  7 
77954  7116 161489  7 
59842  7107 162637  7 
101819 5994 182973  9 
183546 6427 142029 12 
102881 6477 188129  8 

In jedem Monat gibt viele Anwender, die die gleichen sind, und wir sollten zuerst von Monat Teilmenge und eine Frequenztabelle machen des Benutzers und die Menge an Reisen genommen (leider in der Stichprobe, oben gibt es nur eine Fahrt pro Benutzer ist, sondern in der größeren Datenmenge, das ist nicht der Fall ist):

full_data <- full_data[full_data$month == 7,] 
users <- as.data.frame(table(full_data$user_id)) 
head(users) 
    Var1 Freq 
1 100231 10 
2 100744 17 
3 111281 1 
4 111814 2 
5 113716 3 
6 117493 3 

wie wir können Sehen Sie im vollen Datensatz im Monat o Im Juli (Monat = 7) haben Benutzer mehrere Reisen unternommen. Nun ist die wichtige Rolle - die nur die oberen 10% dieser Nutzer (die oberen 10% in Bezug auf Freq)

tenPercent = round(nrow(users)/10) 
users <- users[order(-users$Freq),] 
topten <- head(users, n = tenPercent) 

Jetzt ist die neue Datenrahmen der Teilmenge ist - topten - summiert werden können, und wir bekommen die Menge an durch die besten zehn Prozent der Nutzer Reise genommen

sum(topten$Freq) 
[1] 12147 

Am Ende wie dies die Ausgabe

> output 
    month trips 
1  7 12147 
2  8 ... 
3  9 ... 
4  10 ... 
5  11 ... 
6  12 ... 

gibt es eine Möglichkeit, diesen Prozess zu automatisieren mit 012.345 aussehen soll- Ich meine speziell die Untermenge von den Top Ten Prozent? Ich habe versucht

output <- full_data %>% 
+  group_by(month) %>% 
+  summarise(n = n()) 

Aber dies aggregiert nur die Gesamtzahl der Reisen nach Monat. Könnte jemand vorschlagen, diesen Teil in die Abfrage in dplyr zu integrieren? :

tenPercent = round(nrow(users)/10) 
users <- users[order(-users$Freq),] 
topten <- head(users, n = tenPercent) 

Antwort

1

Der folgende Code zählt die Anzahl der Zeilen für jede user_id in jedem month, und wählt dann die 10% der Nutzer mit den meisten Zeilen in jedem Monat und summiert sie. Lass es mich wissen, wenn es dein Problem löst.

library(dplyr) 

full_data %>% group_by(month, user_id) %>% 
    tally %>% 
    group_by(month) %>% 
    filter(percent_rank(n) >= 0.9) %>% 
    summarise(n_trips = sum(n)) 

UPDATE: auf Ihrem Kommentar Nach oben, lassen Sie sich mit einigen gefälschten Daten einen Scheck tun. Im Folgenden haben wir 30 verschiedene Werte von user_id und 10.000 Gesamtzeilen. Ich habe auch das Argument prob verwendet, so dass die Wahrscheinlichkeit, dass ein user_id ausgewählt wird, proportional zu seinem Wert ist (d. H. user_id 1 ist am wenigsten wahrscheinlich gewählt und user_id 30 ist am ehesten zu wählen).

set.seed(3) 
full_data = data.frame(user_id=sample(1:30,10000, replace=TRUE, prob=1:30), 
         month=sample(1:12, 10000, replace=TRUE)) 

ist als die Anzahl der Zeilen für jede user_id für month==1 aussehen lassen. Der folgende Code zählt die Anzahl der Zeilen für jede user_id und sortiert von den meisten zu den wenigsten gemeinsamen. Beachten Sie, dass die drei häufigsten Werte user_id (28,29,26) 171 Zeilen (60 + 57 + 54) umfassen.Da es 30 verschiedene Werte von user_id die drei Benutzer repräsentieren die Top 10% der Nutzer:

full_data %>% filter(month==1) %>% 
    group_by(month, user_id) %>% 
    tally %>% 
    arrange(desc(n)) %>% as.data.frame 
month user_id n 
1  1  28 60 
2  1  29 57 
3  1  26 54 
4  1  30 53 
5  1  27 49 
6  1  22 43 
7  1  21 41 
8  1  20 40 
9  1  23 40 
10  1  24 38 
11  1  25 38 
12  1  19 37 
13  1  18 33 
14  1  16 28 
15  1  15 27 
16  1  17 27 
17  1  14 26 
18  1  9 20 
19  1  12 20 
20  1  13 20 
21  1  10 17 
22  1  11 17 
23  1  6 15 
24  1  7 13 
25  1  8 13 
26  1  4 9 
27  1  5 7 
28  1  2 3 
29  1  3 2 
30  1  1 1 

So, jetzt wollen wir den nächsten Schritt machen und die Top 10% der Nutzer auswählen. Um die Frage in Ihrem Kommentar zu beantworten, behält filter(percent_rank(n) >= 0.9) nur die oberen 10% von user_id, basierend auf dem Wert n (das ist die Anzahl der Zeilen für jede user_id). percent_rank ist eine von mehreren Ranking-Funktionen in dplyr, die verschiedene Möglichkeiten haben, mit Bindungen umzugehen (was der Grund sein kann, warum Sie nicht die Ergebnisse erhalten, die Sie erwarten). Siehe ?percent_rank für Details:

full_data %>% filter(month==1) %>% 
    group_by(month, user_id) %>% 
    tally %>% 
    group_by(month) %>% 
    filter(percent_rank(n) >= 0.9) 
month user_id  n 
1  1  26 54 
2  1  28 60 
3  1  29 57 

und die Summe von n (die Gesamtzahl der Fahrten, für die Top-10%) ist:

full_data %>% filter(month==1) %>% 
    group_by(month, user_id) %>% 
    tally %>% 
    group_by(month) %>% 
    filter(percent_rank(n) >= 0.9) %>% 
    summarise(n_trips = sum(n)) 
month n_trips 
1  1  171 

So sieht es aus wie die Code macht das, was wir naiv erwarten würden, aber vielleicht hängt das Problem damit zusammen, wie mit Bindungen umgegangen wird. Lassen Sie mich wissen, ob Sie immer noch anomale Ergebnisse in Ihren echten Daten erhalten oder ob ich falsch verstanden habe, was Sie erreichen wollen.

+0

Danke für den Versuch. Die Antworten sind ein wenig aus (ungefähr 1000 Reisen oder so weniger als erwartet), wie funktioniert 'filter (percent_rank (n)> = 0.9)'? –

Verwandte Themen