Search code examples
rdataframetextmerge

How to put minus in front of specific texts stored in a list [R]


I have a list as shown below:

name <- c("A","B","C","D","E")
n <- c("1, 2, 3, 4, 5", "6, 7, 8", "9, 10", "11, 12, 13, 14", "15, 16, 17")
type <- c("a", "b", "c", "d", "e")

list <- list(name=name, n=n, type=type)

> list
$name
[1] "A" "B" "C" "D" "E"

$n
[1] "1, 2, 3, 4, 5"  "6, 7, 8"        "9, 10"          "11, 12, 13, 14" "15, 16, 17"    

$type
[1] "a" "b" "c" "d" "e"
  • The list has three variables, named name, n and type
  • Each element are corresponded to each (i.e., type of name=A is a), thus, the number of vectors in each element is the same
  • n stores a series of integers which are stored in string split by comma (,) (i.e., n of name=A is 1, 2, 3, 4, 5)
  • n may have different number of integers

On the other hand, I have another data frame:

df <- data.frame(
  name=c("A","A","A","A","A","B","B","B","C","C","D","D","D","D","E","E","E"),
n=c(1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17),
yn=c("Yes","Yes","No","No","Yes","No","Yes","Yes","Yes","Yes","No","Yes","Yes","No","Yes","Yes","Yes"))

> df
   name  n  yn
1     A  1 Yes
2     A  2 Yes
3     A  3  No
4     A  4  No
5     A  5 Yes
6     B  6  No
7     B  7 Yes
8     B  8 Yes
9     C  9 Yes
10    C 10 Yes
11    D 11  No
12    D 12 Yes
13    D 13 Yes
14    D 14  No
15    E 15 Yes
16    E 16 Yes
17    E 17 Yes
  • Data frame has a list of n which are corresponded with name and n in the list
  • In addition, this data frame has another attribute yn which defines whether the node is yes or no

I want to put minus (-) in front of the integer stored in the list if the corresponded yn in data frame is No as shown below:

enter image description here

Is anyone who can implement this operation? It seems a bit weird manipulation but I need to keep the structure of the list.

Your suggestions are highly appreciated!!


Solution

  • Bring the data in dataframe, mulitply the values based on yn and get the data in list format again.

    library(dplyr)
    library(tidyr)
    
    bind_rows(list) %>%
      separate_rows(n, sep = ',\\s*', convert = TRUE) %>%
      left_join(df, by = c('name', 'n')) %>%
      mutate(n = n * ifelse(yn == 'No', -1, 1)) %>%
      group_by(name, type) %>%
      summarise(n = toString(n), .groups = 'drop') %>%
      as.list()
    
    #$name
    #[1] "A" "B" "C" "D" "E"
    
    #$type
    #[1] "a" "b" "c" "d" "e"
    
    #$n
    #[1] "1, 2, -3, -4, 5"  "-6, 7, 8"         "9, 10"            "-11, 12, 13, -14" "15, 16, 17"