НАВИГАЦИЯ
КОНТАКТЫ
  • LinkedIn - White Circle
  • Facebook - White Circle
  • Twitter - White Circle

info@DDM.center

Телефон: +380 67 341 7101

© 2017 DDM.center

Использование R для анализа и визуализации данных

По просьбе коллег подготовил небольшую заметку об использовании возможностей R для анализа отзывов страхователей на сайте strahnadzor.ua

По сути, чтобы получить подобный отчет нам надо будет написать три блока кода:

  1. Собрать данные со страниц сайта

  2. Подготовить таблицы и построить графики

  3. Подготовить текст и построить облака слов

Коротко опишем код по каждому блоку.

 

Сбор данных со страниц сайта

 

Используем библиотеку library('rvest'), чтобы иметь возможность загружать страницы сайта и разбирать их текст.

 

Данные за последний год (мы решили строить отчет за год) находятся на первых 84 страницах сайта. Открываем цикл, чтобы их отобрать

 

for (j in c(1:84)) {

 

Сформируем переменную, которая будет содержать адрес конкретной страницы сайта, которую мы хотим считать.

 

url <- paste0('https://www.strahnadzor.ua/comments/?page=', as.character(j))

 

Получим ее html-код в переменную webpage.

 

webpage <- read_html(url)

 

Далее нам необходимо понять в каком разделе страницы находятся данные с названием компании. Можно установить специализированное приложение, например, SelectorGadget (https://chrome.google.com/webstore/detail/selectorgadget/mhjhnkcfbdhnjickkkdbjoemdmbfginb).  Но можно и просто выполнив команду inspect по правой кнопке мыши в Хроме.

 

В нашем случае название компании содержится в блоке '.feeling_х .date a'', где «х» обозначает оценку страхователя от 0 до 5. Так как нас эта оценка интересует, то откроем цикл

 

for (f in c(0:5)) { в котором будем на странице собирать отзывы в разрезе оценок и сохранять их вместе  с названиями компаний.

 

Формируем строку с нужным блоком оценок

 

feeling_string<-paste0('.feeling_', as.character(f))

 

Формируем текст с названием нужного блока

 

paste(feeling_string, '.date a')

 

Копируем часть html-кода из нужной секции с помощью команды html_nodes(‘страница’,’секция’)

 

ic_data_html <- html_nodes(webpage,paste(feeling_string, '.date a'))

 

Извлекаем текст из html-кода (в нашем случае название компании) командой

 

ic_data <- html_text(ic_data_html)

 

Аналогично извлекаем город страхователя и другие данные

 

# город страхователя

reviewercity_data_html<-html_nodes(webpage,paste(feeling_string,'.date span:nth-child(5)'))

reviewercity_data <- append(reviewercity_data,html_text(reviewercity_data_html))

 

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

 

Так как на странице размещается по 10 отзывов, то откроем цикл

 

for (i in c(1:10)) {

 

и сформируем строку с адресом

 

urlreview <- paste0('https://www.strahnadzor.ua/comments/',reviewnumber_data[(j-1)*10+i])

 

Дальше аналогично. Считываем html-код и получаем нужные нам данные

 

webpagereview <- read_html(urlreview)

reviewtext_data_html<-html_nodes(webpagereview,'h1')

reviewtext_data1 <- html_text(reviewtext_data_html)

reviewtext_data<-append(reviewtext_data,reviewtext_data1[1])

 

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

 

# страховая компания

ic_data<-as.factor(ic_data)

 

После того, как собрали и подготовили все данные, формируем итоговую таблицу (dataframe)

 

review_df<-data.frame(q=qnt, id=reviewnumber_data, InsCompany=ic_data, RDate=reviewdate_data,

RTime=reviewtime_data, Name=reviewername_data, Feeling=feeling_data, FeelingText=feelingtext_data, Hour=hour_data, Minutes=minutes_data, Month=month_data, OMonth=ordered_month_data, CountMessage=countmessage_data, City=CityName, Subject=reviewtext_data, SubjectL=nchar(reviewtext_data, type = "chars"), Text=reviewfulltext_data,                      TextL=nchar(reviewfulltext_data, type = "chars"))

 

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

 

Подготовка таблиц и построение графиков

 

Я не буду здесь копипастить весь код R для подготовки данных и графиков. Приведу только несколько примеров.

 

Так как нам надо будет строить графики, где фигурируют ТОП-10 или ТОП-20 компаний, то заготовим табличку (текстовый вектор) с перечнем компаний с наибольшим количеством отзывов.

Считаем количество отзывов в разрезе СК. Сделать это можно многими способами, например так

 

Qnt_df<-aggregate(q ~ InsCompany, data = review_df, sum)

 

Сортируем по количеству отзывов

 

TopQnt<-Qnt_df[order(Qnt_df$q,decreasing = TRUE),]

 

Отбираем первые 10 записей. Они и будут ТОП-10 СК

 

TopQnt<-head(TopQnt,n=10)

 

Строим текстовый вектор из названий ТОП-10 СК

 

TopInsCompany<-TopQnt$InsCompany

 

Рассмотрим пример с построением графика распределения количества отзывов по времени суток

Чтобы его построить нам необходима таблица в которой бы содержались данные о количестве отзывов с оценками в разрезе времени суток. Создадим ее одной строчкой кода

 

HourFeeling_df<-aggregate(q~Hour+FeelingText, data= review_df, sum), где

review_df – исходная таблица со всеми данными

 

FeelingText – оценки страхователя в текстовом виде

  • '1. Автор восхищен'

  • '2. Автор доволен'

  • '3. Автор спокоен'

  • '4. Автор волнуется'

  • '5. Автор зол'

  • '6. Нет оценки'

Hour – час суток, когда был оставлен отзыв

 

Перейдем к построению графиков.

 

Будем использовать известную библиотеку ggplot2. О ней есть много информации в сети Интернет, так что не буду описывать все ее возможности.

 

library('ggplot2')

 

Разберем основные параметры кода для построения графика, который сохраним в переменную «p».

 

p <- ggplot(HourFeeling_df, aes(x = Hour, y = q, fill = FeelingText)) +

 

HourFeeling_df – таблица с данными, которую мы сформировали ранее одной строчкой кода. На этих данных и будет основан график.

 

x = Hour – по оси х будет откладываться время суток (часы)

y = q – по оси y будет откладываться количество отзывов

fill = FeelingText – для заполнения графика возьмем данные оценки страхователя

Таким образом мы сформировали основу для графика – базовый слой.

 

Сформируем теперь слой с графиком.

 

geom_bar(…, position = "stack", …) +

 

geom_bar – формирует столбчатую диаграмму

position = "stack" – означает, что категориальные данные с оценкой страхователя (FeelingText)надо расположить в столбик.

 

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

то просто меняем это параметр на «fill»  geom_bar(…, position = " fill ", …) +

и получаем нужное.

 

Теперь «раскрасим» наш график. Для этого воспользуемся командой

 

scale_fill_brewer('',palette = "RdYlGn", direction = -1)+

 

которая означает, что для «раскраски» данных надо взять палитру "RdYlGn" из пакета ‘RColorBrewer’ и отображать ее в обратном порядке direction = -1

 

Мы выбрали именно такую палитру, так как данные у нас отображают оценку по шкале от хороших к плохим и данных у нас 6 категорий.

 

Детально палитру можно посмотреть по ссылке http://colorbrewer2.org/#type=diverging&scheme=RdYlGn&n=6

 

Если бы мы выполнили описанный код, то получили бы такой вот график

Но параметр времени «Hour» цикличен и нам показалось, что более интересно и наглядно его можно отобразить на «циферблате». Поэтому перейдем к другой системе координат командой

 

coord_polar(start = 0) +

 

где start = 0 указывает на начальное смещение в радианах от стартовой точки – 12 часов

Дальнейший код связан с «оформительством» и мало интересен

 

Сохраняем рисунок на диск командой

 

ggsave('HourFeeling_Q1.png', p, width = 7, height = 7,  dpi=300)

 

Если будет интересен код любого другого графика из статьи «О чем говорят страхователи…», то задавайте вопрос на facebook.com/DDM.center.ua/ или в комментариях под статьей в блоге https://www.ddm.center/blog

 

Подготовка текста и построение облака слов

 

Ранее в статье «О чем говорят в Игре Престолов» я уже описывал код R для получения облака слов. Чтобы не повторяться, здесь опишу только некоторые отличия.

 

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

 

Для начала сгруппируем оценки в два вектора

 

PositiveVector<-c('1. Автор восхищен', '2. Автор доволен', '3. Автор спокоен')

NegativeVector<-c('4. Автор волнуется', '5. Автор зол', '6. Нет оценки')

 

Из нашей общей таблицы сформируем два текстовых блока, отбирая оценки, которые входят в первый и во второй векторы

 

PositiveFeelingFullText_df<-filter(insur_df, FeelingText %in% PositiveVector)

NegativeFeelingFullText_df<-filter(insur_df, FeelingText %in% NegativeVector)

 

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

 

PositiveDoc<-enc2utf8(tolower(paste(as.vector(PositiveFeelingFullText_df$Text),collapse = " ")))

NegativeDoc<-enc2utf8(tolower(paste(as.vector(NegativeFeelingFullText_df$Text),collapse = " ")))

 

Сформируем текстовый корпус для дальнейшего анализа, указав источником таблицу данных (data.frame)

 

dv<-c(PositiveDoc,NegativeDoc)

docs <- data.frame(docs = dv, row.names=c('Positive','Negative'))

 

Эти манипуляции нам нужны, чтобы построить сравнительное облако слов по двум документам с положительными оценками, и с отрицательными оценками.

 

ds <- DataframeSource(docs)

articles<-Corpus(ds,readerControl = list(reader = readPlain,  language = "ru",load = T))

 

Дальше стандартная очистка данных и подготовка матрицы для построение облака слов.

 

tdm <- TermDocumentMatrix(articles,control = list(tokenize=scan_tokenizer))

m <- as.matrix(tdm)

v <- sort(rowSums(m),decreasing=TRUE)

d <- data.frame(word = names(v),freq=v)

 

Ну и, собственно, облако

 

wordcloud2(d, size = 1,minRotation = pi/6, gridSize =0, maxRotation = -pi/6, rotateRatio = .7,color=pal, backgroundColor="seashell", shape = 'circle', widgetsize=c(900,480))

Также строим сравнительное облако слов

 

colnames(m) <- c("Позитивные оценки","Негативные оценки")

comparison.cloud(m,scale=c(8,1),max.words=1500, random.order=FALSE,rot.per=.1, colors=pal1, use.r.layout=TRUE,title.size=3)

Кому интересно, можно еще такую вот дендрограмму построить

 

my.df <- as.data.frame(inspect(tdm))

my.df.scale <- scale(my.df)

d <- dist(my.df.scale,method="euclidean")

fit <- hclust(d, method="ward.D2")

plot(fit)

Надеюсь, эта статья была интересной и может быть даже полезной

 

Загрузите отчет в pdf-формате

 

Share on Facebook
Share on Twitter
Please reload

Избранные посты

Уйдет или не уйдет?

March 23, 2018

1/4
Please reload

Недавние посты