2017-04-25 2 views
0

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.

Antwort

2

zu lange Format gehen ...

mDT = melt(DT, meas=patterns("ratio"), value.name = "ratio") 
setorder(mDT, variable, yr, ratio) 
mDT[, dec := cut(.I, 10, labels = FALSE), by=.(yr, variable)] 

mDT[, .(
    mval = mean(val), 
    mrat = mean(ratio), 
    wmval = weighted.mean(val, weight), 
    wmrat = weighted.mean(ratio, weight) 
), keyby=.(variable, dec)] 

    variable dec   mval  mrat  wmval wmrat 
1: ratio 1 -0.0279943849 3.576939 -0.039512050 3.572319 
2: ratio 2 -0.0011460087 4.329835 0.005093692 4.331433 
3: ratio 3 -0.0090873863 4.784103 -0.012764902 4.767494 
4: ratio 4 -0.0149614666 5.094431 -0.015464918 5.110614 
5: ratio 5 0.0147052939 5.373705 0.015276699 5.364962 
6: ratio 6 -0.0101956297 5.645182 -0.014102394 5.618484 
7: ratio 7 0.0012979528 5.949583 -0.012839401 5.925634 
8: ratio 8 -0.0093009096 6.265297 -0.007141404 6.263371 
9: ratio 9 0.0129705386 6.651047 0.018474949 6.684825 
10: ratio 10 0.0038414948 7.363449 -0.004225650 7.351828 
11: ratio2 1 -0.0120823787 1.195964 -0.016154551 1.199026 
12: ratio2 2 -0.0072534833 1.904354 -0.030409684 1.908494 
13: ratio2 3 -0.0283728080 2.282277 -0.028168936 2.301685 
14: ratio2 4 -0.0068901529 2.590815 0.002836866 2.585152 
15: ratio2 5 -0.0035769658 2.880104 0.002391468 2.872702 
16: ratio2 6 0.0087575593 3.147469 0.004565452 3.134459 
17: ratio2 7 -0.0052354409 3.412187 -0.005866282 3.426711 
18: ratio2 8 0..704371 0.009488475 3.701694 
19: ratio2 9 0.0027419978 4.071582 -0.008958386 4.076264 
20: ratio2 10 -0.0002925368 4.786477 0.003691116 4.772209 
+0

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. –

+1

@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

+0

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. –

Verwandte Themen