我想重组我的数据框,其中包含有关是否查看,购买或出售房屋以及查看/购买/出售日期的数据。
以这样一种方式输入数据:尽管存在多个日期变量(var_datevar_A5_3_B32
,var_datevar_A5_4_B33
,var_datevar_A5_5_B34
),但是这些变量中的每一个都包含销售日期的混合,购买日期和查看日期。
因此,如果想知道例如var_datevar_A5_3_B32
中的日期是观看,销售或购买日期,我需要检查具有匹配前缀(A5_3_B32)的变量,即var_viewed_A5_3_B32
,{ {1}}和var_sold_A5_3_B32
,然后查看哪个编码为“ Y”。
我想在数据框中添加三个新变量:仅销售日期变量(var_purchased_A5_3_B32
),仅购买日期变量(var_date_sold
)和仅观看日期变量( var_date_purchased
),就像在var_date_viewed
中一样。
我已经尝试过,但除此之外,我无法弄清楚如何将日期粘贴到新变量中,我想要一个更通用的解决方案,因为在我的真实数据集中,我有很多变量像这样。
感谢您的帮助!
dfgoal
答案 0 :(得分:0)
使用软件包dplyr
,tidyr
和stringr
的另一种方法:
library(tidyr)
library(dplyr)
library(stringr)
df %>%
gather(datevar, date, contains("datevar")) %>%
gather(action, action_yn, -datevar, -date, -var_home) %>%
mutate(date_code = str_extract(datevar, "A\\d_\\d_B\\d\\d$"),
action_code = str_extract(action, "A\\d_\\d_B\\d\\d$"),
action = str_extract(action, "^var_[[a-z][^_]]+"),
action = str_remove(action, "^var_")) %>%
filter(date_code == action_code) %>%
filter(action_yn == "Y") %>%
select(-datevar) %>%
group_by(var_home, action) %>%
summarise(date = str_c(date, collapse = ",")) %>%
mutate(action = str_c("var_date_", action)) %>%
spread(action, date)
# A tibble: 5 x 4
# Groups: var_home [5]
# var_home var_date_purchased var_date_sold var_date_viewed
# <fct> <chr> <chr> <chr>
# 1 a 05-03-2013 07-12-2012 01-12-2012
# 2 b 05-06-2014 NA NA
# 3 c 07-07-2017 NA 03-09-2015
# 4 d NA NA 03-03-2016,13-03-2016,23-03-2016
# 5 e NA NA NA
我将代码分成几部分来解释,该怎么做。
首先将数据从宽格式转换为长格式,然后首先将所有datvar
收集起来,然后将所有操作一起包含在一个列中,每个列都具有对应的值(date
和action_yn
)。
df <- df %>%
gather(datevar, date, contains("datevar")) %>%
gather(action, action_yn, -datevar, -date, -var_home)
df
# var_home datevar date action action_yn
# 1 a var_datevar_A5_3_B32 01-12-2012 var_purchased_A5_3_B32 <NA>
# 2 b var_datevar_A5_3_B32 05-06-2014 var_purchased_A5_3_B32 Y
# 3 c var_datevar_A5_3_B32 03-09-2015 var_purchased_A5_3_B32 <NA>
# 4 d var_datevar_A5_3_B32 03-03-2016 var_purchased_A5_3_B32 <NA>
# 5 e var_datevar_A5_3_B32 <NA> var_purchased_A5_3_B32 <NA>
# ...
然后使用正则表达式提取代码(每个列名称的最后一部分)。在这里,我假设这总是像A#_#_ B ##那样构造,其中#是数字。此外,使用常规表达式再次提取特定动作。
df <- df %>%
mutate(date_code = str_extract(datevar, "A\\d_\\d_B\\d\\d$"),
action_code = str_extract(action, "A\\d_\\d_B\\d\\d$"),
action = str_extract(action, "^var_[[a-z][^_]]+"),
action = str_remove(action, "^var_"))
df
# var_home datevar date action action_yn date_code action_code
# 1 a var_datevar_A5_3_B32 01-12-2012 purchased <NA> A5_3_B32 A5_3_B32
# 2 b var_datevar_A5_3_B32 05-06-2014 purchased Y A5_3_B32 A5_3_B32
# 3 c var_datevar_A5_3_B32 03-09-2015 purchased <NA> A5_3_B32 A5_3_B32
# 4 d var_datevar_A5_3_B32 03-03-2016 purchased <NA> A5_3_B32 A5_3_B32
# 5 e var_datevar_A5_3_B32 <NA> purchased <NA> A5_3_B32 A5_3_B32
# ...
因为我们只对带有“ Y”的动作感兴趣,并且只对与正确动作相对应的日期进行了编码和action_yn的过滤。 datevar
不再需要,因此被删除。
df <- df %>%
filter(date_code == action_code) %>%
filter(action_yn == "Y") %>%
select(-datevar)
df
# var_home date action action_yn date_code action_code
# 1 b 05-06-2014 purchased Y A5_3_B32 A5_3_B32
# 2 c 07-07-2017 purchased Y A5_4_B33 A5_4_B33
# 3 a 05-03-2013 purchased Y A5_5_B34 A5_5_B34
# 4 a 01-12-2012 viewed Y A5_3_B32 A5_3_B32
# 5 c 03-09-2015 viewed Y A5_3_B32 A5_3_B32
# 6 d 03-03-2016 viewed Y A5_3_B32 A5_3_B32
# 7 d 13-03-2016 viewed Y A5_4_B33 A5_4_B33
# 8 d 23-03-2016 viewed Y A5_5_B34 A5_5_B34
# 9 a 07-12-2012 sold Y A5_4_B33 A5_4_B33
# 10 e <NA> sold Y A5_5_B34 A5_5_B34
最后,对于每个var_home
和每个action
,将日期粘贴在一起(如果有多个日期),将操作重命名(以获得所需的最终列名),然后将每个操作散布到自己的列(带有spread
):
df <- df %>%
group_by(var_home, action) %>%
summarise(date = str_c(date, collapse = ",")) %>%
mutate(action = str_c("var_date_", action)) %>%
spread(action, date)
如果您希望将此信息与原始数据一起存储,请假定将其存储在df_org
中。然后,您可以使用join
:
left_join(df_org, df, by = "var_home")
# var_home var_datevar_A5_3_B32 var_datevar_A5_4_B33 ... var_sold_A5_4_B33 var_sold_A5_5_B34 var_date_purchased var_date_sold var_date_viewed
# 1 a 01-12-2012 07-12-2012 ... Y N 05-03-2013 07-12-2012 01-12-2012
# 2 b 05-06-2014 <NA> ... N <NA> 05-06-2014 <NA> <NA>
# 3 c 03-09-2015 07-07-2017 ... <NA> <NA> 07-07-2017 <NA> 03-09-2015
# 4 d 03-03-2016 13-03-2016 ... N <NA> <NA> <NA> 03-03-2016,13-03-2016,23-03-2016
# 5 e <NA> <NA> ... <NA> Y <NA> <NA> <NA>