Sei que há várias perguntas semelhantes por aqui, mas nenhuma delas parece abordar o problema exato que estou tendo.
set.seed(4)
df = data.frame(
Key = c("A", "B", "A", "D", "A"),
Val1 = rnorm(5),
Val2 = runif(5),
Val3 = 1:5
)
Desejo zerar os valores das colunas de valor das linhas em que Key == "A" Os nomes das colunas são referenciados por meio de um grep:
cols = grep("Val", names(df), value = TRUE)
Normalmente, para alcançar o que eu quero, neste caso, eu usaria data.tableassim:
library(data.table)
df = as.data.table(df)
df[Key == "A", (cols) := 0]
E a saída desejada é assim:
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
No entanto, desta vez eu preciso usá-lo, dplyrpois estou trabalhando em um projeto de equipe onde todos o usam. Os dados que acabei de fornecer são ilustrativos e meus dados reais são> 5m linhas com 16 colunas de valor a serem atualizadas. A única solução que eu poderia encontrar é usar mutate_atassim:
df %>% mutate_at(.vars = vars(cols), .funs = function(x) ifelse(df$Key == "A", 0, x))
No entanto, isso parece ser extremamente lento nos meus dados reais. Eu esperava encontrar uma solução mais elegante e, mais importante, mais rápida.
Eu tentei muitas combinações usando map, sem citar usando !!, usando gete :=(que irritantemente podem ser mascarados pela :=data.table) etc, mas acho que meu entendimento de como esses trabalhos simplesmente não são profundos o suficiente para construir uma solução válida.