Cirrus
Cirrus

Reputation: 648

How to create a new column with if condition

This seems simple but I could not perform. Its different than sound similar question ask here. I want to create new columns say df$col1, df$col2, df$col3 on dataframe df using if condition in the column already exists ie df$con and df$val.

  1. I would like to write the value of column "val" in df$col1 if df$con > 3
  2. I would like to write the value of col df$val in df$col2 if df$con<2
  3. and I would like to write the 30% of df$val in df$col3 if df$con is between 1 and 3.

How should I do it ? Below is my dataframe df with two columns "con" for condition and "val" for value use.

dput(df)
structure(list(con = c(-33.09524956, -36.120924, -28.7020053, 
-26.06385399, -18.45731163, -14.51817928, -20.1005132, -23.62346403, 
-24.90464018, -23.51471516), val = c(0.016808197, 1.821442227, 
 4.078385886, 3.763593573, 2.617612605, 2.691796601, 1.060565469, 
 0.416400183, 0.348732675, 1.185505136)), .Names = c("con", "val"
 ), row.names = c(NA, 10L), class = "data.frame")

Upvotes: 0

Views: 2370

Answers (2)

user14353
user14353

Reputation: 135

Could go the tidyverse way. The pipes %>% just send the output of each operation to the next function. mutate allows you to make a new column in your data frame, but you have to remember to store it at the top. It's stored as output. The ifelse allows you to conditionally assign values to your new column, for example the column col1. The second argument in ifelse is the output for a true condition, and the third argument is when ifelse is false. Hope this helps some too!

Go tidyverse!

 library(tidyverse)

 output <- df %>%
   mutate(col1=ifelse(con>3, val, NA)) %>%
   mutate(col2=ifelse(con<2, val, NA)) %>%
   mutate(col3=ifelse(con<=3 & con>=1, 0.3*val, NA))

Here's a df that actually meets some of the conditions:

structure(list(con = c(-33.09524956, 2.5, -28.7020053, 2, -18.45731163, 
2, -20.1005132, 6, -24.90464018, -23.51471516), val = c(0.016808197, 
1.821442227, 4.078385886, 3.763593573, 2.617612605, 2.691796601, 
1.060565469, 0.416400183, 0.348732675, 1.185505136)), .Names = c("con", 
"val"), row.names = c(NA, 10L), class = "data.frame")

Here's the output after running the code:

         con       val      col1      col2      col3
1  -33.09525 0.0168082        NA 0.0168082        NA
2    2.50000 1.8214422        NA        NA 0.5464327
3  -28.70201 4.0783859        NA 4.0783859        NA
4    2.00000 3.7635936        NA        NA 1.1290781
5  -18.45731 2.6176126        NA 2.6176126        NA
6    2.00000 2.6917966        NA        NA 0.8075390
7  -20.10051 1.0605655        NA 1.0605655        NA
8    6.00000 0.4164002 0.4164002        NA        NA
9  -24.90464 0.3487327        NA 0.3487327        NA
10 -23.51472 1.1855051        NA 1.1855051        NA

Upvotes: 0

Rich Scriven
Rich Scriven

Reputation: 99371

This might do it. First we write a function to change FALSE values to NA

foo <- function(x) {
    is.na(x) <- x == FALSE
    return(x)
}

Then apply it over the list of logical vectors and take the matching val column values

df[paste0("col", 1:3)] <- with(df, {
    x <- list(con > 3, con < 2, con < 3 & con > 1)
    lapply(x, function(y) val[foo(y)])
})

resulting in

df
         con       val col1      col2 col3
1  -33.09525 0.0168082   NA 0.0168082   NA
2  -36.12092 1.8214422   NA 1.8214422   NA
3  -28.70201 4.0783859   NA 4.0783859   NA
4  -26.06385 3.7635936   NA 3.7635936   NA
5  -18.45731 2.6176126   NA 2.6176126   NA
6  -14.51818 2.6917966   NA 2.6917966   NA
7  -20.10051 1.0605655   NA 1.0605655   NA
8  -23.62346 0.4164002   NA 0.4164002   NA
9  -24.90464 0.3487327   NA 0.3487327   NA
10 -23.51472 1.1855051   NA 1.1855051   NA

Upvotes: 1

Related Questions