web-dev-qa-db-fra.com

Multipliez plusieurs colonnes par une autre colonne spécifique de R avec data.table?

J'ai un grand data.table dans R avec plusieurs colonnes avec des valeurs en dollars. Dans une colonne différente, j'ai un numéro d'ajustement de l'inflation. J'essaie de comprendre comment mettre à jour chacune de mes colonnes monétaires avec la multiplication par la colonne de correction de l'inflation. Supposons que j'ai les données:

   DT <- data.table(id=1:1000,year=round(runif(1000)*10), 
          inc1 = runif(1000), inc2 = runif(1000), inc3 = runif(1000),    
          deflator = rnorm(1000))

qui donne la sortie:

             id year      inc1      inc2       inc3    deflator
   1:    1    8 0.4754808 0.6678110 0.41533976 -0.64126988
   2:    2    2 0.6568746 0.7765634 0.70616373  0.39687915
   3:    3    6 0.8192947 0.9236281 0.90002534 -0.69545700
   4:    4    4 0.7781929 0.1624902 0.17565790  0.05263055
   5:    5    7 0.6232520 0.8024975 0.86449836  0.70781887
  ---                                                     
 996:  996    2 0.9676383 0.2238746 0.19822000  0.78564836
 997:  997    9 0.9877410 0.5783748 0.57497438 -1.63365223
 998:  998    8 0.2220570 0.6500632 0.19814932  1.00260174
 999:  999    3 0.4793767 0.2830457 0.54835581  1.04168818
1000: 1000    8 0.2003476 0.6121637 0.02921505  0.34933690

en réalité, j'ai inc1 - inc100, plutôt que trois variables et je veux trouver un moyen d'effectuer cette action:

DT[, inc1 := inc1 * deflator]

pour chacune de mes colonnes de 100 revenus (inc1, inc2, inc3 dans les fausses données ci-dessus). J'aurai plus de 100 colonnes dans le futur, donc j'aimerais trouver un moyen de boucler l'action sur les colonnes. Y at-il un moyen de faire cela pour toutes les colonnes de revenu à la fois?

Je voudrais faire quelque chose comme:

inc_cols = c(inc1, inc2, inc3)

DT[, inc_cols := lapply(inc_cols,function(x)= x * deflator),]

ou

DT[, inc_cols := lapply(.SD,function(x)= x * deflator),.SDcols = inc_cols]

mais ni l'un ni l'autre ne semblent fonctionner. J'ai aussi essayé d'utiliser la fonction get() pour préciser que deflator est une référence à une colonne, telle que:

DT[, inc_cols := lapply(.SD,function(x)= x * get(deflator)),.SDcols = inc_cols]

mais n'a pas eu de chance. J'ai aussi essayé de parcourir les variables avec quelque chose comme:

for (var in inc_cols) {
  print(var)
  DT[, get(var) := get(var) *infAdj2010_mult] 
}

qui retourne

[1] "inc1"
 Error in get(var) : object 'inc1' not found 

Je me rends compte que c’est probablement une question simple et j’ai essayé de chercher les autres questions ici et divers guides et tutoriels en ligne, mais je ne trouve pas d’exemple correspondant à mon problème spécifique. C'est semblable à cette question , mais pas exactement. 

Merci de votre aide!

28
johneric

Tu pourrais essayer

DT[, (inc_cols) := lapply(.SD, function(x) 
        x * DT[['deflator']] ), .SDcols = inc_cols]
head(DT1,2)
#   id year         inc1         inc2       inc3   deflator
#1:  1    3  0.614838304  0.009796974  0.3236051  0.7735552
#2:  2    2 -0.001583579 -0.082289606 -0.1365115 -0.6644330

Ou si vous avez besoin d'une boucle

for(inc in inc_cols){
  nm1 <- as.symbol(inc)
  DT[,(inc):= eval(nm1)*deflator]
}

 head(DT,2)
 #  id year         inc1         inc2       inc3   deflator
 #1:  1    3  0.614838304  0.009796974  0.3236051  0.7735552
 #2:  2    2 -0.001583579 -0.082289606 -0.1365115 -0.6644330

Ou une option possible utilisant set qui devrait être très rapide car le surcoût de [.data.table est évité (suggéré par @Arun)

indx <- grep('inc', colnames(DT))

for(j in indx){
 set(DT, i=NULL, j=j, value=DT[[j]]*DT[['deflator']])
}
head(DT,2)
#  id year         inc1         inc2       inc3   deflator
#1:  1    3  0.614838304  0.009796974  0.3236051  0.7735552
#2:  2    2 -0.001583579 -0.082289606 -0.1365115 -0.6644330

où 

inc_cols <-  grep('^inc', colnames(DT), value=TRUE)

les données

set.seed(24)
DT <- data.table(id=1:1000,year=round(runif(1000)*10), 
      inc1 = runif(1000), inc2 = runif(1000), inc3 = runif(1000),    
      deflator = rnorm(1000)) 
23
akrun

Puisque vous pouvez utiliser dplyr sur data.tables, vous pouvez aussi faire:

library(dplyr)
DT %>% mutate_each(funs(.*deflator), starts_with("inc"))

Ce qui multipliera chaque colonne de DT commençant par "inc" par la colonne "déflateur".

18
docendo discimus

Cette approche est également très pratique, mais probablement plus lente que set()

library(data.table); library(magrittr)
set.seed(42)
DT <- data.table(id=1:1000,year=round(runif(1000)*10),
          inc1 = runif(1000), inc2 = runif(1000), inc3 = runif(1000),
          deflator = rnorm(1000))
vars <- names(DT) %>% .[grepl("inc", .)]
DT[, (vars) := .SD * deflator, .SDcols = vars]
DT[]

        id year         inc1        inc2        inc3   deflator
   1:    1    9  0.212563676  0.24806366  0.06860638  0.2505781
   2:    2    9 -0.017438715 -0.12186792 -0.26241497 -0.2779240
   3:    3    3 -1.414016119 -1.20714809 -0.76920337 -1.7247357
   4:    4    8 -1.082336969 -1.78411512 -1.08720698 -2.0067049
   5:    5    6 -0.644638321 -1.07757416 -0.20895576 -1.2918083
  ---                                                          
 996:  996    1 -0.573551720 -1.93996157 -0.50171303 -2.1569621
 997:  997    5 -0.007899417 -0.01561619 -0.05708009 -0.0920275
 998:  998    1 -0.090975121 -0.30475714 -0.27291825 -0.3974001
 999:  999    5 -0.045984079 -0.01563942 -0.07868934 -0.1383273
1000: 1000    0 -0.785962308 -0.63266975 -0.29247974 -0.8257650
1
chandler