2016-08-08 3 views
3

überschreitet habe ich eine Datenbank, bestehend ausFilter innerhalb von Gruppen, wobei x ersten y

  • Nachbarschaft IDs für die Heimatstadtteile (id_h),
  • Block-IDs für die Heimblocks (blk_h,
  • eine Unter Geographie von Nachbarschaften),
  • Arbeitsblöcke (blk_w),
  • die Strömung der Pendler zwischen den beiden (Flow),
  • der mittlere Pendler pro Wohnviertel (Med_C) und
  • der kumulative Arbeiterfluss von zu Hause Nachbarschaft (CumFlow).

Die Daten werden durch den Abstand zwischen blk_h und blk_w (absteigend) sortiert, gruppiert nach id_h. Ich muss die Daten aufteilen, um den Fall für jede Wohngegend zu extrahieren, in der CumFlow FIRST gleich oder größer ist als Med_C.

Ich habe eine Vielzahl von dplyr-Funktionen ausprobiert und kann es nicht funktionieren. Hier ein Beispiel:

df <- data.frame(
    id_h=c("A","A","A","A","B","B","B"), 
    blk_h=c("A1","A1","A2","A2","B1","B2","B2"), 
    blk_w=c("W1","W2","W3","W3","W1","W2","W2"), 
    dist=c(4.3,5.6,7.0,8.7,5.2,6.5,6.8), 
    Flow=c(3,6,3,7,5,4,2), 
    CumFlow=c(3,9,12,19,5,9,11), 
    Med_C=c(10,10,10,10,6,6,6) 
) 
df 

Ich brauche dafür eine Tabelle wie folgt zurück:

id_h blk_h blk_w dist Flow CumFlow Med_C 
A  A2  W3  7.0 3  12  10 
B  B2  W2  6.5 4  9  6 

Und hier sind einige der Dinge, die ich habe versucht, dies zu verwirklichen: Versuch # 1

library(dplyr) 
df.g <- group_by(df, id_h) 
df.g2 <- filter(df.g, CumFlow == which.min(CumFlow >= Med_C)) 

Versuch # 2

library(data.table) 
setDT(df)[, .SD[which.min(CumCount >= Med_C)], by = id_h] 

Versuch # 3

library(dplyr) 
test <- df %>% group_by(id_h) %>% filter(min(CumFlow) >= Med_C) 

Ich glaube, ich bin Missverständnis, wie die which.min Funktion verwenden. Jeder Rat wird sehr geschätzt.

+2

Ja, es ist Verwirrung von 'which.min', die findet das erste Minimum statt des ersten wahren Wertes; und wenn alle Werte gleich sind, gibt 1 zurück. Sie können 'head (welches (CumFlow> = Med_C), 1)' anstelle von which.min hier verwenden. – Frank

+0

@majom Ich erwähnte dies auch das letzte Mal: ​​Bearbeite Tags nicht in Fragen, die auf den Antworten basieren. – Frank

+0

@ Frank: Die Frage in diesem Fall fragt speziell, wie man mit 'data.table' dazu kommt. Somit ist das Tag legitim. Siehe Versuch "# 2' library (data.table); setDT (df) [, .SD [which.min (CumCount> = Med_C)], by = id_h] '". Für allgemeine Richtlinien zum Tagging siehe http://meta.stackexchange.com/questions/37672/when-should-you-edit-tags – majom

Antwort

1

Zwei filter Anrufe diese lösen können.

group_by Verwenden innerhalb jedes id_h zu arbeiten, wobei die erste filter gibt eine data.frame mit allen Zeilen, in denen die CumFlow größer oder gleich dem Med_C. Die zweite filter gibt innerhalb jeder id_h die Zeile mit der niedrigsten CumFlow zurück. Dies funktioniert nur, weil die Daten sortiert sind. Um die Arbeit robuster zu gestalten, sollten Sie in Erwägung ziehen, nach dem Anruf zu arrange einen Anruf zu group_by hinzuzufügen.

library(dplyr) 

df <- data.frame(
    id_h = c("A","A","A","A","B","B","B"), 
    blk_h = c("A1","A1","A2","A2","B1","B2","B2"), 
    blk_w = c("W1","W2","W3","W3","W1","W2","W2"), 
    dist = c(4.3,5.6,7.0,8.7,5.2,6.5,6.8), 
    Flow = c(3,6,3,7,5,4,2), 
    CumFlow = c(3,9,12,19,5,9,11), 
    Med_C = c(10,10,10,10,6,6,6) 
) 
df 

df %>% 
group_by(id_h) %>% 
filter(CumFlow >= Med_C) %>% 
filter(CumFlow == min(CumFlow)) 
+0

Das war es !! Vielen, vielen Dank. Ich verstehe jetzt, dass ich zwei Filter brauche. – jpg05

2

Sie können es mit dplyr gefällt das

df %>% group_by(id_h) %>% 
    mutate(times_greater = cumsum(CumFlow >= Med_C)) %>% 
    filter(times_greater == 1) 
+1

Ich nahm an, dass der kumulative Fluss immer anstieg, und med_c war konstant, aber es war unklar von der Frage. – shayaa

+0

Ich bekomme die richtige Anzahl von Zeilen mit dieser Lösung. Also denke ich, dass sowohl dies als auch Peters dplyr-Lösung funktionieren. Vielen Dank! – jpg05

+0

Es ist Pendlerfluss, aber ich habe das kumulative berechnet, also helfen, das blk_h und das blk_w Paar zu identifizieren, das den mittleren Arbeiter enthielt. – jpg05

3

Zwei Dinge:

  • Sie benötigen slice statt filter (die einen Index nimmt) (die booleans nimmt) und
  • da die Verwendung von which.min ungerade ist (es gibt den Index der erste Wert entspricht dem Minimum, und Sie haben eine Menge von 1s und 0s), benötigen Sie tatsächlich which.max, wie Sie den ersten Wert von 1 möchten, dh TRUE,

so

df %>% group_by(id_h) %>% 
    slice(which.max(CumFlow >= Med_C)) 
## Source: local data frame [2 x 7] 
## Groups: id_h [2] 
## 
##  id_h blk_h blk_w dist Flow CumFlow Med_C 
## <fctr> <fctr> <fctr> <dbl> <dbl> <dbl> <dbl> 
## 1  A  A2  W3 7.0  3  12 10 
## 2  B  B2  W2 6.5  4  9  6 
+2

'which.max', wenn die Bedingung niemals gilt, wird 1/erste Zeile zurückgeben, was in diesem Fall möglicherweise das ist, was das OP will. – Frank

+1

@Frank Messepunkt. Ich würde wahrscheinlich 'df%>% group_by (id_h)%>% filter (CumFlow> = Med_C)%>% slice (1)' für die Klarheit, ehrlich gesagt. – alistaire

+0

Ja, kommt nur darauf an, ob Sie die Gruppe löschen wollen, wenn sie dieses Kriterium nicht erfüllt oder nicht. Ich würde vielleicht "slice" (was (CumFlow> = Med_C) [1]) ', was meiner Meinung nach eine NA-Reihe ergeben würde. – Frank

2

A data.table Lösung würde wie folgt aussehen:

# Load package 
library(data.table) 

# Setup data 
df <- data.table(
    id_h=c("A","A","A","A","B","B","B"), 
    blk_h=c("A1","A1","A2","A2","B1","B2","B2"), 
    blk_w=c("W1","W2","W3","W3","W1","W2","W2"), 
    dist=c(4.3,5.6,7.0,8.7,5.2,6.5,6.8), 
    Flow=c(3,6,3,7,5,4,2), 
    CumFlow=c(3,9,12,19,5,9,11), 
    Med_C=c(10,10,10,10,6,6,6)) 

# Calculation 
df.out <- df[CumFlow >= Med_C, .SD[1], by = id_h] 

df.out sieht wie folgt aus:

> df.out 
    id_h blk_h blk_w dist Flow CumFlow Med_C 
1: A A2 W3 7.0 3  12 10 
2: B B2 W2 6.5 4  9  6 
+0

Er sagt mir, dass das = ein unbenutztes Argument ist. – jpg05

+0

Haben Sie die Daten so eingerichtet wie ich, dh mit 'df <- data.table (...' anstelle von 'df <- data.frame (...'). – majom

+0

Derp. Richtig. Das war es. – jpg05

Verwandte Themen