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.table
così:
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 dplyr
come 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_at
questo 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 get
e :=
(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.