【发布时间】:2021-01-18 04:45:32
【问题描述】:
我有超过 100 个 csv 文件,它们都具有相同的结构。每个 csv 文件都是系统中所有文档元数据的每日快照。文件名包含快照日期。元数据包含 Document_ID、Status、Author 和其他一些列。每行代表一个文档的元数据。
我想创建一个随时间变化的所有变化的日志。所以我首先将所有文件加载到一个小标题中,使用:
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, 2), seq(1, 3), seq(1, 4), seq(1, 5)),
Status = c("Finished", "Started",
"Finished", "Started", "Started",
"Finished", "Started", "Finished", "Started",
"Finished", "Waiting", "Finished", "Started", "Started"),
Author = c("John", "John",
"John", "Mike", "John",
"John", "Mike", "John", "Mike",
"John", "Mike", "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 月 2 日创建
请注意,文档永远不会消失,它们只会更改其状态或作者。为了手动创建所需的输出,我首先为每个每日快照创建单独的小标题:
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_ID、Status 和Author 的组合有关:
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, 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-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, 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-30 2 Waiting Mike -0.267
2 File_2020-09-30 5 Started Betty -1.36
最后,我将所有更改绑定在一起,以在单个 tibble 中获取所有更改的日志:
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,然后我可以在变更日志中分析其元数据随时间的变化。
鉴于文件和条目的数量庞大,我需要一个更优雅的解决方案来创建变更日志。如何使用迭代实现此过程,最好使用tidyverse 的purrr::map() 函数?我的问题是每次迭代都针对两个连续的索引对象,我在任何地方都找不到这样的例子。我正在考虑这样的事情(显然这段代码不起作用,只是为了说明而发明了我自己的符号):
Changelog <- df %>% split(.$Date) %>%
purrr::map_dfr(df_index+1 %>% dplyr::anti_join(df_index, by = c("Doc_ID", "Status", "Author")))
有人知道如何解决这个问题吗?也许我还应该将 csv 文件的初始加载更改为列表,而不是将它们加载到单个小标题中。
【问题讨论】:
标签: r iteration tidyverse purrr