Sheila
Sheila

Reputation: 2596

Writing a new column if contents of one list is in another in R

Suppose I have several lists of colors, where each list correspond to a given person. I want to create a master list, so I know which person has has what colors in their list.

Here's example data:

Sarah <- c("Red", "Blue", "Yellow", "Green", "Pink")
Ben <- c("Black", "White", "Silver", "Pink", "Red", "Purple")
Jenny <- c("Green", "Orange", "Gold")

people <- list(Sarah, Ben, Jenny)
names(people) <- c("Sarah", "Ben", "Jenny")
allcolors <- c( Sarah, Ben, Jenny)

colorSet <- data.frame(colors = allcolors)

I want a master sheet, where reach row corresponds to a color and each column corresponds to a person. If the person has a color in their list, then that cell would be TRUE, if they do not have a color in their list then it would be FALSE.

This is what I tried to far, but it hasn't worked.

for (i in 1:length(people)) {

   sub_people <- people[[i]]
   sub_people_name <- names(people[i])
   colorSet$x <- ifelse(which(sub_people %in% colorSet$colors), TRUE, FALSE)
   names(colorSet)[names(colorSet) == x] <- sub_people_name

 }

This is the error I get:

Error in $<-.data.frame(*tmp*, "x", value = c(TRUE, TRUE, TRUE, TRUE, : replacement has 5 rows, data has 14

Any help would be greatly appreciated!

Upvotes: 0

Views: 58

Answers (3)

tyluRp
tyluRp

Reputation: 4768

This should work with base R:

colorSet$Sarah <- colorSet$colors %in% Sarah
colorSet$Ben <- colorSet$colors %in% Ben
colorSet$Jenny <- colorSet$colors %in% Jenny

Where colorSet returns:

   colors Sarah   Ben Jenny
1     Red  TRUE  TRUE FALSE
2    Blue  TRUE FALSE FALSE
3  Yellow  TRUE FALSE FALSE
4   Green  TRUE FALSE  TRUE
5    Pink  TRUE  TRUE FALSE
6   Black FALSE  TRUE FALSE
7   White FALSE  TRUE FALSE
8  Silver FALSE  TRUE FALSE
9    Pink  TRUE  TRUE FALSE
10    Red  TRUE  TRUE FALSE
11 Purple FALSE  TRUE FALSE
12  Green  TRUE FALSE  TRUE
13 Orange FALSE FALSE  TRUE
14   Gold FALSE FALSE  TRUE

This should also work:

l <- rbind.data.frame(lapply(people, function(x) colorSet$colors %in% x))
l$colors <- colorSet$colors

With purrr we could do:

purrr::map_df(people, function(x) colorSet$colors %in% x)

# Alternatively, if you prefer formula syntax
purrr::map_df(people, ~ colorSet$colors %in% .)

Returns:

# A tibble: 14 x 3
   Sarah Ben   Jenny
   <lgl> <lgl> <lgl>
 1 TRUE  TRUE  FALSE
 2 TRUE  FALSE FALSE
 3 TRUE  FALSE FALSE
 4 TRUE  FALSE TRUE 
 5 TRUE  TRUE  FALSE
 6 FALSE TRUE  FALSE
 7 FALSE TRUE  FALSE
 8 FALSE TRUE  FALSE
 9 TRUE  TRUE  FALSE
10 TRUE  TRUE  FALSE
11 FALSE TRUE  FALSE
12 TRUE  FALSE TRUE 
13 FALSE FALSE TRUE 
14 FALSE FALSE TRUE

Upvotes: 2

kangaroo_cliff
kangaroo_cliff

Reputation: 6222

Following uses sapply. This way one doesn't have to names of people repeatedly.

all_colours <- unique(allcolors)
tab <- sapply(people, function(x) all_colours %in% x)
rownames(tab) <- all_colours

tab
#        Sarah   Ben Jenny
# Red     TRUE  TRUE FALSE
# Blue    TRUE FALSE FALSE
# Yellow  TRUE FALSE FALSE
# Green   TRUE FALSE  TRUE
# Pink    TRUE  TRUE FALSE
# Black  FALSE  TRUE FALSE
# White  FALSE  TRUE FALSE
# Silver FALSE  TRUE FALSE
# Purple FALSE  TRUE FALSE
# Orange FALSE FALSE  TRUE
# Gold   FALSE FALSE  TRUE

Upvotes: 0

Sarah <- c("Red", "Blue", "Yellow", "Green", "Pink")
Ben <- c("Black", "White", "Silver", "Pink", "Red", "Purple")
Jenny <- c("Green", "Orange", "Gold")

m_color <-unique(c(Sarah,Ben,Jenny))

TF <-data.frame(color = m_color)

TF$Sarah <- m_color%in%Sarah
TF$Ben <- m_color%in%Ben
TF$Jenny <- m_color%in%Jenny

Upvotes: 0

Related Questions