Ich habe eine Menge von Variablen (ungefähr 21), die ich durchlaufen möchte und tue für jedes folgendes: 1. Gruppiere in 10 Gruppen nach Jahr, wobei Gruppen durch Dezile der jährlichen Verteilung bestimmt sind. 2. Berechne bedeutet (gleich und gewichtet) basierend auf diesen neuen Gruppen.Schleife in R data.table: Erzeuge Gruppen durch variable Verteilung, dann berechne Mittel durch neue Gruppen
Testdaten:
set.seed(4)
YR = data.table(yr=1962:2015)
ID = data.table(id=10001:11000)
DT <- YR[,as.list(ID), by = yr] # intentional cartesian join
rm("YR","ID")
# 54,000 obs now add data
DT[,`:=` (ratio = rep(sample(10),each=5400)+rnorm(nrow(DT)),
ratio2 = rep(sample(5),each=10800)+rnorm(nrow(DT)),
weight = abs(rnorm(nrow(DT)))*100,
val = rnorm(nrow(DT))
)]
DT
yr id ratio ratio2 weight val
1: 1962 10001 6.689275 4.895357 129.10487 -0.2022073
2: 1962 10002 4.718753 4.505419 140.70420 -0.0887587
3: 1962 10003 5.786855 4.359488 242.10988 0.9511465
4: 1962 10004 7.896540 4.049974 89.23235 -1.3822148
5: 1962 10005 7.776863 2.233036 177.79650 -1.0671091
---
53996: 2015 10996 10.613272 3.345091 153.81424 0.9269429
53997: 2015 10997 11.260932 1.804315 15.68129 -1.6618414
53998: 2015 10998 8.591909 3.332643 134.80929 -1.1632596
53999: 2015 10999 9.143039 3.012160 178.77301 -0.4761060
54000: 2015 11000 7.470945 4.068919 121.13470 -1.7594423
Also, ich möchte durch Verhältnis zu Schleife, dann Ratio2 usw. Computing Dezilen jeder, dann durch jedes dieser neu berechneten Dezilen zusammenfassend val. Beachten Sie, dass dies keine nummerierten Variablen sind, sodass ich die Namen nicht mit paste() und einem 1:21 Vektor erstellen kann. Zuerst schrieb ich diese Funktion, um die Gruppierung zu tun:
# [function] pctl.grp - order data into groups based on percentil breakpoints
# Number of groups passed
pctl.grp <- function(dat, grp) {
bp <- quantile(dat, probs = c(0,seq(100/grp,100,100/grp))/100)
cut(dat,bp,labels = FALSE, include.lowest = TRUE)
}
Dann kann ich eine Iteration wie folgt tun:
# adds in new variable containing 10 groups numbered 1-10
DT[,ratiogrp := lapply(.SD, pctl.grp, 10), by = .(yr), .SDcols = c("ratio")]
DT[,.(ewval = mean(val),
ewratio = mean(ratio),
vwval = weighted.mean(val, weight, na.rm = TRUE),
vwratio = weighted.mean(ratio, weight, na.rm = TRUE)) ,by=ratiogrp][order(ratiogrp)]
, die das gewünschte Ergebnis liefert:
ratiogrp ewval ewratio vwval vwratio
1: 1 -0.027994385 3.576939 -0.039512050 3.572319
2: 2 -0.001146009 4.329835 0.005093692 4.331433
3: 3 -0.009087386 4.784103 -0.012764902 4.767494
4: 4 -0.014961467 5.094431 -0.015464918 5.110614
5: 5 0.014705294 5.373705 0.015276699 5.364962
6: 6 -0.010195630 5.645182 -0.014102394 5.618484
7: 7 0.001297953 5.949583 -0.012839401 5.925634
8: 8 -0.009300910 6.265297 -0.007141404 6.263371
9: 9 0.012970539 6.651047 0.018474949 6.684825
10: 10 0.003841495 7.363449 -0.004225650 7.351828
Aber wie mache ich das 21 Mal durch jede Variable? Ich kann leicht den Namen meiner Variablen wie diese:
> grep(c("ratio"), names(DT))
[1] 3 4
> names(DT)[grep(c("ratio"), names(DT))]
[1] "ratio" "ratio2"
So denkt ein for (z in 1:length(namelist)) {}
oder etwas funktionieren wird. Aber ich bin mir nicht sicher, wie ich dann auf diese Namen (oder Zahlen) innerhalb der data.table-Struktur verweisen soll, um das, was ich oben gemacht habe, neu zu erstellen.
Brilliant. Ich bin mir nicht sicher, warum cut (I., 10, Labels = FALSE) das gleiche Ergebnis liefert wie meine Funktion. Ich habe meine pctl.grp() -Funktion für cut() ersetzt und bekam, was ich wollte. –
@JesseBlocher Cool, froh, dass es funktioniert. '.I' ist nur der Vektor zusammenhängender Zeilennummern (da die Daten nach Jahr und Variable sortiert sind), einige Vektoren' n: m'; 'cut (n: m, 10, labels = FALSE)' schneidet die Zeilen in 10 gleich große Gruppen; und da die Daten nach Verhältnis sortiert sind, sind diese Gruppen ihre Dezile. Die Labels = FALSE Teil bedeutet, dass es den Dezilen Ganzzahlen zuweist. Art von verschachtelt, ich weiß .... – Frank
Ich bin mir ziemlich sicher, dass "cut (x, 10)" Zeilen nicht in gleich große Gruppen setzt. Wenn Sie 'x <-rnorm (100)', dann 'c <- cut (x, 10, labels = FALSE)' machen und ein Histogramm von 'c' machen, sollten Sie die gleiche Höhe haben und das nicht. Vergleiche mit meiner Funktion. Das ist nicht der Punkt hier - ich denke, meine Beispieldaten sind zufällig einheitlich, so dass beide gleich zu sein scheinen. –