我的数据中有一个列变量,它是一个时间范围:datesowned
。样本数据如下:
name datesemployed university
Kate Oct 2015 – Jan 2016 Princeton
Sue Nov 2015 – Dec 2017 Pomona
我想分隔行,以便时间范围内的每一年都有自己的行:
name datesemployed university
Kate 2015 Princeton
Kate 2016 Princeton
Sue 2015 Pomona
Sue 2016 Pomona
Sue 2017 Pomona
在separate post中,解决方案是根据 -
分隔行。但该解决方案仅在时间范围始终为一年的情况下才有效。例如,如果数据是 2015-2017
,我将缺少 2016 的一行。
上一个答案中的 separate_rows
语法对我来说很有意义,但我不确定如何使其适应这种情况,或者是否有可能这样做。我还发现,对于大数据帧(~1000 个观察值),separate_rows
非常慢,并且对我来说会卡住 R。
最佳答案
我们可以使用 str_extract_all
提取“年份”部分,然后通过循环 list
列并取消嵌套
输出来执行序列
library(dplyr)
library(tidyr)
library(stringr)
df1 %>%
mutate(datesemployed = map(str_extract_all(datesemployed,
"\\d+"), ~as.numeric(.x[1]):as.numeric(.x[2]))) %>%
unnest(c(datesemployed))
# A tibble: 5 x 3
# name datesemployed university
# <chr> <int> <chr>
#1 Kate 2015 Princeton
#2 Kate 2016 Princeton
#3 Sue 2015 Pomona
#4 Sue 2016 Pomona
#5 Sue 2017 Pomona
或者另一种选择是在“受雇日期”上使用separate_rows
,然后在按“name”、“university”分组后使用complete
,我们可以扩展数据
df1 %>%
separate_rows(datesemployed, sep= "\\s*–\\s*") %>%
mutate(datesemployed = readr::parse_number(datesemployed)) %>%
group_by(name, university) %>%
complete(datesemployed =min(datesemployed):max(datesemployed))
或者在基础R
中
lst1 <- lapply(gsub(".*\\s+(\\d+)\\D+(\\d+)", "\\1:\\2",
df1$datesemployed), function(x) eval(parse(text = x)))
transform(df1[rep(seq_len(nrow(df1)), lengths(lst1)), c("name", "university")],
datesemployed = unlist(lst1))
数据
df1 <- structure(list(name = c("Kate", "Sue"), datesemployed =
c("Oct 2015 – Jan 2016",
"Nov 2015 – Dec 2017"), university = c("Princeton", "Pomona"
)), class = "data.frame", row.names = c(NA, -2L))
关于根据时间范围变量重复行 - R,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61703818/