Ich versuche aus Geschwindigkeitsgründen, meinen Datenmanipulationscode von dplyr
in data.table
umzuwandeln. Ich bin fast da, aber ich verpasse den letzten Schritt.
Ich habe einige Beispieldaten, um mein Problem zu replizieren.
c_dt = data.table(u_id=rep(c("u1", "u2"),each=5),
p_id=c("p1", "p1", "p1", "p2","p2", "p1", "p2", "p2", "p2", "p2" ),
c_dt=c("2015-12-01", "2015-12-02", "2015-12-03", "2015-12-02",
"2015-12-05", "2015-12-02", "2015-12-03", "2015-12-04",
"2015-12-05", "2015-12-06"))
Ich möchte die Zeilen identifizieren, in denen u_id
und p_id
dupliziert werden. und behalten Sie nur die Zeile mit dem Minimum c_dt
bei (behalten Sie im Wesentlichen die erste Instanz bei). Ich verwende dafür den folgenden dplyr
Code:
c_df <- as.data.frame(c_dt)
cdedup_df <- c_df %>% group_by(p_id, u_id) %>% filter(c_dt == min(c_dt))
Welche geben die folgende Ausgabe
> cdedup_df
Source: local data frame [4 x 3]
Groups: p_id, u_id
u_id p_id c_dt
1 u1 p1 2015-12-01
2 u1 p2 2015-12-02
3 u2 p1 2015-12-02
4 u2 p2 2015-12-03
Ich habe den folgenden data.table
Code, der die erforderlichen Zeilen korrekt identifiziert, aber ich kann nicht herausfinden, wie nur die Zeile gefiltert werden soll.
cdedup_dt <- c_dt[,c_dt == min(c_dt),by = list(u_id, p_id)]
cdedup_dt
u_id p_id V1
1: u1 p1 TRUE
2: u1 p1 FALSE
3: u1 p1 FALSE
4: u1 p2 TRUE
5: u1 p2 FALSE
6: u2 p1 TRUE
7: u2 p2 TRUE
8: u2 p2 FALSE
9: u2 p2 FALSE
10: u2 p2 FALSE
3 Antworten
Unter meinem Ansatz. Ich würde erwarten, dass es für große Datenmengen besser skaliert, da es keine min
von group
gibt, sondern nur eine einzige Sortierung, die data.table sehr effizient macht, und dann zuerst nach Gruppen unterteilt.
setorderv(c_dt, "c_dt")[, .SD[1L], .(u_id, p_id)]
# in data.table 1.9.7+ you can also use `head`
setorderv(c_dt, "c_dt")[, head(.SD, 1L), .(u_id, p_id)]
Der folgende Code enthält die Validierung der aktuellen anderen Antworten.
Wenn OP einen großen Datensatz bereitstellt, kann ich Benchmarks hinzufügen.
library(data.table)
c_dt = data.table(u_id=rep(c("u1", "u2"),each=5), p_id=c("p1", "p1", "p1", "p2","p2", "p1", "p2", "p2", "p2", "p2" ), c_dt=c("2015-12-01", "2015-12-02", "2015-12-03", "2015-12-02", "2015-12-05", "2015-12-02", "2015-12-03", "2015-12-04", "2015-12-05", "2015-12-06"))
zero = c_dt[, list(c_dt=min(c_dt)), by=list(u_id, p_id)]
ananda = c_dt[, list(c_dt = c_dt[c_dt == min(c_dt)]), by = .(u_id, p_id)]
tal = c_dt[, .SD[rank(c_dt, ties.method = c("first")) == 1],by = .(u_id, p_id)]
all.equal(zero, ananda)
#[1] TRUE
all.equal(ananda, tal)
#[1] TRUE
jan = setorderv(c_dt, "c_dt")[, .SD[1L], .(u_id, p_id)]
all.equal(tal, jan)
#[1] TRUE
So etwas sollte den Trick machen:
c_dt[, list(c_dt=min(c_dt)), by=list(u_id, p_id)]
## u_id p_id c_dt
## 1: u1 p1 2015-12-01
## 2: u1 p2 2015-12-02
## 3: u2 p1 2015-12-02
## 4: u2 p2 2015-12-03
Sie stehen sich also sehr nahe. Sie haben lediglich .SD
in der Spalte j übergeben. Mal sehen, wie es funktioniert:
library(data.table)
c_dt = data.table(u_id=rep(c("u1", "u2"),each=5),
p_id=c("p1", "p1", "p1", "p2","p2", "p1", "p2", "p2", "p2", "p2" ),
c_dt=c("2015-12-01", "2015-12-02",
"2015-12-03", "2015-12-02", "2015-12-05",
"2015-12-02", "2015-12-03", "2015-12-04",
"2015-12-05", "2015-12-06"))
c_dt
u_id p_id c_dt
1: u1 p1 2015-12-01
2: u1 p1 2015-12-02
3: u1 p1 2015-12-03
4: u1 p2 2015-12-02
5: u1 p2 2015-12-05
6: u2 p1 2015-12-02
7: u2 p2 2015-12-03
8: u2 p2 2015-12-04
9: u2 p2 2015-12-05
10: u2 p2 2015-12-06
Jetzt gruppieren wir nach u_id und p_id und filtern nach dem Mindestwert von c_df :
cdedup_dt <- c_dt[ , .SD[c_dt == min(c_dt)], by = .(u_id, p_id)]
cdedup_dt
u_id p_id c_dt
1: u1 p1 2015-12-01
2: u1 p2 2015-12-02
3: u2 p1 2015-12-02
4: u2 p2 2015-12-03
Beachten Sie, dass .(u_id, p_id)
gleich list(u_id, p_id)
ist und .SD
sich auf die Teilmenge der Datentabelle für jede Gruppe bezieht. Alles, was Sie vermisst haben, ist das .SD
.
Wie von @ zero323 erwähnt, behält min Duplikate bei (was im Grunde bedeutet, dass wir in unserem Beispiel einige doppelte Zeilen haben). Wenn Sie nur einen Datensatz für jede Gruppe führen möchten, ist es sicherer, die Rangfunktion zu verwenden:
cdedup_dt <- c_dt[, .SD[rank(c_dt, ties.method = c("first")) == 1],by = .(u_id, p_id)]
cdedup_dt
u_id p_id c_dt
1: u1 p1 2015-12-01
2: u1 p2 2015-12-02
3: u2 p1 2015-12-02
4: u2 p2 2015-12-03
Neue Fragen
r
R ist eine kostenlose Open-Source-Programmiersprache und Softwareumgebung für statistisches Rechnen, Bioinformatik, Visualisierung und allgemeines Rechnen. Bitte geben Sie minimale und reproduzierbare Beispiele zusammen mit der gewünschten Ausgabe an. Verwenden Sie dput () für Daten und geben Sie alle Nicht-Basispakete mit library () -Aufrufen an. Betten Sie keine Bilder für Daten oder Code ein, sondern verwenden Sie stattdessen eingerückte Codeblöcke. Verwenden Sie für statistische Fragen https://stats.stackexchange.com.