.

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

Показаны сообщения с ярлыком программа R. Показать все сообщения
Показаны сообщения с ярлыком программа R. Показать все сообщения

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

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



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

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

Проблема

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

понедельник, 14 мая 2018 г.

Обратная трансформация Бокса-Кокса в R



Трансформация Бокса-Кокса позволяет привести данные к нормальному распределению. Проблема возникает в тот момент, когда мы представляем результаты заказчику. Если у нас целевая переменная - рубли, то трансформация превращает рубли в непонятно во что. И после обучения модели, в уже промышленном применения, нам необходима обратная трансформация из Бокса-Кокса в рубли.
Я нигде не нашел полного поста, как это делается (может просто я не там искал), но решил сделать пост с инструкцией по обратной трансформации Бокса - Кокса.

Итак

Необходимый пакет

library(caret)
Создаем данные
set.seed(1)
a = rnorm(100, mean = 80, sd = 40)
b = rnorm(200, mean = 40, sd =20)
c = c(a,b)
df = as.data.frame(c)
df = subset(df, df$c > 0) # удаляем значение менее нуля 
summary(df)
          c           
 Min.   :  0.4259  
 1st Qu.: 33.3343  
 Median : 48.8389  
 Mean   : 56.0041  
 3rd Qu.: 74.5428  
 Max.   :176.0647 
hist(df$c)
Данные создаем так, чтобы они были не нормально распределены. У вас будут свои данные.
Обратная трансформация Бокса-Кокса в R

shapiro.test(df$c)

 Shapiro-Wilk normality test

data:  df$c
W = 0.93822, p-value = 9.752e-10
Результаты теста нас вполне устраивают: данные далеки от нормальных. Теперь сама трансформация
trans = BoxCoxTrans(df$c) # задаем правило трансформации
transc = predict(trans, df$c) # трансофрмируем
hist(transc) # смотрим, что получилось
Обратная трансформация Бокса-Кокса в R

shapiro.test(transc)

 Shapiro-Wilk normality test

data:  transc
W = 0.99504, p-value = 0.465
Трансформация Бокса-Кокса получилась успешной. Что бывает далеко не всегда: очень часто трансформация Бокса-Кокса не превращает распределение в нормальное.

Обратная трансформация Бокса-Бокса

Нас интересует обратная трансформация Бокса-Кокса. Например, мы получили прогноз регрессии по трансформированным данным, нам необходимо получить значения в первоначальной переменной.
Для начала узнаем лямбу (коэффициент трансформации) Бокса-Кокса. Ее можно узнать в правиле трансформации.
trans
Box-Cox Transformation

294 data points used to estimate Lambda

Input data summary:
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
  0.4259  33.3300  48.8400  56.0000  74.5400 176.1000 

Largest/Smallest: 413 
Sample Skewness: 0.956 

Estimated Lambda: 0.4 
Лямбда = 0.4 Формула трансформации Бокса-Кокса такова
y = (x^lmbda - 1) / lmbda
Из этой формулы мы получаем формулу обратной трансформации Бокса-Кокса
x = (y*lmbda + 1)^(1/lmbda)
ВАЖНО; эта формула корректна для лямбды не равной нулю. Если ламбда принимает значение 0, то преобразование Бокса-Кокса представляет логарифмирование, а обратная трансформация Бокса-Кокса, следовательно, экспонирование, т.е.
x = exp(y)
Давайте проверим корректность трансформации для нашего случая
lmbda=0.4
y = transc
x = (y*lmbda + 1)^(1/lmbda)
summary(x)
    Min.  1st Qu.   Median     Mean  3rd Qu.     Max. 
  0.4259  33.3300  48.8400  56.0000  74.5400 176.1000 
Данные обратной трансформации Бокса-Кокса не идентичны данных первоначального набора данных df$c, но различия в пределах сотых: в оригинальном датасете, например, максимальное значение 176.06, в датасете обратной трансформации Бокса-Кокса 176.1.
Думаю, что нас устроит такая погрешность.



суббота, 31 марта 2018 г.

Индивидуальные факторы успешности: применение пакета LIME для задач регрессии в R



Напомню, что пакет LIME появился в ответ на проблему "черного ящика" машинного обучения: предиктивная модель показывает прогноз (сколько кандидат будет продавать, будет он успешным или нет, насколько у него серьезные риски увольнения или нет), но модель не отвечает на вопрос о том, какое именно качество кандидата "западает". Речь идет о непараметрических моделях, в параметрических есть коэффициенты, поэтому если мы стандартизуем признаки, то можем понимать вес переменных, см. подробнее Интерпретабельность HR-аналитики, пост не про это.
См. также с тему Про деструкторы в отношениях с руководителем. И о том, как правильно их измерять
Итого, LIME позволяет ответить на вопрос про конкретного кандидата, какие качестве его "вытаскивают", какие "западают".
Цель поста - показать, как LIME работает на задачах классификации, а нам бы хотелось использовать LIME для задач регрессии, дожития, кластеризации.....

Ну и так. 

Я показываю решение на основе датасета case1 первого пакета по HR аналитике в R. Как установить, см. Пакет R HR analytics для HR аналитиков. Используем датасет "case1". Понятно, что кейс игрушечный, но достаточный для того, чтобы вы умели применять его на своих данных.

Описание данных

У нас есть информация о 81 сотруднике компании: информация при приеме - уровень IQ, измеряемый с помощью теста, наличие аналогичного опыта на предыдущем месте работы, образование. И спустя время после начала работы мы измеряем уровень продаж.
Задача - на основе данных о кандидате на входе в компанию спрогнозировать продажи.
Поскольку у нас цель поста показать пакет LIME для задачи регрессии, я не буду вникать в особенности задачи прогноза, просто скажу, что у нас есть две значимые переменные для прогноза - IQ и E (наличие релевантного опыта работы).

Решение

Необходимые пакеты

library(lime)
library(HRanalytics)
data("case1")

и отбираем необходимые переменные
df = case1[, c('Продажи', 'IQ', 'E')]
Далее я переменную E - опыт - делаю факторной только для того, чтобы показать, что факторные переменные также работают в модели.
df$E = as.factor(df$E)
И модель. Напоминаю, что я делаю совсем простую модель, поскольку цель в другом.
model = lm(Продажи ~ IQ + E, df)
Переходим к пакету LIME. Первое, что нам нужно, определить тип модели, выясняем его так.
class(model)
[1] "lm"
И создаем тип модели
model_type.lm = function(x, ...) {
    return("regression")
}

Т.е. мы говорим LIME, что мы в типе модели 'lm' будем использовать регрессию.
Следующая формула нужна, чтобы показать, какой тип переменной прогноза желаем используем (числовая в отличие от вероятности для классификации).
predict_model.lm = function(x, newdata, type, ...) {
   pred = predict(x, newdata, type ='response')
    return(as.data.frame(pred))
  }
Собственно ради двух вышеуказанных форму и нужен был пост:). Но поскольку я в интернете не встретил полного описания, то сделал сам.
Далее мы тренируем эхплейнер - то, что в LIME отвечает за индивидуальные прогнозы
explainer = lime(df[, c( 'IQ', 'E')], model)
Обратите внимание, я указываю эксплейнеру конкретные переменные датасета. Задаем новые данные - я показываю двух новых кандидатов.
newd = data.frame(IQ=c(99, 37),  E=c('1', '0'))
Как видите, у одного высокий интеллект и наличие опыта работы, у другого низкий интеллект и отсутствие опыта работы. И запускаем эхплейнер на новых данных.
explanation = explain(newd, explainer, n_features = 2 )
Думаю, что с помощью ?explain вы сможете прочитать, что здесь что обозначает. Получаем вот такой вывод
head(explanation)
model_type case model_r2 model_intercept model_prediction feature feature_value feature_weight   feature_desc
1 regression    1 0.276435        79.85067         93.79742      IQ            99       5.499671 97 < IQ <= 102
2 regression    1 0.276435        79.85067         93.79742       E             2       8.447084          E = 1
3 regression    2 0.726847        92.15528         70.59510      IQ            37     -13.919076       IQ <= 91
4 regression    2 0.726847        92.15528         70.59510       E             1      -7.641104          E = 0
   data prediction
1 99, 2   93.56856
2 99, 2   93.56856
3 37, 1   30.02060
4 37, 1   30.02060
И самое вкусное, что надо показывать Заказчику
plot_features(explanation, ncol = 1)

Картинка

Здесь интуитивно понятная картинка:

  • каждая диаграмма для каждого кандидата;
  • переменные по каждому кандидату (попутно замечу, что высота столбика говорит о весе фактора);
  • зеленый цвет означает, что качество кандидата позволяет ему показывать более высокие результаты, красное - это наоборот - "западение".




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

воскресенье, 25 марта 2018 г.

Анализ коммуникаций коллектива в рабочем чате Telegram




Вдохновившись переводами статей на тему Organizational Network Analysis и постом Эдуарда Бабушкина про работукоманды, я решила попробовать провести организационный  сетевой анализ в R на реальных данных о коммуникации коллектива.

Поскольку мессенджеры нынче наше всё, источником информации стала переписка в рабочем чате Telegram одного профессионального коллектива. Мессенджер является официальным корпоративным средством связи компании, чат используется как для решения рабочих вопросов (около 70% сообщений), так и внерабочих (например, совместно заказать пиццу). В выборку не включались информационные сообщения «для всех» (учитывались только ответные сообщения на них).

Про извлечение этих данных писать особо нечего – в этом деле либо мозги и знание методов парсинга данных из мессенджеров, либо железная… точка опоры :) Я пошла по второму пути – вручную выписала информацию о переписке за 2 месяца. Зато теперь есть понимание возможных сложностей: было бы интересно посмотреть, как  при парсинге решается проблема с определением направления сообщения (кому писалось), или проблема с участниками, которые любят единый по смыслу месседж разбивать на несколько сообщений…

Итак, первое, что мы можем сделать, это построить общую картину коммуникаций в коллективе

Красиво?... Даже визуально заметно, что лидерами по частоте коммуникаций являются сотрудники 11, 15, 5, 10. Первое, что можно предположить, что это - руководители, и  на их сообщения остальные обязаны (либо просто считают необходимым) отреагировать.  Я отметила руководителей красным цветом, и стало понятно, что это предположение не вполне соответствует действительности. Я также отметила квадратом рядового сотрудника, на которого возложены функции «организатора».

Таким образом, есть еще как минимум два специалиста, которые не являются ни руководителями, ни организаторами, но демонстрируют не меньшую частоту коммуникаций.

Для наглядности, мы можем представить активность коммуникаций, вот так:


Активность: суммарное количество сообщений сотрудника и откликов на его сообщения.

Мы видим явно выбивающихся в лидеры не-руководящих 11 и  5. Может, они просто злостные спамеры и генерят поток ненужных картинок с котиками? Можем разбить показатель активности на исходящий (Out) и входящий поток (In) (в % соотношении):

Сотрудник 11 в равной степени одинаково генерит контент и получает отклики, у номера 5 преобладают исходящие, откликов явно меньше.

Вопрос для размышления: можно ли сделать вывод, что сотрудник 11, конкурирующий по активности (в том числе реакциям коллег),  с руководством – является неформальным лидером?

Также обращают на себя внимание сотрудники с крайне низким уровнем общей активности: 22, 24.

Опять вопрос: можно ли предположить, что эти сотрудники испытывают сложности с коммуникацией и обладают невысоким социальным статусом? (Хотя я бы проверила влияние стажа работы, возможно, это просто новички).

Еще один интересный разрез  - разделение по группам внутри коллектива. Данный конкретный коллектив функционально разделен на несколько отделов. Можно посмотреть, как строятся коммуникации внутри и между отделами:
  


Цветом выделены 4 функциональных отдела: «желтый» – сотрудники 1(руководитель), 2, 9, 23, «розовый» – сотрудники  7(руководитель), 13, 21,   «зеленый» - одинокий сотрудник 8, «бирюзовый» - все остальные.

Можно заметить, что большую часть коммуникаций создают сотрудники «бирюзового» отдела. Остальные слабо вовлечены в общие коммуникации, в основном через  одного участника: «розовый» через  сотрудника  13, «желтый» - через 23. Руководители обоих отделов, видимо, вообще предпочитают другие формы общения (возможно, через личные сообщения или устно). При этом, между собой внутри желтый и розовый отделы также общаются слабо, что убеждает меня в наличии альтернативного канала коммуникаций (отдельный чат).

И вновь вопрос для размышления: может ли эта картина отражать сплоченность всего коллектива, качественно характеризовать межгрупповые отношения? Например, что отделы не очень дружат между собой?

Вот еще несколько описательных характеристик сети, которые могут понять ситуацию в коллективе (вообще, параметров еще множество, я честно беру наиболее понятные для меня, как для новичка в анализе сетей).

Транзитивность (коэффициент кластеризации) - характеристика повышенной вероятности связи между двумя участниками коммуникации, если есть одинаковые связи с другими участниками (друг моего друга – мой друг). Когда коэффициент кластеризации высокий – это означает, что коммуникации чрезвычайно плотно сгруппированы вокруг нескольких участников; когда он низкий – это значит, что связи в графе относительно равномерно распространены среди всех узлов.
[1] 0.473301
На мой взгляд, коэффициент подтверждает картинку, полученную выше – коммуникации сгруппированы вокруг части сотрудников одного отдела, за его пределами плотность заметно падает.

Диаметр - максимальный кратчайший путь между любыми двумя вершинами (между которыми такой путь возможно проложить). Параметр, который показывает величину сети. 4  - много это или мало, и какие выводы из этого можно сделать – я пока не могу предположить, не хватает опыта,  сравнить не с чем (если у вас есть идеи – велком!)
[1] 4

Плотность - вычисляется как нормированное число ребер (отношение наличных связей в сети к возможному максимальному количеству связей в сети с данным количеством вершин). 
[1] 0.548913

Взаимность – думаю, понятно из названия. В нашем случае большинство связей оказываются взаимными. Предполагаю, что это хорошо для коллектива.
[1] 0.660066

Средняя длина пути – аналогично, определение очевидно. Среднее количество точек между двумя вершинами.
[1] 1.853755

На мой неопытный взгляд большинство параметров середина на половинку. Не плохо, но и не идеально.

Итак, главные вопросы к экспертному сообществу (и не к экспертному тоже – даже если вы никогда этим не занимались, давайте в режиме мозгового штурма):
1.         Можно ли использовать такую информацию, как коммуникации в чате Telegram для социометрического анализа, в частности, определения звезд и аутсайдеров, оценки социально-психологического климата или других прикладных hr-целей?
2.         Какие выводы сделали бы вы, глядя на полученную информацию?


понедельник, 5 марта 2018 г.

Азбука R (отзыв о курсе «Анализ данных в R»)


По не очень старой, но, несомненно, доброй традиции этого блога публикую отзыв о курсе «Анализ данных  в R»  на платформе он-лайн курсов stepic.org. Есть также вторая часть “Анализ данных в R. Часть 2”, она у меня в планах, поэтому, отзыв пока про первую часть.
  
Итак, из описания курса узнаем, что: “В рамках данного курса мы подробно разберем все основные этапы анализа данных при помощи R. Слушатели научатся без труда манипулировать данными, используя как стандартные методы R и Rstudio, так и специальные пакеты и библиотеки. Мы выясним, как применять основные методы статистического анализа: t-тест, корреляция, регрессия, дисперсионный и регрессионный анализ и др. Также мы научимся писать собственные функции в R. Особое внимание в курсе будет уделено визуализации получаемых результатов”.

Одно из ключевых достоинств курса - он на русском языке. Для меня, например, как не профи в специализированной английской терминологии, это было важно - не нужно разрывать мозг одновременным пониманием лексики и содержания курса.

Преподаватели - внимание! - выпускники факультета психологии СПбГУ, которые потом стали специализироваться на статистике, программировании и прочих всяких machine learning. Возможно, поэтому, курс очень доступен для восприятия “гуманитариям”, такая своего рода азбука с картинками про R - с нуля, пошагово, зачем эта стрелочка и почему тут эта скобочка. И можно перемотать и пять раз прослушать, если не дошло. Идеально)


Из, собственно, анализа данных, возможно, тут не будет чего-то, чего вы сейчас не делаете, например, в Excel (корреляция, регрессия, дисперсионный анализ и т.д.), но, во-первых, вы увидите, что это может делаться в разы проще и быстрее (с и возможностью многократного повторения последовательности вычислений практически без вашего участия).  Кстати, одна из фишек выполнения контрольных работ - начинает хотеться не только написать работающий код, но и короткий и красивый. Страшно бесит, когда ты потратила три дня на пять строчек кода, и оно вроде бы принято, но можно было решить в две))

Во вторых, курс помогает погрузиться в R, выучить “буквы”, прежде чем браться за серьезные “произведения”. Поэтому, в первую очередь я бы рекомендовала его тем, кто уже решил взяться за R, но не знает, с какой стороны подойти. Ну и перед семинаром "HR-Аналитика в R" тоже неплохо бы пройти, чтобы набить руку на операционных вещах и полностью погрузиться в содержательные.

пятница, 2 февраля 2018 г.

Свои функции в R, оптимизация препроцессинга подготовки данных в R



Я не работаю с макросами в excel - мозгов не хватает, но мне кажется, что то, что я покажу, есть эти самые макросы в R.
В R в подготовке модели очень много места занимают коды препроцессинга, подготовки данных. Меня лично убивают многокилометровые портянки. Понятно, что их не надо писать каждый раз заново, можно из предыдущих кодов вставлять, но сам факт копирования, вставки, потом этот код при каждом повторе кода заново запускать - не комильфо.
Хочу поделиться тем, как можно все это сократить. И сделаю это на примере кейса по текучести персонала используя первый специализированный пакет в R по HR аналитике.

И заодно рекламирую свой семинар по HR-аналитике в R - Семинар-практикум "HR-Аналитика в R", Москва, 23-24 апреля

Задача.

При решении задачи по текучести персонала мы всегда имеем колонки Дата приема и Дата увольнения, а нам надо получить из них переменные "Stag" и "Event". Это достаточно однообразная операция, она занимает на так много места, но тем не менее я у себя оптимизирую эту операцию.

Решение

Загружаем пакет 'HRanalytics'. Как установить пакет см. пост Пакет R HR analytics для HR аналитиков.

library(HRanalytics)
data("survey")
str(survey)
Эти данные - данные нашего исследования факторов текучести персонала (поучаствуйте, ау).
В этом исследовании респонденты описывают одно из своих мест работы от даты приема до даты увольнения. Мы можем построить модель прогноза текучести на основе регрессии Кокса, но сначала нам надо преобразовать дату приема и дату увольнения в стаж и события.
Создаем два скрипта в Rstudio: один основной, на котором мы будем решать задачу, а на второй вынесем формулы препроцессинга, подготовки данных. Этот второй скрипт можно будет впоследствии использовать много раз для решения подобных задач. У меня этот файл называется незамысловато: podgotovka.
В этом аподготовительном скрипте в R я прописываю формулу

stag = function(end, date_report, begin) {
  library(lubridate)
  x = ifelse(is.na(end), 0, 1)
  end = parse_date_time(end, c("dmy", "dmy_HMS")) 
  end[is.na(end)] =  as.Date(date_report, "%d.%m.%Y")  
  
  begin = parse_date_time(begin, c("dmy", "dmy_HMS"))
  y = as.numeric((end-begin)/(30.4375*24*60*60)) 
  
  return(data.frame('event' = x, 'stag'=y))
}
Эта функция позволяет нам создавать переменные стажа и события. Прокомментирую:

  1. на всякий случай я подгружаю пакет lubridate, если забываю подгрузить в основном скрипте
  2. x = ifelse(is.na(end), 0, 1)- это формула создания переменной event
  3. Далее - и вот здесь вам надо быть внимательными- идет формат работы с датами, который зависит от того, в каком формате данные подгружаются. Я здесь предусмотрел два формата (я надеюсь, вы понимаете по формуле).
  4. И в стаже у нас удивительный знаменатель - это от того, что формат даты у нас в секундах, и чтобы получить месяца, я делю на секунды.
  5. И функция возвращает датафрейм из двух переменных

Далее вы можете получить на данных исследования:

st = stag(survey$Дата.увольнения, survey$Отметка.времени, survey$Дата.трудоустройства) 
summary(st)
event             stag         
 Min.   :0.0000   Min.   :-130.037  
 1st Qu.:0.0000   1st Qu.:   5.979  
 Median :1.0000   Median :  19.959  
 Mean   :0.6061   Mean   :  35.370  
 3rd Qu.:1.0000   3rd Qu.:  47.359  
 Max.   :1.0000   Max.   : 591.146  
                  NA's   :80
И сразу получаем первый втык: какого хрена у нас стаж отрицательный? и почему в стаже таки 80 пустых значений? Ну это уже другая задачка.
Вы можете получить переменные так:

survey$stag = stag(survey$Дата.увольнения, survey$Отметка.времени, survey$Дата.трудоустройства)$stag
Переменную 'event' получите сами.
Когда вы будете работать со своими данными, то у вас дата выгрузки будет фиксированной, а не отдельной колонкой, поэтому вы пишите так

stag(q$Дата.увольнения, "20.12.2017", q$Дата.приема)
ВАЖНО: дату используете свою, эта произвольная
Ну т.е. если вам по барабану мой пакет, но у вас есть свои задачи, что вы просто берете эту формулу и работаете с ней.
Я хотел вставить эту формулу в пакет HRanalytics, но откровенно боюсь того, что пойдут баги типа: а если в Дате увольнения пустые значения не Nan, а "" или " "? Наверное, все эти ситуации можно предусмотреть, но я не готов так глубоко залезать.


Проще

Если у вас названия колонок уже давно определены (выгрузка из системы), данные вы выгружаете в одном формате, то можно сделать совсем просто


stag = function(q) {
  
q$event = 1
q$event[is.na(q$Дата.увольнения)] = 0
q$end = q$Дата.увольнения
q$end = dmy(q$end) # dmy это day-month-year
q$end[is.na(q$end)] =  "2017-12-20 UTC" # заполяем датой выгрузки отчета 
q$begin = dmy(q$Дата.приема)
q$stag = as.numeric((q$end-q$begin)/30.4375) 
return(q)}

Здесь вы видите, что уже заточено на конкретные данные. Но просто в том, что вы потом в основном скрипте просто пишите:
df = stag(df)
И у вас добавляются колонки стажа и евента.
ПыСы. Честно говоря, не уверен, что все гладко сделал, поэтому, если заметите ошибки, пишите.


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



воскресенье, 21 января 2018 г.

Нормированная гистограмма в R






Нашел свой старый файл, решил поделиться. Создание нормированной гистограммы в R было делом нетривиальным, хотя сам тип диаграммы очень распространенный. Может быть сейчас уже что-то придумано более удобное, но на тот момент (года два назад) я не видел ничего удобного для создания нормированных гистограмм в R.
Мой код мне самому не кажется идеальным, особенно в части разнесения значений ячеек, поэтому не претендую на идеальность. Буду рад вашим комментариям и исправлениям.
Итак

Нормированная гистограмма в R

# необходимые пакеnы для работы
library("dplyr")
library(ggplot2)
Далее я создам выборку из двух категориальных переменных, в каждой переменной по два уровня фактора. Можно больше, но это уже вопрос тренировки.

a = sample(c("наши", "не наши"), 1000, replace = TRUE)
b = sample(c("русские", "не русские"), 1000, replace = TRUE)
c = as.data.frame(cbind(a,b))
Собственно нормированная диаграмма в R
# делаем таблицу сопряженности
d = table(c$a, c$b)

# получим %, например по строкам
e = prop.table(d, 1)

# получим дата фрейм

tab = data.frame(e)
# дадим новые имена переменным
tab = rename(tab, наши=Var1, русские=Var2, проценты=Freq)

# приукрасим проценты
tab$проценты = round(tab$проценты*100, digits=1)
делаем первый драфт диаграммы

ggplot(tab,aes(x = наши,  y = проценты, fill = русские)) + geom_bar(stat="identity") +
  scale_y_continuous("", breaks=c(0, 25, 50, 75, 100), label=c("0%", "25%", "50%", "75%", "100%")) +
  
  theme(text = element_text(size=30)) +  
  theme(legend.position = "bottom", legend.title = element_blank()) +
  scale_fill_manual(values=c( "purple2", "red2")) +

  geom_text(aes(label=paste(проценты,"%",sep=""),y= проценты), color="white" ,size=15) 
Драфт первый, потому что вы видите, как значения ячеек налеплены. Их надо разнести. Вот здесь я как раз споткнулся: можно написать код для таблицы 2Х2, 3Х2 и т.п.. с тем, чтобы лепить значения ячеек по месту, но я не могу написать код для таблицы nХn. Поэтому просто тупо руками указываю значения координат. Задаю переменную координат
tab$координаты = c(72, 28, 24, 78)
У вас координаты могут быть другими. А далее в geom_text указываю y= координаты вместо y= проценты.

ggplot(tab,aes(x = наши,  y = проценты, fill = русские)) + geom_bar(stat="identity") +
  scale_y_continuous(breaks=c(0, 25, 50, 75, 100), label=c("0%", "25%", "50%", "75%", "100%")) +
   theme(text = element_text(size=30)) +  
  theme(legend.position = "bottom", legend.title = element_blank(),   
axis.title.x=element_blank(), axis.title.y=element_blank()) +
  scale_fill_manual(values=c( "purple2", "red2")) +
    geom_text(aes(label=paste(проценты,"%",sep=""),y= координаты), color="white" ,size=15) 
И получаем нормированную диаграмму в R.
Нормированная гистограмма в R
Наверное, это не очень удобно - разносить руками координаты значений ячеек, но я исхожу из того, что перегруженные уровнями и значениями нормированные диаграммы в R все равно делать никто не будет, они нечитабельны, а несколько строк и уровней разметить можно.

суббота, 13 января 2018 г.

Пакет R HR analytics для HR аналитиков




Создал сегодня пакет в R. Описание в видео и ниже:)
Смею надеяться, что это еще одно маленькое событие Мира HR-аналитики.

Этот пакет содержит данные из сферы управления персоналом для подготовки и тренировки HR-аналитиков. Основной датасет data(survey) содержит данные исследования факторов текучести и эффективности персонала

Опрос действующий, вы можете еще в нем поучаствовать. Респонденты заполняют информацию об одном из своих мест работы: от знакомства с компанией и дня трудоустройства до увольнения из компании. Большой набор переменных позволяет на реальных данных использовать алгоритмы регрессии, классификации, дожития. При этом обращаю ваше внимание, что не все ответы респондентов корректны, поэтому имеет место garbage. Поэтому данные хороши также тем, что позволяют тренировать навыки очистки данных.

Также в пакете есть data(case1), который содержит 81 строку данных продаж сотрудников и их показатели интеллекта, предыдущего опыта работы, образования. Пакет будет обновляться.
Добавлю еще, что эти данные используются мной на семинаре "HR-Аналитика в R", ближайший состоится в Москве, 23-24 апреля 2018

Как получить доступ к данным

install.packages("devtools")
devtools::install_github("edvbb/HRanalytics")
library(HRanalytics)
data(survey)
data(case1)

На Github



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



воскресенье, 15 февраля 2015 г.

Инструмент отсева неэффективных работников на этапе подбора: дерево решения

Решил показать новый для нашего рынка инструмент принятия решения на основе данных кейса Кейс: отсев неэффективных работников на этапе подбора.
Напомню, мы протестировали кандидатов на входе, они в дальнейшем показали определенные результаты, что позволило разделить их на 1 - неэффективных (или тех, кого не стоило бы брать в компанию) и 2) всех остальных или тех, кого можно принимать.
В предыдущем посте я показал возможности логистической регрессии. Мы выявили две шкалы - Sp и Do, которые позволяют отличать неэффективных от всех остальных.
Главный недостаток логистической регрессии - интуитивно непонятные результаты, диаграмму ROC не предъявишь совету директоров. 
Требуется более наглядный инструмент. Таким инструментом является технология Trees - или дерево принятия решения.

Итак, 

Напоминаю, что мы выявили две шкалы, которые значимо различают неэффективных и остальных:
  • Sp
  • Do
(про то, как выявили, что такое значимость различий, читай 
Визуализируем взаимосвязь тестов и показателей эффективности. 

На этой диаграмме
  • шкала X - показатели кандидатов по шкале Sp теста CPI, 
  • шкала Y - данные шкалы Do теста CPI; 
  • зеленые пирамидки - неэффективные работники, 
  • красные точки - работники, качество работы, которое устраивает работодателя.
График сам подсказывает решение, верно? Прям так и просится провести границу по линии 50 Sp. 
Посмотрим, что нам скажет инструмент Trees
Инструмент отсева неэффективных работников на этапе подбора: дерево решения
Обращаю ваше внимание, что это не человек рисует данное дерево, а машинка (программа R или она же Rstudio). Для спецов в области статистики сообщаю, что я здесь не рассматриваю проблемы оверфитинга и т.п., моя задача - показать инструмент. Инструмент нам предлагает следующую инструкцию принятия решения по кандидату:
  1. если показатели кандидата по шкале Sp больше или равно 50, значит берем на работу
  2. если меньше 50, смотрим шкалу Do.
  3. если Do больше или равно 54, берем кандидата, если меньше, отклоняем кандидатуру.
Красиво?

вторник, 13 января 2015 г.

Vlookup (ВПР) в Rstudio



Во вчерашнем посте Аналитика в дистанционном обучении (кейс для работы) основная идея аналитики - посмотреть, какие факторы влияют на оценку курса обучаемым.
Однако в самой оценке курса могут быть проблемы: кто-то подходит серьезно, ставя оценки взвешенно, кто-то "лепит" подряд "пятерки", кто-то всегда "троечки".
В нашем кейсе (прикрепленные данные) 36 000 строк - записей о прохождении курсов и 4 900 юзеров или работников компании, т.е. на каждого работника примерно 7 курсов.
на самом деле статистика такая
  Min. 1st Qu.  Median    Mean 3rd Qu.    Max.
  1.000   2.000   5.000   6.838  10.000  39.000
a = table(r$ID)
b = as.data.frame(a)
summary(b$Freq)

суббота, 20 декабря 2014 г.

Как в Boxplot в R, Rstudio избавиться от ненужных факторов



Представьте такую задачу: вам нужно построить boxplot в Rstudio для фактора "а" для набора данных
   q p
1   1 a
2   2 b
3   3 a
4   4 b
5   5 a
6   6 b
7   7 a
8   8 b
9   9 a
10 10 b

Стандартный вариант
boxplot(q ~ p, data = h)
Как в Boxplot в R, Rstudio избавиться от ненужных факторов
Но нам надо избавиться от правого "ящика"
Мы делаем так
j = subset(h, p == "a")
boxplot(q ~ p, data = j)
Как в Boxplot в R, Rstudio избавиться от ненужных факторов
И нас, вероятно, не устроит такой вариант: ось X показывает наличие пустого фактора. Если проверить данные, str(j), то увидим присутствие этого фактора - "b".
В данном конкретном случае можно обойтись простым решением
boxplot(q, data = j)
но чаще мы выделяем не один, а несколько факторов, тогда такое решение не прокатит.
Среди вариантов решения:

  1. переменную перекодировать в тип переменной numeric -  для количественной переменной Rstudio этот глюк исчезает
  2. сохранить subset на компе как txt или csv файл, потом загрузить снова, R воспринимает как новый файл 
  3. посоветуете свой вариант? я подозреваю, что есть более простое решение
  4. либо вопользоваться формулой

boxplot(q ~ droplevels(p), data=subset(h, p %in% c('a'),
                                       drop=TRUE))

Как в Boxplot в R, Rstudio избавиться от ненужных факторов

читаем: The function droplevels is used to drop unused levels from a factor or, more commonly, from factors in a data frame.
надеюсь, было полезно

P.S.

уже после публикации мне подсказали более простое решение
boxplot(q ~ as.character(p), data = subset(h, p == c("a", "b")))
в данном случае мы переменную из категориальной / номинативной перекодируем в текстовую, а данный тип переменных позволяет исключать ненужные значения переменной

воскресенье, 2 ноября 2014 г.

Как быстро создавать страты в R (управляем переменными исследования)

Когда то написал пост Как быстро создавать страты (управляем переменными исследования). Этот пост был про то, как метрическую переменную перевести в номинативную или, по другому: задать диапазоны метрической переменной.
В указанном мной посте нужно было переменную возраст (метрическую) разбить на страты / диапазоны:
  • до 25 лет;
  • 25-34 года;
  • 35-44 года;
  • старше 45 лет.
В Excel это делается с помощью функции ВПР, в программе R, Rstudio это решается функцией cut
Для нашего примера команда выглядела бы так
Как быстро создавать страты в R (управляем переменными исследования)

где br - точки, которые задают диапазоны, labels - обозначения диапазонов
я крайними точками указал возраст 0 и 100 лет, это потому, что я не знал минимальный и максимальный возраст. Можно задать более точно, узнав минимальный и максимальный возрасты в выборке через функции min и max

среда, 10 сентября 2014 г.

Преобразование переменной для получения нормального распределения

Пост скорее для себя.
Одна из основных проблем использования линейной регрессии - ненормальной распределения переменных. Выбросы сильно искажают картину. Для некоторых случаев можно пренебречь ими: ну, например, отбросить члена КПСС с дореволюционным стажем из выборки. К сожалению, так получается не всегда, поэтому мы можем преобразовать переменную для того, чтобы получаемые данные подчинялись закону нормального распределения.
У нас есть в ассортимента два наиболее распространенных снаряда:

  • корень квадратный
  • логарифмирование

Корень квадратный мне не нравится: он не меняет характер распределения, а только сужает асимметрию до адекватных размеров, и мы закрываем глаза на выбросы, которые как бы уже и не выбросы
логарифмирование меняет характер распределения. Я сегодня сделал логарифмирование в программе R, вот собственно и хочу похвастаться
Исходные данные
Преобразование переменной для получения нормального распределения

После логарифмирования
Преобразование переменной для получения нормального распределения

Чувствуется разница?
И собственно все элементарно
i = log10(Y$переменная)
l = cbind(Y, i)
Для аналитиков: я не претендую на что-то гениальное. ничуть. Это пост баловство, иногда хочется поиграться с диаграммками. 

воскресенье, 8 июня 2014 г.

Подготовка данных к анализу в R

Выкладываю сам для себя полезную ссылку на подготовку данных к анализу в R
pre-processing
данные команды содержатся в пакете caret и содержат создание фиктивных переменных, выявление мультиколлинеарности, импутацию, центрацию и т.п..

вторник, 18 марта 2014 г.

Наглядная статистика. Используем R!

Анонс книги Наглядная статистика. Используем R!
Новинка от издательства «ДМК Пресс»
Рекомендую всем, кто занимается или собирается заниматься аналитикой. Сам я работаю в программе R, поэтому рекомендую как пользователь. Напомню, что в Мире программа R считается самой популярной программой анализа данных. На русском языке книг и литературы по программе R мало, эта книга одна из малого числа. Также рекомендую книгу по программе R того же издательства R в действии. Анализ и визуализация данных на языке R.
Наглядная статистика. Используем R!

Наглядная статистика. Используем R!

Освойте статистическую среду R, которая принадлежит к числу наиболее динамически развивающихся про-грамм в своем классе!
Освоив R, Вы сможете:.

  • полностью автоматизировать свою работу;
  • запускать статистическую обработку прямо из текста документа;
  • получать графики высокого качества и сохранять их в переносимых графических форматах;
  • в любой момент повторить Ваш анализ;
  • использовать сотни «библиотек»-плагинов, разработанных для R;
  • разрабатывать собственные программы анализа дан-ных: от коротких «макросов» до полноценных пакетов, реализующих новейшие алгоритмы.

Если вам необходима статистическая обработка данных для курсовой, диплома, статьи или диссертации; вы хотите лучше понимать результаты тех статистических методов, которые применяете; вы устали от того, что программы анализа данных не способны выполнить нестандартные задачи; вам необходимо перегруппировать ваши данные, но жаль тратить на это часы ручного труда; вам нужно освоить самые современные методы, еще не нашедшие отражения в большинстве статистических пакетов, то эта книга – для вас!
Изложение построено на базе самого современного программного обеспечения – статистической среды R, которая принадлежит к числу наиболее динамически развивающихся программ в своем классе.
Заказать на OZON>>
Издательство «ДМК Пресс»
тел.: (495) 743-22-39
e-mail: dmkpress@gmail.com
internet-магазин: www.дмк.рф
Оптовая торговля: ООО «АЛЬЯНС БУКС»
115487, г. Москва, 2-й Нагатинский пр., д.6А
тел.: (499)725-54-09 e-mail: books@alians-kniga.ru

вторник, 25 февраля 2014 г.

Выбор контрольной группы в программе R при использовании категориальных переменных в регрессионном анализе

При использовании категориальных переменных в регрессионном анализе исследователю бывает важно задать контрольную группу самостоятельно.
Пост - инструментальная подсказка для тех, кто пользуется R. В качестве кейса беру результаты нашего опроса по исследованию факторов текучести персонала (поучаствуйте заодно). В качестве независимой категориальной переменной я беру источники трафика подбора персонала (через какие каналы кандидаты узнали о вакансии).
Знакомые
friend
Социальные сети
 sm
Джоб сайты
jobsites
Объявление в газете
paper
Раздел Вакансии компании (карьерный портал)
cariersite
Работодатель сам вышел на Вас
direct
Вы обратились непосредственно в саму компанию (отдел кадров и т.п.)
self_direct
Кадровое агентство
KA
Центр занятости
Center_job
другое
etc
В R по умолчанию контрольная группа задается первой в алфавитном порядке, т.е. если у вас "арбузы", "апельсины", "мандарины", то по умолчанию контрольной группой будет "апельсины".

воскресенье, 8 декабря 2013 г.

Statistics One


Не считая финальной контрольной, можно сказать, что мой первый курс на coursera - Statistics One - закончился. По результатам первой недели курса я писал отзыв - MOOC - опыт нового формата обучения. В данном посте хочу поделиться мыслями о курсе Statistics One и, в целом, форме обучения MOOC (massive open online course).

Statistics One

Содержательно, этот курс - фактически курс нашей матстатистики для студентов психологов (в приложении даю программу курса).
Курс длился 12 недель, каждая неделя включала видеолекции, лабораторную работу и задание, необходимое к выполнению. К услугам участников был учебный форум - форум очень живой, что делало выполнение домашних заданий очень легким. Совет от участников можно было получить всегда. Повторюсь, что видеолекции имели субтитры, поэтому можно браться за курс со слабым знанием английского. К концу курса английский подтягиваешь.

понедельник, 4 ноября 2013 г.

Основы управления данными

Цитирую раздел книги R в действии. Анализ и визуализация данных на языке R. Этот текст на коротком примере показывает, что такое управление данными. Сам пример построен на данных, которые относятся непосредственно к HR
И тем, кто желает стать профессионалом в сфере анализа данных, рекомендую эту книгу
Итак, 

Основы управления данными

Одна из задач, которую я решаю по долгу службы, – это как мужчины и женщины различаются по стилю руководства организациями.
Обычные вопросы могут быть следующими:
  • различаются ли мужчины и женщины на руководящих должностях по степени лояльности к вышестоящему начальству?
  • зависит ли это от страны, или выявленные гендерные (половые) различия носят универсальный характер?
Один из способов ответить на эти вопросы – взять начальников из разных стран и ранжировать подчиненных им менеджеров по степени лояльности, используя вопросы вроде этого:
этот менеджер спрашивает мое мнение перед принятием кадровых решений.
  1. абсолютно не согласен;
  2. не согласен;
  3. бывает по-разному;
  4. согласен;
  5. полностью согласен.
В результате можно получить данные вроде тех, что представлены в табл. 4.1. Каждая строка – это оценка, которую дал менеджеру его или ее начальник.

воскресенье, 27 октября 2013 г.

И все-таки: какой город самый HR-ый в России?

Пост про то, что сами вычисления в исследованиях занимают крайне мало место в сравнении с поиском данных. И это как не смешно, не только российская специфика. Если вы все – таки купите или попросите у меня почитать книгу MoneyBall. Как математика изменила самую популярную спортивную лигу в мире, то увидите, что в истоках феноменального результата лежал не успех гения выскочки, а долгая работа целой прослойки людей по созданию необходимой базы цифр. И также было непонимание специалистов, и сопротивление. Но если мы с вами захотим свернуть планету под названием HR на нужную нам траекторию, то в первую очередь задача не в построении «правильного» уравнения, а в постановке сбора статистик, а это задача менеджерская, а не исследовательская. Хотя изначально, безусловно, нужно хотя бы в общих чертах понимать, что ищем. И путь к логическому завершению в бейсболе составил больше 20 лет. Я надеюсь, что мне не придется столько долго ждать решений в HR сфере. Хотел бы пафосно назвать пост: хронология BigData HR в России.

Возвращаясь к теме поста

Помните мой пост HR-рейтинг городов России? Там Краснодар занял первое место в рейтинге городов России. Тему развил в посте Кейс по измерению HR-активности. Показал на диаграмме три города: Краснодар, Екатеринбург и Ханты-Мансийск, которые явно выбивались из тренда.