Tôi biết có một số câu hỏi tương tự ở đây, nhưng không ai trong số chúng dường như giải quyết vấn đề chính xác mà tôi đang gặp phải.
set.seed(4)
df = data.frame(
Key = c("A", "B", "A", "D", "A"),
Val1 = rnorm(5),
Val2 = runif(5),
Val3 = 1:5
)
Tôi muốn zeroise giá trị của các cột giá trị cho các hàng trong đó Key == "A" Các tên cột được tham chiếu qua a grep
:
cols = grep("Val", names(df), value = TRUE)
Thông thường để đạt được những gì tôi muốn trong trường hợp này, tôi sẽ sử dụng data.table
như thế này:
library(data.table)
df = as.data.table(df)
df[Key == "A", (cols) := 0]
Và đầu ra mong muốn là như thế này:
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
Tuy nhiên lần này tôi cần sử dụng dplyr
vì tôi đang làm việc trong một dự án nhóm nơi mọi người sử dụng nó. Dữ liệu tôi vừa cung cấp có tính minh họa và dữ liệu thực của tôi là> 5m hàng với 16 cột giá trị sẽ được cập nhật. Giải pháp duy nhất tôi có thể đưa ra là sử dụng mutate_at
như thế này:
df %>% mutate_at(.vars = vars(cols), .funs = function(x) ifelse(df$Key == "A", 0, x))
Tuy nhiên, điều này dường như là cực kỳ chậm trên dữ liệu thực của tôi. Tôi đã hy vọng tìm ra một giải pháp thanh lịch hơn và quan trọng hơn là nhanh hơn.
Tôi đã thử nhiều kết hợp bằng cách sử dụng map
, bỏ qua việc sử dụng !!
, sử dụng get
và :=
(điều khó chịu có thể bị che dấu bởi :=
data.table), v.v., nhưng tôi nghĩ rằng sự hiểu biết của tôi về cách thức hoạt động của những công việc này không đủ sâu để xây dựng một giải pháp hợp lệ.