.

Сделать репост в соц сети!

воскресенье, 12 августа 2018 г.

Препроцессинг данных: если часть переменной категориальная, часть числовая (с кодом в R)



90 % работы аналитика это извлечение и препроцессинг данных. Хочу поделиться, как я решил одну проблему, которую сам себе же и создал.
Самый пост технически не сложный, но, надеюсь, фишки кода препроцессинга будут оценены теми, кто работает в R. Ну и саму логику решения задачи:)

Препроцессинг данных: если часть переменной категориальная, часть числовая (с кодом в R)

Проблема

  • В моем опросе Портрет HR-директора (кстати, поучаствуйте) есть такие вопросы "Количество подчиненных HR-директора (размер HR-службы) - укажите число работников службы HR - можно приблизительно"
  • "Размер компании (количество работающих) - укажите число работников компании, хотя бы приблизительно". 
Изначально эти вопрос представлял собой тип вопроса "one choice" - респондент выбирал один вариант из нескольких предложенных (далее буду показывать на примере вопрос о размере HR службы):
  • 'ни одного'
  • 'от 1 до 3' 
  • 'от 4 до 10' 
  • 'от 11 до 30' 
  • 'более 30'



Потом я понял, что эта переменная дает слишком грубое приближение размера HR службы. И решил изменить тип вопроса, теперь респонденты ничего не выбирают, а руками пишут размер службы. Получается примерно так

4
25
50
0
12
1
13
50
5
Теперь в одной переменной у нас разного типа данные.
Проблема в том, что делать с первой частью переменной, там где 'от 4 до 10'. У меня там 205 строк. Можно просто удалить их. Но жалко терять. Согласитесь.
Можно заменить значения таким образом
  • 'ни одного' - 0
  • 'от 1 до 3'  - 2
  • 'от 4 до 10' - 7
  • 'от 11 до 30' - 25
  • 'более 30' - ....
Просто взять примерно среднее значение. Но не факт, что верно. И с последним значением совсем нехорошо выходит: там служба более 30, сколько по факту, мы не можем знать. И исказим данные.

Решение

должно быть таким: полученные числовые данные (те, когда респонденты руками заполняли размер HR службы), разбить их на страты ('ни одного', 'от 1 до 3', 'от 4 до 10' , 'от 11 до 30' , 'более 30'), получить для каждой страты медианы, а потом заменить наши реальные страты на эти значения. 

Если не поняли, надеюсь, кодом все покажу.

1. Subset

Выделяем выборку, которая содержит только числовые значения размера HR службы
q1 = subset(q, as.numeric(rownames(q)) > 205) 
q - мой полный датасет, кодом я показываю, что беру данные выше 205 строки по индексу. Ниже этой строки данные типа 'от 1 до 3' и т.п..

2. Меняем тип переменной 

Далее нам надо переменную "размер hr службы" сделать числовой (она у нас по категориальная. Делается это так
q1$hr = as.numeric(as.character(q1$размер.hr.службы)) 
Обратите внимание, я сначала делаю ее типа character, а потом уже числовой.

3. Страты

С помощью функции cut я разбиваю нашу переменную на страты
q1$straty = cut(q1$hr, br=c(0, 3, 10, 30, 30000), labels = c('very_low', 'low', 'ave', 'high')) 

4. Описательные статистики

Получаем описательные статистики для каждой страты

 tapply(q1$hr, q1$straty, summary)
$very_low
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  1.000   1.000   2.000   2.032   3.000   3.000 

$low
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  4.000   5.000   6.000   6.652   8.000  10.000 

$ave
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  12.00   15.00   19.00   19.82   25.00   30.00 

$high
   Min. 1st Qu.  Median    Mean 3rd Qu.    Max. 
  34.00   40.00   50.00   58.07   67.50  100.00
Можно было сразу медианы получить, но я хотел посмотреть на распределение, чтобы понять, нормально оно или нет.


5. Замена данных 

Теперь нам надо заменить в первых 205 строках наши категориальные признаки на значения медиан (или средние, если вам интересно). Делать мы это будем с помощью функции revalue пакета plyr. Но вот тут я хочу вам фишку раскрыть. Мы получили значения медиан на имеющихся данных. Опрос не закончен и данные будут пополняться, следовательно, описательные статистики будут меняться. Поэтому нам в идеале с формулу revalue надо значения медиан не руками подставлять, а брать кодом из tapply(q1$hr, q1$straty, summary). И вот код, как брать значение медиан
as.vector(med$very_low[3])
[1] 2 
Теперь мы в revalue просто вставляем этот код

 q$hr = revalue(q$размер.hr.службы,  
               c('ни одного' = 0,
                 'от 1 до 3' = as.vector(med$very_low[3]),
                 'от 4 до 10' = as.vector(med$low[3]),
                 'от 11 до 30' = as.vector(med$ave[3]),
                 'более 30' = as.vector(med$high[3])   )   )
И последний штрих: мы эту переменную превращаем в числовую
q$hr = as.numeric(as.character(q$hr))
Далее мы по аналогии проделываем тоже самое в переменной размера компании. И тот график, что в топе - этот график связи между размером компании и размером HR службы получен на исправленных, а не обрезанных данных.

Результат

этот код позволяет нам "не замечать", что у нас есть данные категориального типа. Препроцессинг данных происходит автоматически, с накоплением данных мы обновляем / уточняем наши медианы. Те, кто ежедневно работают с R, знают, сколько времени это экономит.


__________________________________________________________

На этом все, читайте нас в фейсбуке, телеграмме и вконтакте



Комментариев нет:

Отправить комментарий