Frage Plotten nach Gruppe in data.table


Ich habe Daten auf individueller Ebene, für die ich versuche, ein Ergebnis dynamisch nach Gruppe zusammenzufassen.

Beispiel:

set.seed(12039)
DT <- data.table(id = rep(1:100, each = 50),
                 grp = rep(letters[1:4], each = 1250),
                 time = rep(1:50, 100),
                 outcome = rnorm(5000))

Ich möchte den einfachsten Weg kennen, um die Zusammenfassung auf Gruppenebene darzustellen, deren Daten enthalten sind in:

DT[ , mean(outcome), by = .(grp, time)]

Ich wollte etwas wie:

dt[ , plot(mean(outcome)), by = .(grp, time)]

Aber das funktioniert überhaupt nicht.

Die praktikable Option, die ich überlebte (die ziemlich einfach geloopt werden konnte) ist:

plot(DT[grp == "a", mean(outcome), by = time])
lines(DT[grp == "b", mean(outcome), by = time])
lines(DT[grp == "c", mean(outcome), by = time])
lines(DT[grp == "d", mean(outcome), by = time])

(mit zusätzlichen Parametern für Farben, etc., ausgeschlossen für Prägnanz)

Dies scheint mir nicht der beste Weg, dies zu tun data.tableHandwerk im Umgang mit Gruppen, gibt es keine elegantere Lösung?

Andere Quellen haben mich darauf hingewiesen matplot aber ich kann keinen direkten Weg sehen, es zu benutzen - muss ich umgestalten DTund gibt es ein einfaches reshape das würde die Arbeit erledigen?


5
2018-02-08 23:06


Ursprung


Antworten:


Base R Lösung mit matplot und dcast

dt_agg <- dt[ , .(mean = mean(outcome)), by=.(grp,time)]
dt_cast <- dcast(dt_agg, time~grp, value.var="mean")
dt_cast[ , matplot(time, .SD[ , !"time", with=FALSE],
                   type="l", ylab="mean", xlab="")]
#or, if you've got the data.table version 1.9.7+:
#  (see https://github.com/Rdatatable/data.table/wiki/Installation)
dt_cast[ , matplot(time, .SD, type="l", ylab="mean", xlab=""), .SDcols = !"time"]

Ergebnis: enter image description here


4
2018-02-09 09:01



Sie sind sehr auf dem richtigen Weg. Benutzen ggplot um dies wie folgt zu tun:

(dt_agg <- dt[,.(mean = mean(outcome)),by=list(grp,time)]) # Aggregated data.table
     grp time        mean
  1:   a    1  0.75865672
  2:   a    2  0.07244879
 ---

Jetzt ggplot diese aggregierte data.table

require(ggplot2)
ggplot(dt_agg, aes(x = time, y = mean, col = grp)) + geom_line()

Ergebnis: enter image description here


4
2018-02-08 23:46



Es gibt eine Möglichkeit, dies zu tun data.tableist es by Argument wie folgt:

DT[ , mean(outcome), by = .(grp, time)
    ][ , {plot(NULL, xlim = range(time),
           ylim = range(V1)); .SD}
       ][ , lines(time, V1, col = .GRP), by = grp]

Beachten Sie, dass das Zwischenprodukt {...; .SD} Teil ist notwendig, um weiter zu verketten. Ob DT[ , mean(outcome), by = .(grp, time)] wurden bereits als andere gespeichert data.table, DT_m, dann könnten wir einfach tun:

DT_m[ , plot(NULL, xlim = range(time), ylim = range(V1))]
DT_m[ , lines(time, V1, col = .GRP), by = grp]

Mit Ausgabe

data.table group by

Viel schickere Ergebnisse sind möglich; Wenn wir beispielsweise bestimmte Farben für jede Gruppe angeben möchten:

grp_col <- c(a = "blue", b = "black",
             c = "darkgreen", d = "red")
DT[ , mean(outcome), by = .(grp, time)
    ][ , {plot(NULL, xlim = range(time),
           ylim = range(V1)); .SD}
       ][ , lines(time, V1, col = grp_col[.BY$grp]), by = grp]

HINWEIS

Es gibt einen Fehler in RStudio, der dazu führt, dass dieser Code fehlschlägt wenn die Ausgabe an das RStudio-Grafikgerät gesendet wird. Daher funktioniert dieser Ansatz nur von R auf der Kommandozeile oder von dem Senden der Ausgabe an ein externes Gerät (ich schickte es an png um das oben genannte zu produzieren).

Sehen data.table Ausgabe # 1524, Dieses RStudio-Supportticketund diese SO Qs (1 und 2)


4
2017-08-31 18:14



Mit reshape2 können Sie den Datensatz in etwas mit Mitteln umwandeln:

new_dt <- dcast(dt,time~grp,value.var='outcome',fun.aggregate=mean)

new_dt_molten <- melt(new_dt,id.vars='time')

und dann plotten Sie es mit ggplot2 wie folgt:

ggplot(new_dt_molten,aes(x=time,y=value,colour=variable)) + geom_line()

Alternativ, (eigentlich einfachere Lösung) können Sie das Dataset, das Sie direkt haben, verwenden und so etwas tun:

ggplot(dt,aes(x=time,y=outcome,colour=grp)) + geom_jitter() + geom_smooth(method='loess')

oder

ggplot(dt,aes(x=time,y=outcome,colour=grp)) + geom_smooth(method='loess')

0
2018-02-08 23:26