如何使用purrr :: map遍历两个连续的索引对象?

如何解决如何使用purrr :: map遍历两个连续的索引对象?

我有100多个csv文件,所有文件都具有相同的结构。每个csv文件都是系统中所有文档的元数据的每日快照。文件名包含快照日期。元数据包含Document_ID,状态,作者和其他一些列。每行代表文档的元数据。

我想创建一个随时间变化的日志。因此,我首先使用:

df <- fs::dir_ls(path = "Files") %>% 
  purrr::map_dfr(read_csv,.id = "Filename")

包含快照日期的原始文件名现在位于第一列中。这是生成的df的简化表示:

library(tidyverse)

df <- tibble(Filename = c(rep("File_2020-09-27",2),rep("File_2020-09-28",3),rep("File_2020-09-29",4),rep("File_2020-09-30",5)),Doc_ID = c(seq(1,seq(1,Status = c("Finished","Started","Finished","Waiting","Started"),Author = c("John","John","Mike","Betty"),Other_column = rnorm(14))
df
#> # A tibble: 14 x 5
#>    Filename        Doc_ID Status   Author Other_column
#>    <chr>            <int> <chr>    <chr>         <dbl>
#>  1 File_2020-09-27      1 Finished John          0.319
#>  2 File_2020-09-27      2 Started  John          0.633
#>  3 File_2020-09-28      1 Finished John          2.27 
#>  4 File_2020-09-28      2 Started  Mike          0.302
#>  5 File_2020-09-28      3 Started  John          0.905
#>  6 File_2020-09-29      1 Finished John          0.451
#>  7 File_2020-09-29      2 Started  Mike          1.46 
#>  8 File_2020-09-29      3 Finished John          0.306
#>  9 File_2020-09-29      4 Started  Mike         -0.850
#> 10 File_2020-09-30      1 Finished John         -2.03 
#> 11 File_2020-09-30      2 Waiting  Mike          0.250
#> 12 File_2020-09-30      3 Finished John          0.637
#> 13 File_2020-09-30      4 Started  Mike         -0.207
#> 14 File_2020-09-30      5 Started  Betty        -2.13

reprex package(v0.3.0)于2020-10-02创建

请注意,文档永远不会消失,它们只会更改其状态或作者。要手动创建所需的输出,我首先为每个每日快照创建单独的小标题

Docs_1 <- df %>% filter(Filename == "File_2020-09-27")
Docs_2 <- df %>% filter(Filename == "File_2020-09-28")
Docs_3 <- df %>% filter(Filename == "File_2020-09-29")
Docs_4 <- df %>% filter(Filename == "File_2020-09-30")

然后,对于每对连续的每日快照,我确定第二天的行,这些行是新的或与前一天不同。我只对这些感兴趣。 “新”或“不同”与Doc_IDStatusAuthor的组合有关:

Changes_1_2 <- Docs_2 %>% dplyr::anti_join(Docs_1,by = c("Doc_ID","Status","Author"))

导致:

# A tibble: 2 x 5
  Filename        Doc_ID Status  Author Other_column
  <chr>            <int> <chr>   <chr>         <dbl>
1 File_2020-09-28      2 Started Mike          0.807
2 File_2020-09-28      3 Started John          0.336
Changes_2_3 <- Docs_3 %>% dplyr::anti_join(Docs_2,"Author"))

导致:

# A tibble: 2 x 5
  Filename        Doc_ID Status   Author Other_column
  <chr>            <int> <chr>    <chr>         <dbl>
1 File_2020-09-29      3 Finished John         1.48  
2 File_2020-09-29      4 Started  Mike        -0.0407
Changes_3_4 <- Docs_4 %>% dplyr::anti_join(Docs_3,"Author"))

导致:

# A tibble: 2 x 5
  Filename        Doc_ID Status  Author Other_column
  <chr>            <int> <chr>   <chr>         <dbl>
1 File_2020-09-30      2 Waiting Mike         -0.267
2 File_2020-09-30      5 Started Betty        -1.36 

最后,我将所有更改绑定在一起,以便在一个标题中记录所有更改:

Changelog <- dplyr::bind_rows(Changes_1_2,Changes_2_3,Changes_3_4)

导致:

# A tibble: 6 x 5
  Filename        Doc_ID Status   Author Other_column
  <chr>            <int> <chr>    <chr>         <dbl>
1 File_2020-09-28      2 Started  Mike         0.807 
2 File_2020-09-28      3 Started  John         0.336 
3 File_2020-09-29      3 Finished John         1.48  
4 File_2020-09-29      4 Started  Mike        -0.0407
5 File_2020-09-30      2 Waiting  Mike        -0.267 
6 File_2020-09-30      5 Started  Betty       -1.36  

然后,我可以针对每个Doc_ID在变更日志中分析其元数据随时间的变化。

鉴于文件和条目的绝对数量,我需要一个更优雅的解决方案来创建Changelog。如何使用迭代来实现此过程,最好使用purrr::map()的{​​{1}}函数?我的问题是每次迭代都以两个连续的索引对象为目标,而我在任何地方都找不到这样的示例。我在想这样的事情(显然,这段代码行不通,只是发明了自己的说明用插图):

tidyverse

有人知道如何解决这个问题吗?也许我还应该将csv文件的初始加载更改为列表,而不是将其加载为单个小标题

解决方法

我认为我们可以分组/嵌套,滞后和比较:

library(dplyr)
library(tidyr) # unnest
set.seed(42) # and then your `df <- tibble(...)`

df %>%
  nest_by(Filename) %>%
  ungroup() %>%
  mutate(lastdata = lag(data)) %>%
  filter(lengths(lastdata) > 0) %>%
  mutate(
    diffs = purrr::map2(data,lastdata,~ anti_join(.x,.y,by = c("Doc_ID","Status","Author")))
  ) %>%
  select(-data,-lastdata) %>%
  tidyr::unnest(diffs)
# # A tibble: 6 x 5
#   Filename        Doc_ID Status   Author Other_column
#   <chr>            <int> <chr>    <chr>         <dbl>
# 1 File_2020-09-28      2 Started  Mike         0.633 
# 2 File_2020-09-28      3 Started  John         0.404 
# 3 File_2020-09-29      3 Finished John        -0.0947
# 4 File_2020-09-29      4 Started  Mike         2.02  
# 5 File_2020-09-30      2 Waiting  Mike         1.30  
# 6 File_2020-09-30      5 Started  Betty       -0.279 

要查看的重要步骤是:

  1. 初始分组/嵌套设置:

    df %>%
      nest_by(Filename) %>%
      ungroup() %>%
      mutate(lastdata = lag(data))
    # # A tibble: 4 x 3
    #   Filename                      data           lastdata
    #   <chr>           <list<tbl_df[,4]>> <list<tbl_df[,4]>>
    # 1 File_2020-09-27            [2 x 4]                [0]
    # 2 File_2020-09-28            [3 x 4]            [2 x 4]
    # 3 File_2020-09-29            [4 x 4]            [3 x 4]
    # 4 File_2020-09-30            [5 x 4]            [4 x 4]
    

    其中data列实际上包含您的Docs_1Docs_2,而lastdata包含data上一个。这意味着对于第二行,data包含来自09-28的行,lastdata包含来自09-27的行。

  2. 由于我们无法将09-27与前一天进行比较(并且其lastdata为空),因此我们将其过滤掉了:

      filter(lengths(lastdata) > 0)
    
  3. 最后,我们遍历各列,anti_join依次lastdatadata每对:

      mutate(
        diffs = purrr::map2(data,"Author")))
      )
    # # A tibble: 3 x 4
    #   Filename                      data           lastdata diffs           
    #   <chr>           <list<tbl_df[,4]>> <list>          
    # 1 File_2020-09-28            [3 x 4]            [2 x 4] <tibble [2 x 4]>
    # 2 File_2020-09-29            [4 x 4]            [3 x 4] <tibble [2 x 4]>
    # 3 File_2020-09-30            [5 x 4]            [4 x 4] <tibble [2 x 4]>
    
  4. 通过删除和取消嵌套进行清理。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?