如何在带有 apply 或 map 的列表上使用 case_when()

How to use case_when() on a list with apply or map

我正在尝试在注释列表上使用 dplyr 函数 case_when(),这样我就可以将标记的名称分配给我的数据。我找到了一种通过多次编写来手动执行此操作的方法,但我尝试使用 apply 或 map 将其应用于列表但没有找到解决方案。

这是一个可重现的例子:

library(tidyverse)
annotation <- list (marker_1 = c("L", "D"),
                    marker_2 = c("C","R"),
                    marker_3 = c("A", "B"),
                    marker_4 = c("E", "F"),
                    marker_5 = c("G", "H"))


df <- tibble(L = 1, D = 2, C = 3, R = 4)


annotation_df <-
  tibble(markers = colnames(df)) %>%
  mutate(
    type = case_when(
      markers %in% annotation[[1]] ~ names(annotation[1]),
      markers %in% annotation[[2]] ~ names(annotation[2]),
      markers %in% annotation[[3]] ~ names(annotation[3]),
      markers %in% annotation[[4]] ~ names(annotation[4]),
      markers %in% annotation[[5]] ~ names(annotation[5])
    )
  ) %>%
  column_to_rownames("markers")
print(annotation_df)
#>       type
#> L marker_1
#> D marker_1
#> C marker_2
#> R marker_2

reprex package (v2.0.1)

于 2022-04-25 创建

而不是 case_when,一个更简单的选择是在将命名的 list 转换为两列 tibble 之后使用 (tibble::enframe)[=25= 进行联接]

library(dplyr)
library(tidyr)
library(tibble)
enframe(annotation, name = 'type', value = 'markers') %>% 
   unnest(markers) %>%
    right_join(tibble(markers = colnames(df))) %>%
   relocate(type, .after = 'markers')

-输出

# A tibble: 4 × 2
  markers type    
  <chr>   <chr>   
1 L       marker_1
2 D       marker_1
3 C       marker_2
4 R       marker_2

或者另一种选择是遍历 list,获取 intersecting 元素并将命名列表转换为 tibble

library(purrr)
map(annotation, ~ intersect(names(df), .x)) %>%
  keep(lengths(.) > 0) %>%
  enframe(name = 'markers', value = 'type') %>%
  unnest(type)

或将 base Rlapplystack

一起使用
lapply(annotation, \(x) intersect(names(df), x)) |>
    Filter(length, x = _) |>
    stack() |> 
    setNames(c("markers", "type")) |>
    subset(select = 2:1)

-输出

      type markers
1 marker_1       L
2 marker_1       D
3 marker_2       C
4 marker_2       R