R dplyr:更改具有特定名称的列的行值

5

我是一个数据框。其中一列具有字符串值,我想将其用作其他列名称的条件。例如,

df <- data.frame(
  cond=c("a","b"),
  aVal=c(1  , 2),
  bVal=c(3  , 4)
)

我希望逐行检查df中每列的名称,如果列名不以cond开头,则将该列的值设置为0。 预期输出如下:
#    cond aVal bVal
# 1    a    1    0
# 2    b    0    4

我不确定如何使用R,最好使用dplyr来完成这个任务。


从第一行开始,获取条件为“a”的行,然后选择该行中所有列名不以“a”开头的列,并将它们的值设置为0。对于每一行都要继续执行此操作。现在清楚了吗? - user9224
3个回答

5
这里有一个基于R语言的选项。
df[-1] <- df[-1] * t(apply(df, 1, function(x)  substr(names(x)[-1], 1, 1) == x[1]))
df
#   cond aVal bVal
#1    a    1    0
#2    b    0    4

此外,以上内容的一个变化是:
df[-1] * (substr(matrix(names(df)[-1][row(df[-1])], 2, 2), 1, 1) == 
               df$cond[col(df[-1])])

4

这里是一个 tidyverse 的解决方案。请注意,我使用 stringsAsFactors = FALSE 来创建您的示例数据框,以避免出现因子列。 df2 是最终输出。

library(tidyverse)

df2 <- df %>%
  gather(Column, Value, -cond) %>%
  mutate(Column2 = str_sub(Column, 1, 1)) %>%
  mutate(Value = ifelse(map2_lgl(cond, Column2, ~str_detect(.y, .x)), Value, 0)) %>%
  select(-Column2) %>%
  spread(Column, Value)
df2
#   cond aVal bVal
# 1    a    1    0
# 2    b    0    4

数据

df <- data.frame(
  cond=c("a","b"),
  aVal=c(1  , 2),
  bVal=c(3  , 4),
  stringsAsFactors = FALSE
)

解决方案不应该依赖于Val来实现可扩展性。 - user9224
我已经更新了我的答案。对于所有列,“Val”是否一致并不清楚。下次请包含这种重要信息。 - www
此外,cond 列中的字符长度没有任何保证,而且列名始终是一个字母长度,因此删除 "Val" 对我来说似乎是一个安全的选择。 - www

2
library(tidyverse)
df <- data.frame(
  cond=c("a","b"),
  aVal=c(1  , 2),
  bVal=c(3  , 4)
)

gather(df, col1, col2, -cond) %>% 
  as.tibble() %>% 
  filter(str_sub(col1, 1, 1) == cond) %>% 
  spread(col1, col2) %>%
  mutate_at(vars(contains('Val')),
            funs(replace(., is.na(.), 0)))

# A tibble: 2 x 3
  cond   aVal  bVal
  <fct> <dbl> <dbl>
1 a         1     0
2 b         0     4

解决方案不应该依赖于Val来实现可扩展性。 - user9224

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接