使用mutate_at使用数据框中的其他多个列创建新列

时间:2019-11-22 20:19:03

标签: r

鉴于我有一个像这样的数据框:

x <- data.frame(d1 = c(1,0,1,3,5), d2 = c(0,0,1,1,0))

#   d1 d2
# 1  1  0
# 2  0  0
# 3  1  1
# 4  3  1
# 5  5  0

如果c1或c2等于1,而如果两个都不等于0,如何创建等于1的新列呢?像这样:

#   d1 d2 R
# 1  1  0 1
# 2  0  0 0
# 3  1  1 1
# 4  3  1 1
# 5  5  0 0

使用dplyr,我可以通过首先使用filter_at拆分数据帧,然后将结果数据帧重新绑定在一起来实现此目的。

x1 <- x %>%
  filter_at(vars(starts_with("d")), any_vars(. == 1))
x1$R <- 1

x2 <- x %>%
  filter_at(vars(starts_with("d")), all_vars(. != 1))
x2$R <- 0

x <- bind_rows(x1,x2)

#   d1 d2 R
# 1  1  0 1
# 2  1  1 1
# 3  3  1 1
# 4  0  0 0
# 5  5  0 0

但是,此方法不仅看起来像是完成此任务的一种回旋方式,而且数据帧的顺序也发生了变化。在我看来,这不是问题,但在其他情况下可能会令人讨厌。有人知道更好的方法吗?

5 个答案:

答案 0 :(得分:3)

如果我正确理解了您的问题,我将使用带有ifelse语句的mutate函数。

x <- data.frame(d1 = c(1,0,1,3,5), d2 = c(0,0,1,1,0))

# the | is a logical OR operator
x %>% mutate(R = ifelse(d1 ==1 | d2== 1,1,0))

   d1 d2 R
 1  1  0 1
 2  0  0 0
 3  1  1 1
 4  3  1 1
 5  5  0 0

答案 1 :(得分:1)

如果不确定要包含多少个d列,可以先调整形状。

library(dplyr)
library(tidyr)
x %>% 
  mutate(id = row_number()) %>% 
  pivot_longer(starts_with('d')) %>% 
  group_by(id) %>% 
  mutate(R = as.numeric(any(value == 1))) %>% 
  pivot_wider()
# A tibble: 5 x 4
# Groups:   id [5]
     id     R    d1    d2
  <int> <dbl> <dbl> <dbl>
1     1     1     1     0
2     2     0     0     0
3     3     1     1     1
4     4     1     3     1
5     5     0     5     0

答案 2 :(得分:1)

另一个选择可能是:

x %>%
 mutate(R = +(rowSums(select(., starts_with("d")) == 1) != 0))

  d1 d2 R
1  1  0 1
2  0  0 0
3  1  1 1
4  3  1 1
5  5  0 0

答案 3 :(得分:0)

在此处了解有关ifelse的更多信息:

https://www.rdocumentation.org/packages/base/versions/3.6.1/topics/ifelse

使用data.table软件包尝试此操作:

library(data.table)
setDT(x)[,result:=ifelse(d1==1 | d2==1,1,0)]

基本R:

x$result <- ifelse(x$d1==1 | x$d2==1,1,0)

答案 4 :(得分:0)

如果以d开头的列数有所不同,则可以在基数R中执行以下操作:

cbind(x, R = +Reduce("|",data.frame(x[startsWith(names(x),"d")]==1)))
  d1 d2 R
1  1  0 1
2  0  0 0
3  1  1 1
4  3  1 1
5  5  0 0