2 votes

Mise à jour des valeurs des colonnes d'une base de données, en utilisant une condition sur une colonne d'une autre base de données, lorsqu'une colonne de caractères dans les deux bases de données peut

Je dois mettre à jour les valeurs d'une colonne df de manière sélective, en fonction de la satisfaction d'une condition sur une colonne df2, et fournir comme valeurs de mise à jour pour df1, les valeurs d'une colonne de df2. Les deux df ont une colonne dont les valeurs sont uniques, et les uniques dans df2 sont un sous-ensemble approprié de ceux dans df1. L'approche que j'ai essayé est de prendre les valeurs de la colonne unique dans les deux df, et de les transformer en noms de ligne, de les utiliser pour définir un index de sélection, qui est créé à partir de df2, et ensuite appliqué à df1 pour une mise à jour de la valeur. J'ai réussi à faire fonctionner la syntaxe (finalement !) en utilisant l'indice numérique pour définir les colonnes, en combinaison avec mon index de clé partagée basé sur les caractères pour les lignes. Et voilà

Mais existe-t-il un moyen plus simple, plus efficace et plus "R" que celui que j'essaie de mettre en œuvre, en utilisant un logiciel intégré, par exemple ? J'aurai besoin d'une mise à l'échelle. L'exemple de test suit :

goo <- data.frame(Uids=c("UidD", "UidA", "UidC"), Payout=c(3,0,5), stringsAsFactors = FALSE)
moo <- data.frame(Uids=c("UidB", "UidC", "UidA", "UidD"), PayOut=0, stringsAsFactors = FALSE)
goo
  Uids Payout
1 UidD      3
2 UidA      0
3 UidC      5
moo
  Uids PayOut
1 UidB      0
2 UidC      0
3 UidA      0
4 UidD      0
# I want to update moo$Payout with the value of goo$Payout, for matching Uids,
# when goo$Payout > 0, i.e. moo[4,2] <- goo[1,2]; moo[2,2 <- goo[3,2]
rownames(goo) <- goo$Uids
rownames(moo) <- moo$Uids
#I am trying to create and apply an index based on turning uids into rownames
IndexToUpdate <- goo$Uids[goo$Payout>0]
IndexToUpdate
[1] "UidD" "UidC"
 moo[IndexToUpdate, 2] <- goo[IndexToUpdate, 2]
#this works, but is there a better way to do it?
moo
     Uids PayOut
UidB UidB      0
UidC UidC      5
UidA UidA      0
UidD UidD      3

3voto

flodel Points 41487

J'utiliserais merge con all.x = TRUE :

voo <- merge(moo, goo, by = "Uids", all.x = TRUE)
voo
#   Uids PayOut.x PayOut.y
# 1 UidA        0        0
# 2 UidB        0       NA
# 3 UidC        0        5
# 4 UidD        0        3

Entonces ifelse :

within(voo, PayOut <- ifelse(is.na(PayOut.y), PayOut.x, PayOut.y))
#   Uids PayOut.x PayOut.y PayOut
# 1 UidA        0        0      0
# 2 UidB        0       NA      0
# 3 UidC        0        5      5
# 4 UidD        0        3      3

La même chose en utilisant data.table s :

library(data.table)
GOO <- data.table(goo)
MOO <- data.table(moo)
setkey(GOO, Uids)
setkey(MOO, Uids)
VOO <- GOO[MOO]
VOO[, FinalPayout := ifelse(is.na(PayOut), PayOut.1, PayOut)]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X