новые переменные из неопрятных данных на основе сопоставления суффиксов - PullRequest
0 голосов
/ 03 сентября 2018

Я хотел бы реструктурировать свой фрейм данных, который содержит данные о том, был ли дом просмотрен, куплен или продан, а также о дате просмотра / покупки / продажи.

Данные были введены таким образом, что, хотя существует несколько переменных даты (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, var_sold_A5_3_B32, и var_purchased_A5_3_B32 и посмотрите, какой из них закодирован как "Y".

Я бы хотел добавить три новые переменные в мой фрейм данных: переменная только для дат продаж (var_date_sold), переменная только для дат покупок (var_date_purchased) и переменная только для дат просмотра (var_date_viewed) как в dfgoal.

Я предпринял попытку, но кроме этого я не могу понять, как вставить дату в мою новую переменную, я хотел бы найти более общее решение, потому что в моем реальном наборе данных у меня есть множество переменных как это.

Спасибо за любую помощь!

# Starting point 
df <- data.frame(var_home=c("a","b","c","d","e"),
                 var_datevar_A5_3_B32=c("01-12-2012","05-06-2014","03-09-2015","03-03-2016",NA),var_datevar_A5_4_B33=c("07-12-2012",NA,"07-07-2017","13-03-2016",NA),var_datevar_A5_5_B34=c("05-03-2013",NA,NA,"23-03-2016",NA),var_purchased_A5_3_B32=c(NA,"Y",NA,NA,NA),var_purchased_A5_4_B33=c("N","N","Y",NA,NA),var_purchased_A5_5_B34=c("Y",NA,NA,NA,NA),
                 var_viewed_A5_3_B32=c("Y","N","Y","Y",NA),var_viewed_A5_4_B33=c(NA,NA,NA,"Y","N"),var_viewed_A5_5_B34=c(NA,NA,NA,"Y",NA),var_sold_A5_3_B32=c("NA","N",NA,"N",NA),var_sold_A5_4_B33=c("Y","N",NA,"N",NA),var_sold_A5_5_B34=c("N",NA,NA,NA,"Y"))



# Goal
dfgoal <- data.frame(var_home=c("a","b","c","d","e"),
                 var_datevar_A5_3_B32=c("01-12-2012","05-06-2014","03-09-2015","03-03-2016",NA),var_datevar_A5_4_B33=c("07-12-2012",NA,"07-07-2017","13-03-2016",NA),var_datevar_A5_5_B34=c("05-03-2013",NA,NA,"23-03-2016",NA),var_purchased_A5_3_B32=c(NA,"Y",NA,NA,NA),var_purchased_A5_4_B33=c("N","N","Y",NA,NA),var_purchased_A5_5_B34=c("Y",NA,NA,NA,NA),
                 var_viewed_A5_3_B32=c("Y","N","Y","Y",NA),var_viewed_A5_4_B33=c(NA,NA,NA,"Y","N"),var_viewed_A5_5_B34=c(NA,NA,NA,"Y",NA),var_sold_A5_3_B32=c("NA","N",NA,"N",NA),var_sold_A5_4_B33=c("Y","N",NA,"N",NA),var_sold_A5_5_B34=c("N",NA,NA,NA,"Y"),
                 var_date_viewed =c("01-12-2012",NA,"03-09-2015","03-03-2016,13-03-2016,23-03-2016",NA),var_date_sold=c("07-12-2012",NA,NA,NA,NA),var_date_purchased=c("05-03-2013","05-06-2014","07-07-2017",NA,NA))



# Attempt pseudo-code 
var_date_viewed <- ifelse((!is.na(var_datevar_A5_3_B32) & var_viewed_A5_3_B32=="Y") | (!is.na(var_datevar_A5_4_B33) & var_viewed_A5_4_B33=="Y") | (!is.na(var_datevar_A5_5_B34) & var_viewed_A5_5_B34=="Y"), PASTE_THE_DATE,NA)

1 Ответ

0 голосов
/ 03 сентября 2018

Другой подход с использованием пакетов 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" и только даты, соответствующие правильному действию, мы фильтруем по кодам de и 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>
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...