Reputation: 26027
If I have a dataframe like this:
df <- data.frame(c1=1:6, c2=2:7)
I can happily replace values in c2
that are larger then 4
doing
df$c2[df$c2 > 4] <- 10
yielding the desired output
c1 c2
1 1 2
2 2 3
3 3 4
4 4 10
5 5 10
6 6 10
However, I want to select the column by its name using a string, in this case "c2"
, as the column selection should not be hard-coded but it is context dependent.
The best I could come up with is
df[,c('c2')][df[,c('c2')] > 4] <- 1000
yielding
c1 c2
1 1 2
2 2 3
3 3 4
4 4 1000
5 5 1000
6 6 1000
It works, but I find it rather ugly. Is there a better way of doing the same thing?
Upvotes: 1
Views: 453
Reputation: 887531
Using transform
and ifelse
transform(df, c2 = ifelse(c2 > 4, 100, c2))
# c1 c2
#1 1 2
#2 2 3
#3 3 4
#4 4 100
#5 5 100
#6 6 100
If we need to pass a string, one option with dplyr
, would be convert to symbol and evaluate
library(dplyr)
df %>%
mutate(!! "c2" := replace(!! rlang::sym("c2"),
!! rlang::sym("c2") > 4, 100))
# c1 c2
#1 1 2
#2 2 3
#3 3 4
#4 4 100
#5 5 100
#6 6 100
Upvotes: 2
Reputation: 13319
If one is open to packages, we can use purrr
's modify_at
or dplyr
's mutate_at
purrr::modify_at(df,"c2",
function(x)
ifelse(x>4,100,x))
With dplyr
:
mutate_at(df,"c2",
function(x)
ifelse(x>4,100,x))
Upvotes: 2
Reputation: 389155
Maybe using replace
df['c2'] <- replace(df['c2'], df['c2'] > 4, 100)
df
# c1 c2
#1 1 2
#2 2 3
#3 3 4
#4 4 100
#5 5 100
#6 6 100
Or something similar as your attempt
df['c2'][df['c2'] > 4] <- 100
Upvotes: 2
Reputation: 33548
df[df$c2 > 4, 'c2'] <- 10
# or
df$c2 <- with(df, replace(c2, c2 > 4, 10))
Using package data.table
you could do:
library(data.table)
setDT(df)
df[c2 > 4, c2 := 10]
Upvotes: 1