1

I am trying to add a new column "result" in my dataframe df1, if the condition is

  1. select only specific columns (from count1:count3 columns) have negative value, then result = "negative"
  2. if any one of the columns (count1, count2, count3) have a positive value the result = "positive"

input

df1<- data.frame(ID= c("ID1","ID2","ID3","ID4"), count1 = c(1,-1,0,-1), count2 = c(1,-1,-1,1), count3 = c(1,-1,1,-1))

expected output

df2 <- data.frame(ID= c("ID1","ID2","ID3","ID4"),count1 = c(1,-1,1,-1), count2 = c(1,-1,-1,1), count3 = c(1,-1,1,-1), result = c("positive","negative","positive","positive"))

  ID count1 count2 count3   result
 ID1      1      1      1 positive
 ID2     -1     -1     -1 negative
 ID3      1     -1      1 positive
 ID4     -1      1     -1 positive
zx8754
  • 52,746
  • 12
  • 114
  • 209
Kryo
  • 921
  • 9
  • 24

4 Answers4

1

Does this work:

apply(df1,1,function(x) if(all(x > 0)) 'positive' else 'negative')
[1] "positive" "negative" "negative" "negative"

library(dplyr)
df1 %>% rowwise() %>% mutate(result = if_else(all(c_across(cols = everything()) > 0),'positive','negative'))
# A tibble: 4 x 4
# Rowwise: 
  count1 count2 count3 result  
   <dbl>  <dbl>  <dbl> <chr>   
1      1      1      1 positive
2     -1     -1     -1 negative
3      0     -1      1 negative
4     -1      1     -1 negative
Karthik S
  • 11,348
  • 2
  • 11
  • 25
  • i edited my question. I only want to select specific columns, eg from column 2 to 4. – Kryo Jun 10 '21 at 09:21
  • You can include only those columns in both solutions, i.e. `df1[2:4]` in `apply` and `c_across(2:4)` accordingly. – Karthik S Jun 10 '21 at 09:25
  • that worked fine. But the condition is if any one of the column have positive value the results should be positive, and not negative. It should report negative only if all the three columns have value < 0. My apology for not explaining it clearly – Kryo Jun 10 '21 at 09:31
  • @Kryo, ah ok, please change `all` to `any` in that case in both solutions – Karthik S Jun 10 '21 at 09:41
1

This should do it:

df2 <- df1 %>%
  mutate(results = if_else(apply(df1, 1, min) < 0, "negative", "positive"))
koolmees
  • 2,725
  • 9
  • 23
1

Using rowSums:

df1$results <- ifelse(rowSums(df1[ grepl("^count", colnames(df1)) ] > 0) > 0,
                      "positive", "negative")


df1
#    ID count1 count2 count3  results
# 1 ID1      1      1      1 positive
# 2 ID2     -1     -1     -1 negative
# 3 ID3      0     -1      1 positive
# 4 ID4     -1      1     -1 positive
zx8754
  • 52,746
  • 12
  • 114
  • 209
1

A data.table option

setDT(df1)[, result := c("negative", "positive")[1 + (rowSums(.SD == 1) > 0)], .SDcols = patterns("count")][]

gives

    ID count1 count2 count3   result
1: ID1      1      1      1 positive
2: ID2     -1     -1     -1 negative
3: ID3      0     -1      1 positive
4: ID4     -1      1     -1 positive
ThomasIsCoding
  • 96,636
  • 9
  • 24
  • 81