Repeated function over varnames

Viewed 31

Using the following dataframe (similar to my data, but much smaller):

id <- c(1:10)
clo_a <- c(rep(c("Yes","No"), 5))
clo_f <- c(rep(c(4,5), 5))
man_a <- c(rep(c("Yes","No"), each = 5))
man_f <- c(rep(c(c(3,7)), each = 5))
pho_a <- c(rep(c(NA, NA, "Yes", NA, "No"), 2))
pho_f <- c(rep(c(1,2,3,4,5), 2))

ds <- data.frame(id, clo_a, clo_f, man_a, man_f, pho_a, pho_f)

produces a dataframe ds as follows:

   id clo_a clo_f man_a man_f pho_a pho_f
1   1   Yes     4   Yes     3  <NA>     1
2   2    No     5   Yes     3  <NA>     2
3   3   Yes     4   Yes     3   Yes     3
4   4    No     5   Yes     3  <NA>     4
5   5   Yes     4   Yes     3    No     5
6   6    No     5    No     7  <NA>     1
7   7   Yes     4    No     7  <NA>     2
8   8    No     5    No     7   Yes     3
9   9   Yes     4    No     7  <NA>     4
10 10    No     5    No     7    No     5

I now want to select the id's of the variables ending in _a with "Yes", but also the values of the variables ending in _f, albeit ideally separately.

As one example I can write:

upset_clo_a <- ds$id[which( ds$clo_a == "Yes")]

producing:

> upset_clo_a
[1] 1 3 5 7 9

I'd now like the repeat this for all variables, ideally using a vector with the common denominator in the set of variables, susch as:

ai_list <- c("clo", "man", "pro")

Obviously the following example doesn't work. I tried several variants of using paste() or substitute(), not yielding anything useful.

lapply(ai_list, function(x) {
  upset_x <- ds$id[which( ds$x == "Yes")]
})

The output is the same for all variants I tried:

[[1]]
integer(0)

[[2]]
integer(0)

[[3]]
integer(0)

In the end I want to (for example) read the ID-vectors per variable (e.g. upset_clo_f) as list of vectors into an upSet plot. Maybe you have a great idea. Thanks!

1 Answers

You can paste the missing part (_a) in each vector element and use it to subset your data.frame. Then loop over those columns and get the index of Yes, i.e.

sapply(ds[names(ds) %in% paste0(ai_list, '_a')], function(i)which(i == 'Yes'))

Breaking down the code

  • paste0(ai_list, '_a') - Pastes the suffix [_a] to each name (clo_a, man_a, pro_a)
  • names(ds) %in% paste0(ai_list, '_a') - Returns a logical vector (TRUE, FALSE) which will be used for sub setting the columns of interest
  • ds[names(ds) %in% paste0(ai_list, '_a')] - Returns a data frame with only the columns of interest (as per logical conditions from above step)
  • sapply(ds[names(ds) %in% paste0(ai_list, '_a')], function(i)which(i == 'Yes')) - Finally, we loop over the columns and apply the which() function to get the indices of YES
Related