如何处理数据集中的合并变量和拆分变量

问题描述

我有一个数据(当前为csv),其中包含一个带事件的变量(可以为空或包含最多30个由空格分隔的事件代码),然后每个事件的事件日期分别在单独的变量ED1,ED2,ED3中...

要从这些数据中获取有用的信息,我需要能够找到每个事件的日期。我的方法是将事件变量拆分为新行,但我对如何正确设置日期感到困扰。 (我正在使用R,因为稍后将使用它来分析数据,但我正在考虑也许切换到sql来管理数据)。

为简单起见,最多只能采样5个事件的数据:

# Sample data
df <- data.frame(ID = 1:5,E = c("FTT JAD AHN TKZ","","JAD FTT","AJN","TKZ AHD"),ED1 = as.Date(c("2016-04-01","2014-12-31","2019-05-15","2005-05-04")),ED2 = as.Date(c("2009-06-18","2007-11-12","2004-04-09")),ED3 = as.Date(c("2004-09-19","")),ED4 = as.Date(c("2012-07-15",ED5 = as.Date(NA))
# New variable with all dates
df %>%
  unite(ED,ED1:ED5,sep=" ",na.rm=T) -> df

# Separate rows
df %>%
  separate_rows(E,ED,sep=" ") -> df

这适用于此示例数据集,但是当我尝试将其应用于我的数据时,出现错误

Error: Incompatible lengths: 4,2.

如果我是正确的话,这意味着EED会分成不同的行数。所以我认为数据集缺少数据。我试图用以下方法验证这一点:

df %>% 
  unite(ED,na.rm=T) %>%
  mutate(E = strsplit(E," "),ED = strsplit(ED," ")) %>% 
  filter(length(E) != length(ED))

[1] ID E  ED
<0 rows>

但是,如果我尝试分别在separate_rows()EED,则会得到不同数量的行。这就是我被困住的地方。

其他问题: 在另一个数据帧中,我想为每个ID添加一个布尔值,如果该ID参加了两个日期之间的特定事件类型或是否不基于此数据帧。每个ID可以在事件数据帧中多次出现,并且每个ID可以多次参加相同类型的事件。

解决方法

问题显然是由于分隔E值的空格数比ED中的空格差这一事实引起的。为了解决这个问题,您可以只拆分E列,并用空字符串填充值。

library(tidyverse)
#> Warning: package 'tibble' was built under R version 3.6.2
#> Warning: package 'purrr' was built under R version 3.6.2

# Sample data
df <- data.frame(ID = 1:5,E = c("FTT JAD AHN TKZ","","JAD FTT","AJN","TKZ AHD"),ED1 = as.Date(c("2016-04-01","2014-12-31","2019-05-15","2005-05-04")),ED2 = as.Date(c("2009-06-18","2007-11-12","2004-04-09")),ED3 = as.Date(c("2004-09-19","")),ED4 = as.Date(c("2012-07-15",ED5 = as.Date(NA),stringsAsFactors=F)
# testing 
df %>% 
  mutate(E = strsplit(E," ")) %>% 
  # change 5 to 30 if you want to use this code on your data
  filter(lengths(E) != 5)
#>   ID                  E        ED1        ED2        ED3        ED4  ED5
#> 1  1 FTT,JAD,AHN,TKZ 2016-04-01 2009-06-18 2004-09-19 2012-07-15 <NA>
#> 2  2                          <NA>       <NA>       <NA>       <NA> <NA>
#> 3  3           JAD,FTT 2014-12-31 2007-11-12       <NA>       <NA> <NA>
#> 4  4                AJN 2019-05-15       <NA>       <NA>       <NA> <NA>
#> 5  5           TKZ,AHD 2005-05-04 2004-04-09       <NA>       <NA> <NA>

df %>% 
   mutate( E=lapply(strsplit(E," "),function(x) c(x,rep("",5-length(x))) )) -> df.split 

### First method keeps numerical format for date and NAs
df.split %>% 
    nest(ED=starts_with("ED"))  %>% 
    mutate(ED=lapply(ED,function(x) unlist(x[1,],use.names=FALSE))) %>%
    unnest(c(E,ED))
#> # A tibble: 25 x 3
#>       ID E        ED
#>    <int> <chr> <dbl>
#>  1     1 "FTT" 16892
#>  2     1 "JAD" 14413
#>  3     1 "AHN" 12680
#>  4     1 "TKZ" 15536
#>  5     1 ""       NA
#>  6     2 ""       NA
#>  7     2 ""       NA
#>  8     2 ""       NA
#>  9     2 ""       NA
#> 10     2 ""       NA
#> # … with 15 more rows

### Second method Everything is a string
df.split %>%
  unite(ED,ED1:ED5,sep=" ",na.rm=T)%>%
  mutate( ED = strsplit(ED," ")) %>%
  unnest(c(E,ED))
#> # A tibble: 25 x 3
#>       ID E     ED   
#>    <int> <chr> <chr>
#>  1     1 "FTT" 16892
#>  2     1 "JAD" 14413
#>  3     1 "AHN" 12680
#>  4     1 "TKZ" 15536
#>  5     1 ""    NA   
#>  6     2 ""    NA   
#>  7     2 ""    NA   
#>  8     2 ""    NA   
#>  9     2 ""    NA   
#> 10     2 ""    NA   
#> # … with 15 more rows

整齐

df%>% 
    separate(E,into=paste0("E",1:5),fill="right",sep=" ") %>%
    unite(E,E1:E5,sep=" ") %>%
    unite(ED,sep=" ") %>%
    mutate(E=strsplit(E,ED=strsplit(ED," ")) %>%
    unnest(c(E,ED)) %>% mutate(ED=as.Date(ED)) %>% filter(!is.na(ED))
#>      ID E     ED        
#>   <int> <chr> <date>     
#> 1     1 FTT   2016-04-01
#> 2     1 JAD   2009-06-18
#> 3     1 AHN   2004-09-19
#> 4     1 TKZ   2012-07-15
#> 5     3 JAD   2014-12-31
#> 6     3 FTT   2007-11-12
#> 7     4 AJN   2019-05-15
#> 8     5 TKZ   2005-05-04
#> 9     5 AHD   2004-04-09