Ma table de données dt0
est:
Error in `[.data.table`(dt0, , `:=`(as.name(paste0(c, "_t")), as.name(c) * : LHS of := must be a symbol, or an atomic vector (column names or positions).
ANSWERx
sont des pourcentages. SCORE100
est calculé comme SCORE100: = (100 * ANSWER1 * ANSCOUNT + 75 * ANSWER2 * ANSCOUNT + 50 * ANSWER3 * ANSCOUNT + 25 * ANSWER4 * ANSCOUNT) / (ANSWER1 * ANSCOUNT + ANSWER2 * ANSCOUNT + ANSWER3 * ANSCOUNT + ANSWER4 * ANSCOUNT + ANSWER5 * ANSCOUNT)]
Afin de recalculer SCORE100
pour toutes les lignes de mon ensemble de données,
Je dois automatiquement (en boucle) multiplier tous les ANSWERx
par ANSCOUNT
dans chaque ligne, puis ajouter toutes les multiplications obtenues, puis diviser par la somme de tous les ANSCOUNT code>.
Pouvez-vous aider s'il vous plaît, quelque chose comme ci-dessous:
for (c in paste0("ANSWER",1:5)) { dt0[, as.name(paste0(c,"_t")):= as.name(c)*"ANSCOUNT", , with=T] }
Merci.
Voici l'erreur. Comment le comprendre et comment le faire correctement?
ANSWER1 ANSWER2 ANSWER3 ANSWER4 ANSWER5 ANSCOUNT SCORE100 21 37 16 14 11 200784 61 20 37 16 15 11 177165 60
3 Réponses :
Pour répondre à la question générale - " Quand et comment utiliser as.name () contre get () dans data.table? ".
D'après mon expérience, cela est rarement nécessaire lorsque vous pouvez utiliser les méthodes de programmation R existantes:
Une approche fonctionnelle similaire à l'autre réponse (maintenant supprimée):
dt0[, newcol := Reduce(`+`, Map(`*`, c(100,75,50,25,0), .SD)) / Reduce(`+`, .SD), .SDcols = ANSWER1:ANSWER5 ] # ANSWER1 ANSWER2 ANSWER3 ANSWER4 ANSWER5 ANSCOUNT SCORE100 newcol #1: 21 37 16 14 11 200784 61 60.85859 #2: 20 37 16 15 11 177165 60 60.10101
Explication:
Mappez
le facteur de pondération de 100-to-0
au code ANSWER1: ANSWER5 correspondant > colonnes, puis
Réduisez
les ensemble à l'aide d'une fonction +
. En d'autres termes, 100 * ANSWER1 + 75 * ANSWER2 + 50 * ANSWER3 ...
etc.
Utilisez ensuite les mêmes Réduire
et +
pour former le dénominateur de l'équation.
Je pense que la multiplication par ANSCOUNT
est inutile car elle l'est à la fois au numérateur et au dénominateur.
Une façon plus compliquée d'utiliser Réduire: DT [ Réduire (`+`, Réduire (`+`, .SD [ - longueur (.SD), avec = FALSE], accumuler = TRUE)) / Réduire ( `+`, .SD) * 25, .SDcols = REPONSE1: REPONSE5]
Cela ne pourra peut-être pas rivaliser en termes de vitesse avec data.table
mais avec une option de base R utilisant sweep
et rowSums
m <- as.matrix(dt0[,.SD,.SDcols=ANSWER1:ANSWER5]) m %*% seq(100,0,-25) /rowSums(m)
Ou sans utiliser sweep
rowSums(t(t(dt0[,1:5]) * seq(100,0,-25)))/rowSums(dt0[, 1:5])
Les deux approches ci-dessus convertissent implicitement le data.table en matrice et exécute le calcul. Nous pouvons avoir une légère amélioration de la vitesse en utilisant la multiplication matricielle et en évitant l'opération de sous-ensemble deux fois. (merci à @nicola).
rowSums(sweep(dt0[,1:5],2, seq(100,0,-25), FUN = "*"))/rowSums(dt0[, 1:5]) #[1] 60.859 60.101
J'imagine que ce sera en fait très compétitif. :-RÉ
@thelatemail mais il perd sa valeur de data.table
je crois.
Une petite amélioration dans ce sens pourrait être l'utilisation de la multiplication matricielle (% *%
): m <-as.matrix (dt0 [. SD, .SDcols = ANSWER1: ANSWER5] ); m% *% c (100,75,50,25,0) / rowSums (m)
(dans vos lignes, la coersion en matrice est implicite).
Je viens de trouver à Attribution / Référencement dynamique d'un nom de colonne dans data.table (en i, j et par) l'interrelation entre les deux:
get(strFactor)
est la même
eval(as.name(strFactor))
à la seule différence que le premier est "plus sûr" que le second ( plus précisément, get
ne fonctionne pas dans certaines anciennes versions de certains packages (par exemple dans les anciennes versions de data.table
)
Donc, avec cette mise en garde à l'esprit, l'un ou l'autre de ces deux peut être utilisé - lors de la boucle dans les colonnes!
Une sous-question: Quel code créera automatiquement N nouvelles colonnes
ANSWER1_t
, ....,ANSWERN_t
, qui sont égales àANSWER1 * ANSCOUNT
, ...ANSWERN * ANSCOUNT
?Je souhaite toujours savoir comment / quand utiliser
as.name (x)
ouget (x)
avecdata.table
, où x est passé en paramètre (d'une boucle ou d'une fonction). Pouvez-vous me donner des exemples de bonne utilisation de ceux-ci, s'il vous plaît? Ce serait formidable si l'aide / manuel de 'data.table' incluait également ces exemples ...as.name
ne convient que si vous créez une expression et appliquezeval
, je pense. Ici, vous pouvez fairefor (c in paste0 ("ANSWER", 1: 5)) dt0 [ paste0 (c, "_ t"): = get (.. c) * ANSCOUNT]
Le point La notation -dot est assez récente, utilisée pour clarifier que c se réfère à une variable "un niveau supérieur" de la table