2016-12-07 97 views
1

我试图在数据帧的特定列中替换一个值(例如总是1)。列j中给出了替换的列索引。根据给定索引用dplyr替换列中的值

它与一个循环:

data <- data.frame(v1 = rep(0, 10), 
       v2 = rep(0, 10), 
       j = sample(1:2, 10, replace = TRUE)) 

for (i in 1: nrow(data)){ 
    data[i, (data$j[i])] <- 1 
} 

我要找的处理这种情况的dplyr方式。

回答

2

这可以用row/column索引可以轻松完成,它应该是更快

data[cbind(1:nrow(data), data$j)] <- 1 
data 
# v1 v2 j 
#1 0 1 2 
#2 1 0 1 
#3 0 1 2 
#4 0 1 2 
#5 0 1 2 
#6 0 1 2 
#7 0 1 2 
#8 1 0 1 
#9 1 0 1 
#10 0 1 2 

或者另一种方式是

library(tidyr) 
library(dplyr) 
tibble::rownames_to_column(data, var = "rn") %>% 
      gather(Var, Val, v1:v2) %>% 
      mutate(Val= +(sub("\\D+", "", Var)==j)) %>% 
      spread(Var, Val) %>% 
      arrange(as.numeric(rn)) %>% 
      select_(.dots=names(data)) 
# v1 v2 j 
#1 0 1 2 
#2 1 0 1 
#3 0 1 2 
#4 0 1 2 
#5 0 1 2 
#6 0 1 2 
#7 0 1 2 
#8 1 0 1 
#9 1 0 1 
#10 0 1 2 
+1

我没有downvote。但实际上我正在寻找处理这种情况的方式。只是出于好奇。 – Fritzbrause

+0

@Fritzbrause我发布了来自tidyverse/dplyr家族的解决方案 – akrun

+1

太棒了!谢谢。基本版本确实更容易。我更喜欢这个解决方案,因为它更容易适用于多个变量。 – Fritzbrause

3

这里是一个dplyr版,采用bind_rows。首先让我们来设置数据:

set.seed(2) 
data <- data.frame(v1 = rep(0, 10), 
        v2 = rep(0, 10), 
        j = sample(1:2, 10, replace = TRUE)) 

然后我们加载dplyr和使用do作用于每一行。这里我们使用do来每行返回一个数据帧,并且使用bind_rows来将它们合并在一起。每行中的数据可以使用.变量进行访问。

library(dplyr) 

data %>% 
    do(data.frame(v1 = ifelse(.$j == 1, 1, .$v1), 
        v2 = ifelse(.$j == 2, 1, .$v2), 
        j = .$j)) %>% 
    bind_rows() 


# v1 v2 j 
#1 1 0 1 
#2 0 1 2 
#3 0 1 2 
#4 1 0 1 
#5 0 1 2 
#6 0 1 2 
#7 1 0 1 
#8 0 1 2 
#9 1 0 1 
#10 0 1 2 

更短的解决方案,通过@Akrun建议,就是:

data %>% mutate(v1 = +(j==1), v2 = +(j==2)) 
+3

你也可以做'data%>%mutate(v1 = +(j == 1),v2 = +(j == 2))''。假设只有两列 – akrun

+0

哦,非常好,@akrun!你应该添加这个答案。 – River

+1

它与您的思考过程相似。请将其添加到您的答案 – akrun