工作项目的逻辑数据整理建议
Advice on Logical Data Tidying for a work project
我的数据集来自 excel 由非数据导向的同事建立的文件。我的数据很敏感,所以我不能共享数据集,但我会尝试举一个例子,这样更容易理解我在说什么。我有一个唯一标识符列。我的问题是日期列。我有多个日期列。当导入到 R 中时,一些列作为日期导入,其中一些作为 excel 日期导入。然后列中的某些单元格具有一串日期(字符类型)。并非所有字符串的大小都相同。有些有 2 个列表,有些有 7 个列表。
我正在尝试整理我的数据。我的想法是将所有收集日期放在一栏中。这就是我被困的地方。我可以使用 pivot_longer() 因为并非所有列都是同一类型。我无法将 excel 日期转换为 R 日期 w/out 以摆脱字符串列表。而且我无法摆脱字符串列表,因为我 运行 进入错误:长度不兼容。我认为我的逻辑流程是错误的,任何指向正确方向的建议都会有所帮助。我可以在我的流程正确后查看编码。
我有:
Unique.ID Collection.Date1 Test.Result1 Collection.Date2 Test.Result2 Collection.Date3
1 1 12/12/2020 positive 1/1/21 negative 44890
2 2 11/30/20 negative 1/8/21,1/20/21 negative 2/10/21,3/10/21,4/10/21
3 3 1/20/21 negative 44011 positive 44007
4 4 12/1/20 positive 44018 negative 44064
我想要的:
Unique ID Collection Date Test Result
1 12/12/20 positive
1 1/1/21 negative
1 2/2/21 NA
2 11/30/20 negative
2 1/8/21 negative
2 1//20/21 negative
2 2/10/21 NA
2 3/10/21 NA
2 4/10/21 NA
3 1/20/21 negative
3 3/3/21 positive
3 4/3/21 NA
4 12/1/20 positive
4 3/3/21 negative
4 4/3/21 NA
如果我尝试先将所有内容都变成日期,则会遇到字符串错误 bc。当我尝试扩展字符串时,由于它们的长度不同,因此出现错误。
由于您没有 post 真实数据,我们必须对您的数据集结构做出一些假设。
数据
假设,你的数据看起来像
structure(list(Unique.ID = c(1, 2, 3, 4), Collection.Date1 = c("12/12/2020",
"11/30/20", "1/20/21", "12/1/20"), Test.Result1 = c("positive",
"negative", "negative", "positive"), Collection.Date2 = c("1/1/21",
"1/8/21,1/20/21", "44011", "44018"), Test.Result2 = c("negative",
"negative", "positive", "negative"), Collection.Date3 = c("44890",
"2/10/21,3/10/21,4/10/21", "44007", "44064")), problems = structure(list(
row = c(1L, 4L), col = c(NA_character_, NA_character_), expected = c("6 columns",
"6 columns"), actual = c("7 columns", "7 columns"), file = c("literal data",
"literal data")), row.names = c(NA, -2L), class = c("tbl_df",
"tbl", "data.frame")), class = c("spec_tbl_df", "tbl_df", "tbl",
"data.frame"), row.names = c(NA, -4L), spec = structure(list(
cols = list(Unique.ID = structure(list(), class = c("collector_double",
"collector")), Collection.Date1 = structure(list(), class = c("collector_character",
"collector")), Test.Result1 = structure(list(), class = c("collector_character",
"collector")), Collection.Date2 = structure(list(), class = c("collector_character",
"collector")), Test.Result2 = structure(list(), class = c("collector_character",
"collector")), Collection.Date3 = structure(list(), class = c("collector_character",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), skip = 2L), class = "col_spec"))
或为了更好的可读性
# A tibble: 4 x 6
Unique.ID Collection.Date1 Test.Result1 Collection.Date2 Test.Result2 Collection.Date3
<dbl> <chr> <chr> <chr> <chr> <chr>
1 1 12/12/2020 positive 1/1/21 negative 44890
2 2 11/30/20 negative 1/8/21,1/20/21 negative 2/10/21,3/10/21,4/10/21
3 3 1/20/21 negative 44011 positive 44007
4 4 12/1/20 positive 44018 negative 44064
注意:这个数据看起来还不错。我真的能想到更糟糕的数据。如果您的数据还有一些问题,以下工作流程可能会失败。
工作流程
我更喜欢使用 tidyverse
中包含的软件包,在本例中为 dplyr
、tidyr
和 stringr
。
根据您的数据,我将执行以下步骤:
- 正在将数据转换为长格式。
- 分隔一个单元格中的日期,即将“2/10/21、3/10/21、4/10/21”分成单独的行。
- 将数据转换为宽格式,将日期和结果分别转换为一列。
- 整理你的约会对象,尤其是 Excel 风格的约会对象。
变成了这样的代码
library(tidyr)
library(dplyr)
library(stringr)
df %>%
pivot_longer(-Unique.ID, names_pattern="(.+)(\d)", names_to=c("name", "no") ) %>%
mutate(value = str_split(value, ",\s*")) %>%
unnest(value) %>%
pivot_wider(values_fn=list) %>%
unnest(c(Collection.Date, Test.Result)) %>%
mutate(Collection.Date = coalesce(as.Date(Collection.Date, "%m/%d/%y"),
as.Date(as.integer(Collection.Date), origin="1900-01-01"))) %>%
suppressWarnings() %>%
select(-no)
哪个returns
# A tibble: 15 x 3
Unique.ID Collection.Date Test.Result
<dbl> <date> <chr>
1 1 2020-12-12 positive
2 1 2021-01-01 negative
3 1 2022-11-27 NA
4 2 2020-11-30 negative
5 2 2021-01-08 negative
6 2 2021-01-20 negative
7 2 2021-02-10 NA
8 2 2021-03-10 NA
9 2 2021-04-10 NA
10 3 2021-01-20 negative
11 3 2020-07-01 positive
12 3 2020-06-27 NA
13 4 2020-12-01 positive
14 4 2020-07-08 negative
15 4 2020-08-23 NA
我的数据集来自 excel 由非数据导向的同事建立的文件。我的数据很敏感,所以我不能共享数据集,但我会尝试举一个例子,这样更容易理解我在说什么。我有一个唯一标识符列。我的问题是日期列。我有多个日期列。当导入到 R 中时,一些列作为日期导入,其中一些作为 excel 日期导入。然后列中的某些单元格具有一串日期(字符类型)。并非所有字符串的大小都相同。有些有 2 个列表,有些有 7 个列表。
我正在尝试整理我的数据。我的想法是将所有收集日期放在一栏中。这就是我被困的地方。我可以使用 pivot_longer() 因为并非所有列都是同一类型。我无法将 excel 日期转换为 R 日期 w/out 以摆脱字符串列表。而且我无法摆脱字符串列表,因为我 运行 进入错误:长度不兼容。我认为我的逻辑流程是错误的,任何指向正确方向的建议都会有所帮助。我可以在我的流程正确后查看编码。
我有:
Unique.ID Collection.Date1 Test.Result1 Collection.Date2 Test.Result2 Collection.Date3
1 1 12/12/2020 positive 1/1/21 negative 44890
2 2 11/30/20 negative 1/8/21,1/20/21 negative 2/10/21,3/10/21,4/10/21
3 3 1/20/21 negative 44011 positive 44007
4 4 12/1/20 positive 44018 negative 44064
我想要的:
Unique ID Collection Date Test Result
1 12/12/20 positive
1 1/1/21 negative
1 2/2/21 NA
2 11/30/20 negative
2 1/8/21 negative
2 1//20/21 negative
2 2/10/21 NA
2 3/10/21 NA
2 4/10/21 NA
3 1/20/21 negative
3 3/3/21 positive
3 4/3/21 NA
4 12/1/20 positive
4 3/3/21 negative
4 4/3/21 NA
如果我尝试先将所有内容都变成日期,则会遇到字符串错误 bc。当我尝试扩展字符串时,由于它们的长度不同,因此出现错误。
由于您没有 post 真实数据,我们必须对您的数据集结构做出一些假设。
数据
假设,你的数据看起来像
structure(list(Unique.ID = c(1, 2, 3, 4), Collection.Date1 = c("12/12/2020",
"11/30/20", "1/20/21", "12/1/20"), Test.Result1 = c("positive",
"negative", "negative", "positive"), Collection.Date2 = c("1/1/21",
"1/8/21,1/20/21", "44011", "44018"), Test.Result2 = c("negative",
"negative", "positive", "negative"), Collection.Date3 = c("44890",
"2/10/21,3/10/21,4/10/21", "44007", "44064")), problems = structure(list(
row = c(1L, 4L), col = c(NA_character_, NA_character_), expected = c("6 columns",
"6 columns"), actual = c("7 columns", "7 columns"), file = c("literal data",
"literal data")), row.names = c(NA, -2L), class = c("tbl_df",
"tbl", "data.frame")), class = c("spec_tbl_df", "tbl_df", "tbl",
"data.frame"), row.names = c(NA, -4L), spec = structure(list(
cols = list(Unique.ID = structure(list(), class = c("collector_double",
"collector")), Collection.Date1 = structure(list(), class = c("collector_character",
"collector")), Test.Result1 = structure(list(), class = c("collector_character",
"collector")), Collection.Date2 = structure(list(), class = c("collector_character",
"collector")), Test.Result2 = structure(list(), class = c("collector_character",
"collector")), Collection.Date3 = structure(list(), class = c("collector_character",
"collector"))), default = structure(list(), class = c("collector_guess",
"collector")), skip = 2L), class = "col_spec"))
或为了更好的可读性
# A tibble: 4 x 6
Unique.ID Collection.Date1 Test.Result1 Collection.Date2 Test.Result2 Collection.Date3
<dbl> <chr> <chr> <chr> <chr> <chr>
1 1 12/12/2020 positive 1/1/21 negative 44890
2 2 11/30/20 negative 1/8/21,1/20/21 negative 2/10/21,3/10/21,4/10/21
3 3 1/20/21 negative 44011 positive 44007
4 4 12/1/20 positive 44018 negative 44064
注意:这个数据看起来还不错。我真的能想到更糟糕的数据。如果您的数据还有一些问题,以下工作流程可能会失败。
工作流程
我更喜欢使用 tidyverse
中包含的软件包,在本例中为 dplyr
、tidyr
和 stringr
。
根据您的数据,我将执行以下步骤:
- 正在将数据转换为长格式。
- 分隔一个单元格中的日期,即将“2/10/21、3/10/21、4/10/21”分成单独的行。
- 将数据转换为宽格式,将日期和结果分别转换为一列。
- 整理你的约会对象,尤其是 Excel 风格的约会对象。
变成了这样的代码
library(tidyr)
library(dplyr)
library(stringr)
df %>%
pivot_longer(-Unique.ID, names_pattern="(.+)(\d)", names_to=c("name", "no") ) %>%
mutate(value = str_split(value, ",\s*")) %>%
unnest(value) %>%
pivot_wider(values_fn=list) %>%
unnest(c(Collection.Date, Test.Result)) %>%
mutate(Collection.Date = coalesce(as.Date(Collection.Date, "%m/%d/%y"),
as.Date(as.integer(Collection.Date), origin="1900-01-01"))) %>%
suppressWarnings() %>%
select(-no)
哪个returns
# A tibble: 15 x 3
Unique.ID Collection.Date Test.Result
<dbl> <date> <chr>
1 1 2020-12-12 positive
2 1 2021-01-01 negative
3 1 2022-11-27 NA
4 2 2020-11-30 negative
5 2 2021-01-08 negative
6 2 2021-01-20 negative
7 2 2021-02-10 NA
8 2 2021-03-10 NA
9 2 2021-04-10 NA
10 3 2021-01-20 negative
11 3 2020-07-01 positive
12 3 2020-06-27 NA
13 4 2020-12-01 positive
14 4 2020-07-08 negative
15 4 2020-08-23 NA