【问题标题】:How to conditional subset a list in R based on range in another row如何根据另一行中的范围对 R 中的列表进行条件子集化
【发布时间】:2021-03-25 14:20:20
【问题描述】:

这个问题与我 14 天前提出的另一个问题有关。

How to conditional subset a list in R based on range in another column

这里的不同之处在于,我需要对行而不是列进行子集化,我无法做到这一点。

我已将 100 多个相等的 .xls 文件(每个文件 10 张)导入 R 中的一个列表。我现在正试图获取我需要的信息。文件中的数据高度非结构化。

我创建了一些玩具数据来展示我想要的东西。

list3 <- list(data.frame(depth = c(NA,NA,NA,1,2,3,4,5),
                         col1 = c(NA,NA,"black",NA,"x",NA,NA,NA),
                         col2 = c(NA,NA,"blue",NA,NA,"x",NA,NA),
                         col3 = c(NA,NA,"white","x",NA,NA,NA,NA),
                         col4 = c(NA,NA,"grey",NA,NA,NA,"x",NA),
                         col5 = c(NA,NA,"yellow",NA,NA,NA,NA,"x")))

list4 <- list(data.frame(depth = c(NA,NA,NA,1,2,3,4,5),
                         col1 = c(NA,NA,"black",NA,NA,"x",NA,NA),
                         col2 = c(NA,NA,"blue",NA,NA,NA,"x",NA),
                         col3 = c(NA,NA,"white","x",NA,NA,NA,NA),
                         col4 = c(NA,NA,"grey",NA,"x",NA,NA,NA),
                         col5 = c(NA,NA,"yellow",NA,NA,NA,NA,"x")))

list5 <- list(data.frame(depth = c(NA,NA,NA,1,2,3,4,5),
                         col1 = c(NA,NA,"black",NA,"x","x",NA,NA),
                         col2 = c(NA,NA,"blue",NA,NA,NA,"x",NA),
                         col3 = c(NA,NA,"white","x",NA,NA,NA,NA),
                         col4 = c(NA,NA,"grey",NA,NA,NA,NA,NA),
                         col5 = c(NA,NA,"yellow",NA,NA,NA,NA,"x")))

my_list <- list(list3,list4,list5)

desired_result <- data.frame(depth = c(1,2,3,4,5,1,2,3,4,5,1,2,3,4,5),
                             color = c("white","black","blue","grey","yellow",
                                       "white","grey","black","blue","yellow",
                                       "white","black","black","blue","yellow"))

正如我在上一个问题中提到的,数据是高度非结构化的,因此我需要一个基于子集范围的解决方案。

我需要遍历我的列表。到目前为止,我已经成功使用 purrr:map 做到了这一点。但这个我似乎无法弄清楚。

我需要链接我所有文件中每个深度的颜色。结果不需要在数据框中,每个深度的向量都可以。

我希望得到一个 purrr 解决方案,但谢天谢地,一切都被接受了。

【问题讨论】:

  • 检查修改后的答案。这可以满足您的额外要求。

标签: r purrr


【解决方案1】:

cmets 中给出的额外要求

你的my_list实际上没有名字!所以试试这个语法


library(janitor)
imap_dfr(my_list, ~(.x[[1]] %>% mutate(across(starts_with("col"), ~ifelse(. == "x", depth, .))) %>%
                                                           select(-depth) %>% row_to_names(3) %>% ungroup() %>%
                                                           pivot_longer(everything(), names_to = "color", values_to = "depth", values_drop_na = T) %>%
                                                           mutate(list_name = .y)))

# A tibble: 15 x 3
   color  depth list_name
   <chr>  <chr>     <int>
 1 white  1             1
 2 black  2             1
 3 blue   3             1
 4 grey   4             1
 5 yellow 5             1
 6 white  1             2
 7 grey   2             2
 8 black  3             2
 9 blue   4             2
10 yellow 5             2
11 white  1             3
12 black  2             3
13 black  3             3
14 blue   4             3
15 yellow 5             3

如果列表包含名称,则输出将包含名称,否则列表的索引号。建议使用imap_dfr。这里的假设是第三列包含颜色名称。

【讨论】:

  • 感谢您的解决方案。但是您的输出不适合所需的输出。例如。在 list1 中,第一个深度(深度 1)是“白色”而不是输出中的“黑色”。
  • 我仍然不认为它是正确的。在我的示例数据中,我有 4 个颜色为“黑色”的深度,在您的输出中,只有 3 个颜色为“黑色”的深度。
  • 看来这就是我想要的。但我发现我的深度专栏中有一些 NA。 NA 在 [11:20,1] (第 1 行第 11-20 列)中,我需要将它们全部替换为 c(1,2,3,4,5,6,7,8,9,10)在我可以继续之前,我的列表中的文件。我会回来的,谢谢。
  • 这不是我的问题的一部分。在我接受您的回答之前,我只需要通过替换一些 NA 来更新我的真实数据。我需要看到你的代码在我的真实数据上运行。
  • 完美运行 - 非常感谢!我已经接受了你的回答。你有一个快速调整,所以我可以看到数据来自哪个列表?
【解决方案2】:

试试这个:

library(purrr)
library(dplyr)

my_fun <-function(x){
  depth <- x %>% summarise(across(.cols = starts_with("col"),.fns=~depth[which(.=="x")])) %>%
    as.numeric()
  color <- select(x,starts_with("col"))[3,] %>% as.character(.)
  data.frame(depth,color) %>% arrange(depth)
}

map(my_list,function(l)do.call("rbind",map(l,my_fun))) %>% do.call("rbind",.)

输出:

#    depth  color
# 1      1  white
# 2      2  black
# 3      3   blue
# 4      4   grey
# 5      5 yellow
# 6      1  white
# 7      2   grey
# 8      3  black
# 9      4   blue
# 10     5 yellow

【讨论】:

  • 非常感谢。我会调查并返回。一个简短的问题:有没有办法替换“starts_with”来指定按位置查看哪些列?在上面的示例数据中,位置 2:6。
  • 当然。您可以将starts_with("col") 替换为name_first_col:name_last_col,在您的情况下为col1:col5
  • 很抱歉提供了一些不好的示例数据。我已经用另一个列表 list5 更新了上面的示例。问题是每个深度都可以有相同的颜色。在 list5 中,给定“黑色”颜色有两个深度。我喜欢你的代码,我可以让它在我的真实数据上工作,除非有两个(或更多)深度具有相同的颜色。希望您有时间研究一下 - 谢谢。
猜你喜欢
  • 2021-08-01
  • 2020-09-09
  • 1970-01-01
  • 2015-11-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-25
相关资源
最近更新 更多