在我的縱向資料集中,每一行代表每個人的觀察時間段,每一行都以開始和結束日期為界。這些行被編號('episode'),并包含許多特定于行的變數(例如,'edu_level'),我需要在以下步驟中保留這些變數。
我創建了一個新的日期變數 hx_start,它可以以 3 種方式中的 1 種方式關聯每行資料的開始和結束日期(如下)。對于每種情況,我需要使用 dplyr相應地編輯(拼接)現有資料行:
1. 在給定行的開始日期和結束日期之間(即,就像對第 2 個人和第 4 個人所做的那樣) 在這種情況下,我想將現有行拼接成兩個新行,以便 hx_start 的日期是一個的開始日期的行。另一行將保留原始行的開始日期,其結束日期將比 hx_start 日期早一天。
2. 與某人的行開始日期相同的日期(即第 1 個人) 在這種情況下,不需要更改。
3. 在與某人的行結束日期相同的日期(即第 3 個人) 與 #1 相同:我需要將現有行拼接成兩個新行,以便 hx_start 的日期是其中一行的開始日期。另一行將保留原始行的開始日期,其結束日期將比 hx_start 日期早一天。
到目前為止,我已經創建了一個新資料集,其中每行有 2 個重復項,假設我需要對現有行最多編輯 2 行,然后洗掉原件(或僅保留原件,如果是 person 1)。重要的是,如果可能的話,我需要一種方法將所有其他變數從原始行轉移到所有新行,而不用全部命名(我的真實資料集中有很多)。
#Load packages
library(lubridate)
#>
#> Attaching package: 'lubridate'
#> The following objects are masked from 'package:base':
#>
#> date, intersect, setdiff, union
#Create data set
person <- c(1, 2, 3, 4)
episode <- c(33, 50, 65, 70)
start <- c('2013-01-01', '2010-01-21', '2009-09-18', '2010-05-26')
end <- c('2013-06-04', '2010-06-19', '2009-12-31', '2010-12-24')
hx_start <- c('2013-01-01', '2010-03-09', '2009-12-31', '2010-07-04')
edu_level <- c(2, 3, 2, 1)
#Populate data frame
d <- cbind(person, episode, start, hx_start, end, edu_level)
d <- as.data.frame(d)
#Format dates and add to data frame
d$start <- as.Date(start, format = '%Y-%m-%d')
d$end <- as.Date(end, format = '%Y-%m-%d')
d$hx_start <- as.Date(hx_start, format = '%Y-%m-%d')
#Create 2 duplicates of this row for each person
d1 <- d[rep(seq_len(nrow(d)), each = 3), ]
d1
#> person episode start hx_start end edu_level
#> 1 1 33 2013-01-01 2013-01-01 2013-06-04 2
#> 1.1 1 33 2013-01-01 2013-01-01 2013-06-04 2
#> 1.2 1 33 2013-01-01 2013-01-01 2013-06-04 2
#> 2 2 50 2010-01-21 2010-03-09 2010-06-19 3
#> 2.1 2 50 2010-01-21 2010-03-09 2010-06-19 3
#> 2.2 2 50 2010-01-21 2010-03-09 2010-06-19 3
#> 3 3 65 2009-09-18 2009-12-31 2009-12-31 2
#> 3.1 3 65 2009-09-18 2009-12-31 2009-12-31 2
#> 3.2 3 65 2009-09-18 2009-12-31 2009-12-31 2
#> 4 4 70 2010-05-26 2010-07-04 2010-12-24 1
#> 4.1 4 70 2010-05-26 2010-07-04 2010-12-24 1
#> 4.2 4 70 2010-05-26 2010-07-04 2010-12-24 1
由reprex 包創建于 2022-03-23 (v2.0.0 )
uj5u.com熱心網友回復:
您可以通過創建一個小的輔助函式來做到這一點。我已經使用 data.table 格式完成了這項作業
library(data.table)
f <- function(s,m,e) {
if(m>s) return(list("start" = c(m,s),"hx_start" = c(m,m),"end" = c(e,m-1)))
if(m == s) return (list("start" = s,"hx_start" = m,"end" =e))
}
setDT(d)[,!c(3:5)][d[ ,f(start,hx_start,end), by=person], on=.(person)]
輸出:
person episode edu_level start hx_start end
1: 1 33 2 2013-01-01 2013-01-01 2013-06-04
2: 2 50 3 2010-03-09 2010-03-09 2010-06-19
3: 2 50 3 2010-01-21 2010-03-09 2010-03-08
4: 3 65 2 2009-12-31 2009-12-31 2009-12-31
5: 3 65 2 2009-09-18 2009-12-31 2009-12-30
6: 4 70 1 2010-07-04 2010-07-04 2010-12-24
7: 4 70 1 2010-05-26 2010-07-04 2010-07-03
請注意:
- 對于人 2,4,一行現在有 hx_start 作為開始日期,另一行有原始開始日期,而結束日期是 hx_start 日期的前一天。
- 對于人 1,沒有變化
- 對于第 3 個人,一行現在將 hx_start 作為開始日期,另一行具有原始開始日期,而結束日期是 hx_start 日期的前一天。
Tidyverse 選項(也使用上述功能)
inner_join(
d %>% select(-c(start,hx_start,end)),
d %>%
rowwise() %>%
summarize(person = max(person),
dates = list(f(start,hx_start,end))) %>%
unnest_wider(dates) %>%
unnest(cols=everything()),
by = "person"
)
輸出:
person episode edu_level start hx_start end
1: 1 33 2 2013-01-01 2013-01-01 2013-06-04
2: 2 50 3 2010-03-09 2010-03-09 2010-06-19
3: 2 50 3 2010-01-21 2010-03-09 2010-03-08
4: 3 65 2 2009-12-31 2009-12-31 2009-12-31
5: 3 65 2 2009-09-18 2009-12-31 2009-12-30
6: 4 70 1 2010-07-04 2010-07-04 2010-12-24
7: 4 70 1 2010-05-26 2010-07-04 2010-07-03
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/448531.html
下一篇:在Pandas中按周分組資料
