Reputation: 77
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
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
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
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