user9224
user9224

Reputation: 77

R dplyr: change the row value of columns having an specific name

I have a data frame. One of the columns has string values that I want to use as a condition for the name of the other columns. For example,

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

I want to check the name of each column in the df row by row, if the colname does not start with cond then I want to set the value of that column to 0. The expected output here will be.

#    cond aVal bVal
# 1    a    1    0
# 2    b    0    4

I am not sure how to do this with R preferably with dplyr.

Upvotes: 5

Views: 1270

Answers (3)

www
www

Reputation: 39154

Here is a tidyverse solution. Notice that I used stringsAsFactors = FALSE to create your example data frame for avoiding factor columns. df2 is the final output.

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

Data

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

Upvotes: 4

akrun
akrun

Reputation: 887501

Here is a base R option

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

Also a variation of the above would be

df[-1] * (substr(matrix(names(df)[-1][row(df[-1])], 2, 2), 1, 1) == 
               df$cond[col(df[-1])])

Upvotes: 5

mkeskisa
mkeskisa

Reputation: 86

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

Upvotes: 2

Related Questions