So che ci sono molte domande simili qui intorno, ma nessuna sembra affrontare il problema preciso che sto riscontrando.
set.seed(4)
df = data.frame(
Key = c("A", "B", "A", "D", "A"),
Val1 = rnorm(5),
Val2 = runif(5),
Val3 = 1:5
)
Voglio azzerare i valori delle colonne dei valori per le righe in cui Key == "A" I nomi delle colonne sono referenziati attraverso un grep:
cols = grep("Val", names(df), value = TRUE)
Normalmente per ottenere quello che voglio in questo caso lo userei data.tablecosì:
library(data.table)
df = as.data.table(df)
df[Key == "A", (cols) := 0]
E l'output desiderato è così:
Key Val1 Val2 Val3
1 A 0.000000 0.00000000 0
2 B -1.383814 0.55925762 2
3 A 0.000000 0.00000000 0
4 D 1.437151 0.05632773 4
5 A 0.000000 0.00000000 0
Tuttavia, questa volta ho bisogno di usare dplyrcome sto lavorando a un progetto di squadra in cui tutti lo usano. I dati che ho appena fornito sono illustrativi e i miei dati reali sono> 5m righe con 16 colonne di valori da aggiornare. L'unica soluzione che ho potuto trovare è usare in mutate_atquesto modo:
df %>% mutate_at(.vars = vars(cols), .funs = function(x) ifelse(df$Key == "A", 0, x))
Tuttavia, questo sembra essere estremamente lento sui miei dati reali. Speravo di trovare una soluzione più elegante e, soprattutto, più veloce.
Ho provato molte combinazioni usando map, annullando la citazione usando !!, usando gete :=(che può essere fastidiosamente mascherato da in :=in data.table) ecc., Ma penso che la mia comprensione di come questi lavori semplicemente non sia abbastanza profonda per costruire una soluzione valida.