hier ein viel einfacher und schneller dplyr
methode:
df %>% group_by(gene) %>%
summarise_each(funs(.[which.max(abs(.))]))
Versuchen es auf reproduzierbare Daten:
set.seed(495)
opts <- seq(-0.5, 0.5, 0.05)
df <- data.frame(combo1=sample(opts, 6),
combo2=sample(opts, 6),
combo3=sample(opts, 6),
gene=rep(c("g1", "g2", "g3"), each=2), stringsAsFactors=F)
df
combo1 combo2 combo3 gene
1 -0.15 0.50 -0.25 g1
2 -0.45 -0.50 0.15 g1
3 -0.25 0.10 -0.30 g2
4 0.35 -0.40 -0.15 g2
5 -0.05 -0.35 -0.40 g3
6 0.15 -0.05 -0.10 g3
df %>% group_by(gene) %>%
summarise_each(funs(.[which.max(abs(.))]))
gene combo1 combo2 combo3
1 g1 -0.45 0.50 -0.25
2 g2 0.35 -0.40 -0.30
3 g3 0.15 -0.35 -0.40
Beachten Sie, dass im obigen Fall gibt es eine Krawatte in den Absolutwert für combo2
und gene=g1
. Wenn das wichtig ist, müssen Sie entscheiden, wie Sie Bindungen lösen.
Timings für meine dplyr
Verfahren und eine etwas schnellere Version data.table
Methode des @ mathematical.coffee (eine viel größere Probe Datenrahmen verwendet wird):
set.seed(495)
opts <- seq(-0.5, 0.5, 0.05)
df <- data.frame(combo1=sample(opts, 9e4, replace=TRUE),
combo2=sample(opts, 9e4, replace=TRUE),
combo3=sample(opts, 9e4, replace=TRUE),
gene=rep(c("g1", "g2", "g3"), each=3e4), stringsAsFactors=F)
microbenchmark::microbenchmark(
dplyr=setDF(df) %>% group_by(gene) %>%
summarise_each(funs(.[which.max(abs(.))])),
data.table={setDT(df)[, lapply(.SD, function (col) col[which.max(abs(col))]), by='gene']}
)
Unit: milliseconds
expr min lq mean median uq max neval cld
dplyr 10.013623 11.839132 14.156735 12.284574 12.675220 32.35739 100 b
data.table 4.434841 6.008701 6.947104 6.222775 6.415083 29.52652 100 a
So sind die data.table
läuft Version in etwa der Hälfte der Zeit der dplyr
Version.
UPDATE: Um Adresse @ Arun Kommentar, hier ist ein viel größerer Probendatenrahmen mit mehreren Spalten und mehr gene
Kategorien.
# Large sample of fake data
set.seed(194)
genes=apply(expand.grid(letters,letters), 1, paste, collapse="")
df = data.frame(replicate(50, rnorm(26*26*1e3)), gene=genes)
object.size(df)
# 273 MB
microbenchmark::microbenchmark(
dplyr=setDF(df) %>% group_by(gene) %>%
summarise_each(funs(.[which.max(abs(.))])),
data.table={setDT(df)[, lapply(.SD, function (col) col[which.max(abs(col))]), by='gene']},
times=10
)
Unit: milliseconds
expr min lq mean median uq max neval cld
dplyr 1240.1695 1299.0425 1375.8298 1318.5343 1385.5854 1748.8112 10 b
data.table 464.5597 493.8959 527.7097 519.3607 585.1482 603.3916 10 a
UPDATE 2: Wie oben, aber mit einer noch größeren Anzahl von Gruppen (26^3 anstelle von 26^2). Wie @Arun diskutiert, steigt der Geschwindigkeitsvorteil mit der größeren Anzahl von Gruppen.
# Large sample of fake data
set.seed(194)
genes=apply(expand.grid(letters,letters,letters), 1, paste, collapse="")
df = data.frame(replicate(50, rnorm(26*26*26*50)), gene=genes)
object.size(df)
# 356 MB
microbenchmark::microbenchmark(
dplyr=setDF(df) %>% group_by(gene) %>%
summarise_each(funs(.[which.max(abs(.))])),
data.table={setDT(df)[, lapply(.SD, function (col) col[which.max(abs(col))]), by='gene']},
times=1
)
Unit: seconds
expr min lq mean median uq max neval
dplyr 27.567790 27.567790 27.567790 27.567790 27.567790 27.567790 1
data.table 2.765047 2.765047 2.765047 2.765047 2.765047 2.765047 1
Sie möchten wahrscheinlich 'set.seed' vor dem Erstellen eines zufälligen Beispieldatensatzes verwenden. – Frank