Запрос на помощь в преобразовании нечетного фрейма данных в R - PullRequest
0 голосов
/ 28 апреля 2018

У меня есть некоторые данные, которые я получил от компании, с которой я работаю, но не знаю, как подходить к преобразованию их в широкий формат данных, который я могу использовать для анализа. Фрейм данных - 15 800 000 строк и только 5 переменных. Однако 4-я и 5-я переменные - это имя и ответ на одну из (~ 90) переменных, с которыми мне приходится работать. Чтобы усложнить задачу, вопросы задавались более одного раза, поэтому ответьте несколько раз.

Однако, если существует более 1 возможного ответа, ответы переносятся на следующую строку (см. Ниже).

      id       date answer_instance                         pdl_variable_name answer_option
1  25839 2014-02-01               4                      discretspend (25228)            14
2  25839 2014-02-05              11                    legal_services (25495)          [99]
3  25839 2014-12-07               6                     comppen_company (706)          [97]
4  25837 2014-12-15               2               Affluence_V2_P_2014 (34264)             8
5  25837 2015-01-20               5      study_qualification_children (35100)          [98]
6  25837 2015-08-05               4                      overall_debt (27281)          [99]
7  25837 2015-09-03               3                 benefits_received (25465)          [98]
8  25834 2015-09-13               5                     privpen_company (707)          [96]
9  25834 2015-11-12               3            pocket_money_frequency (27076)            10
10 25835 2016-01-18               4               unemployment_status (21922)             6
11 25835 2016-02-05               8                    legal_services (25495)          [99]
12 25822 2016-02-11               3           assets_total_investable (26413)             3
13 25822 2016-03-03               2      disability_benefits_received (25055)          [99]
14 25822 2018-04-01               1               insurance_held_2018 (58085)            [1
15    4]                                                                                   
16 25811 2018-04-13               1                      insurance_held (615)            [1
17     4         11             20]                                                        
18 25811 2018-04-26               2                 profile_work_stat (25617)             5

В идеале я хотел бы преобразовать это в длинный / широкий формат, который я могу использовать для анализа. Есть идеи?

Ответы [ 3 ]

0 голосов
/ 28 апреля 2018

Основная проблема в данных, представленных OP, заключается в том, что единственная запись распространяется на следующую строку. Следовательно, после правильного размещения строк будет довольно легко преобразовать данные в любую форму для анализа.

Положительный прогноз вперед ^(?=.*]) на ] и Отрицательный прогноз вперед (?!.*\\[) на [ используется для определения, является ли строка частичной и является ли она второй частью предыдущего ряда.

Столбец space и ( с pdl_variable_name был изменен на _(, чтобы его можно было прочитать как один столбец с помощью read.table

library(tidyverse)
library(splitstackshape)

# Read from text file linewise
df_line <- data.frame(fileText = readLines("Answer.txt"), stringsAsFactors = FALSE)


tidy_text <- df_line %>% mutate(rn = row_number()) %>%  # To merge partial row
  mutate(rn = ifelse(grepl("^(?=.*])(?!.*\\[)",df$fileText, perl = TRUE),lag(rn), rn)) %>%  #doesnot contain [ but contains ]
  group_by(rn) %>%
  summarise(fileText = paste0(trimws(fileText), collapse=" ")) %>%
  ungroup() %>%
  mutate(fileText = gsub("\\s(\\()", "_\\1", fileText)) %>%
  mutate(fileText = gsub("\\[|]", "\\'", fileText))  # [1 4] is changed to '1 4'


  # Concatenate rows prepared above separated by '\n' so that it read as dataframe 
  tidy_data <- read.table(text = paste0(trimws(tidy_text$fileText), collapse="\n"), header = TRUE, stringsAsFactors = FALSE)

  #Use cSplit to split answers in multiple columns
  tidy_data  <- tidy_data %>%
    mutate(pdl_variable_name = gsub("_(\\()", " \\1", pdl_variable_name)) %>%
    cSplit("answer_option", sep=" ")

Результат:

 tidy_data         
 #       id       date answer_instance                    pdl_variable_name answer_option_1 answer_option_2 answer_option_3 answer_option_4
 # 1: 25839 2014-02-01               4                 discretspend (25228)              14              NA              NA              NA
 # 2: 25839 2014-02-05              11               legal_services (25495)              99              NA              NA              NA
 # 3: 25839 2014-12-07               6                comppen_company (706)              97              NA              NA              NA
 # 4: 25837 2014-12-15               2          Affluence_V2_P_2014 (34264)               8              NA              NA              NA
 # 5: 25837 2015-01-20               5 study_qualification_children (35100)              98              NA              NA              NA
 # 6: 25837 2015-08-05               4                 overall_debt (27281)              99              NA              NA              NA
 # 7: 25837 2015-09-03               3            benefits_received (25465)              98              NA              NA              NA
 # 8: 25834 2015-09-13               5                privpen_company (707)              96              NA              NA              NA
 # 9: 25834 2015-11-12               3       pocket_money_frequency (27076)              10              NA              NA              NA
 # 10: 25835 2016-01-18               4          unemployment_status (21922)               6              NA              NA              NA
 # 11: 25835 2016-02-05               8               legal_services (25495)              99              NA              NA              NA
 # 12: 25822 2016-02-11               3      assets_total_investable (26413)               3              NA              NA              NA
 # 13: 25822 2016-03-03               2 disability_benefits_received (25055)              99              NA              NA              NA
 # 14: 25822 2018-04-01               1          insurance_held_2018 (58085)               1               4              NA              NA
 # 15: 25811 2018-04-13               1                 insurance_held (615)               1               4              11              20
 # 16: 25811 2018-04-26               2            profile_work_stat (25617)               5              NA              NA              NA

Необработанные данные:

Содержимое answer.txt, как указано в OP:

   id       date answer_instance                         pdl_variable_name answer_option
25839 2014-02-01               4                      discretspend (25228)            14
25839 2014-02-05              11                    legal_services (25495)          [99]
25839 2014-12-07               6                     comppen_company (706)          [97]
25837 2014-12-15               2               Affluence_V2_P_2014 (34264)             8
25837 2015-01-20               5      study_qualification_children (35100)          [98]
25837 2015-08-05               4                      overall_debt (27281)          [99]
25837 2015-09-03               3                 benefits_received (25465)          [98]
25834 2015-09-13               5                     privpen_company (707)          [96]
25834 2015-11-12               3            pocket_money_frequency (27076)            10
25835 2016-01-18               4               unemployment_status (21922)             6
25835 2016-02-05               8                    legal_services (25495)          [99]
25822 2016-02-11               3           assets_total_investable (26413)             3
25822 2016-03-03               2      disability_benefits_received (25055)          [99]
25822 2018-04-01               1               insurance_held_2018 (58085)            [1
4]                                                                                   
25811 2018-04-13               1                      insurance_held (615)            [1
4         11             20]                                                        
25811 2018-04-26               2                 profile_work_stat (25617)             5
0 голосов
/ 28 апреля 2018

Надеюсь, это поможет!

library(readr)
library(tidyverse)
library(splitstackshape)

#read file
txt <- read_lines(file = "file_path/test.txt")

#identify continuation of previous row and add it to the previous row
idx <- which(grepl('\\]\\s+$', txt)) 
txt <- gsub("^\\d+\\s+", "", txt)    #remove row number from each row
txt[idx-1] <- paste(txt[idx-1], trimws(txt[idx]))
txt <- txt[-c(1,idx)]

#add a separator ";" to identify different columns in each row
txt <- gsub("(\\S+)\\s+(\\S+)\\s+(\\S+)\\s+(\\S+\\s+\\S+)\\s+(.*)", "\\1;\\2;\\3;\\4;\\5", txt)

#prepare data for analysis
df <- as.data.frame(txt) %>%
  cSplit("txt", sep = ";") %>%
  `colnames<-`(c("id", "date", "answer_instance", "pdl_variable_name", "answer_option")) %>%
  mutate(answer_option = gsub("\\[|\\]|(\\s{2})+", "", answer_option)) %>%
  separate_rows("answer_option", sep=" ")
df

Вывод:

      id       date answer_instance                    pdl_variable_name answer_option
1  25839 2014-02-01               4                 discretspend (25228)            14
2  25839 2014-02-05              11               legal_services (25495)            99
3  25839 2014-12-07               6                comppen_company (706)            97
4  25837 2014-12-15               2          Affluence_V2_P_2014 (34264)             8
5  25837 2015-01-20               5 study_qualification_children (35100)            98
6  25837 2015-08-05               4                 overall_debt (27281)            99
7  25837 2015-09-03               3            benefits_received (25465)            98
8  25834 2015-09-13               5                privpen_company (707)            96
9  25834 2015-11-12               3       pocket_money_frequency (27076)            10
10 25835 2016-01-18               4          unemployment_status (21922)             6
11 25835 2016-02-05               8               legal_services (25495)            99
12 25822 2016-02-11               3      assets_total_investable (26413)             3
13 25822 2016-03-03               2 disability_benefits_received (25055)            99
14 25822 2018-04-01               1          insurance_held_2018 (58085)             1
15 25822 2018-04-01               1          insurance_held_2018 (58085)             4
16 25811 2018-04-13               1                 insurance_held (615)             1
17 25811 2018-04-13               1                 insurance_held (615)             4
18 25811 2018-04-13               1                 insurance_held (615)            11
19 25811 2018-04-13               1                 insurance_held (615)            20
20 25811 2018-04-26               2            profile_work_stat (25617)             5

Пример данных:

      id       date answer_instance                         pdl_variable_name answer_option
1  25839 2014-02-01               4                      discretspend (25228)            14
2  25839 2014-02-05              11                    legal_services (25495)          [99]
3  25839 2014-12-07               6                     comppen_company (706)          [97]
4  25837 2014-12-15               2               Affluence_V2_P_2014 (34264)             8
5  25837 2015-01-20               5      study_qualification_children (35100)          [98]
6  25837 2015-08-05               4                      overall_debt (27281)          [99]
7  25837 2015-09-03               3                 benefits_received (25465)          [98]
8  25834 2015-09-13               5                     privpen_company (707)          [96]
9  25834 2015-11-12               3            pocket_money_frequency (27076)            10
10 25835 2016-01-18               4               unemployment_status (21922)             6
11 25835 2016-02-05               8                    legal_services (25495)          [99]
12 25822 2016-02-11               3           assets_total_investable (26413)             3
13 25822 2016-03-03               2      disability_benefits_received (25055)          [99]
14 25822 2018-04-01               1               insurance_held_2018 (58085)            [1
15    4]                                                                                   
16 25811 2018-04-13               1                      insurance_held (615)            [1
17     4         11             20]                                                        
18 25811 2018-04-26               2                 profile_work_stat (25617)             5

в test.txt

0 голосов
/ 28 апреля 2018

Если мы игнорируем формат данных для нескольких ответов, вы можете dcast ваши данные, как это:

library(data.table)
dt <- data.table(df)
dt.wide <- dcast(
  formula =  date +  answer_instance ~ pdl_variable_name, 
  data = dt, 
  value.var = "answer_option"
)

Для нескольких вариантов вам нужно запросить данные в формате, который вы можете прочитать в data.frame, если хотите использовать R.

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

Поскольку ваш файл относительно большой, я рекомендую использовать data.table с быстрой fread функцией.

...