Введение

В документе приведен короткий анализ активности пользователей соцсети “Вконтакте”, состоящих в группе Stepik.org. Под активностью понимаются: со стороны участников группы - лайки и репосты записей на стене группы, со стороны администраторов - частота записей.

Предупреждение:

  1. Несмотря на то, что исходный массив данных абсолютно достоверен, ограничение объема документа не позволяет привести полноценную аналитику. Поэтому данный документ следует воспринимать, прежде всего, как демонстрацию усвоенного курса по возможностям markdown документов и визуализации данных с помощью пакетов R.
  2. Каждый раз, говоря о наличии статистически значимой связи между какими-либо переменными, мы будем говорить лишь о наличии связи, но не о причинах и следствии. Например, если активность пользователей падает в выходные дни это может быть связано как с низким качества контекта в группе, так и с тем, что люди проводят меньше времени в соцсетях.

Гипотезы

Основные гипотезы, которые подвергнутся проверке в ходе данного мини-исследования: 1) С течением времени число лайков и репостов растет 2) Количество лайков и репостов прямо пропорциональны друг другу 3) Активность зависит от содержимого записи

Исходные данные

Исходными данными для исследования является массив данных, скаченный с помощью VK Api 1. Скачивание данных происходило с помощью отдельного парсера, написанного не на R, поэтому его описание выходит за рамки данного документа. Данные представлены таблицей в файле формата *.txt. Скачать файл можно по ссылке: https://yadi.sk/i/HhaFP3iSvbJs7. Дата сбора данных: 19.09.2016.

Краткое описание колонок таблицы исходных данных:

  • Code - ИД записи
  • Text - содержимое записи (текст)
  • Date - дата и время записи
  • Attachments - есть ли вложения в записи (картинки, документы)
  • Link - есть ли ссылка в записи
  • Likes - количество лайков
  • Reposts - количество репостов

Анализ

Подготовка данных

Загрузим набор данных:

#подключаем нужные пакеты
require(tidyr)
require(ggplot2)
require(dplyr)
require(stringr)

#не забудьте сменить рабочую директорию!
df <- read.csv("Stepik_data.txt", sep="\t", encoding = "UTF-8", stringsAsFactors = F)

#заменим Да/Нет на TRUE/FALSE
df[df$Attachments=="Да",]$Attachments <- TRUE
df[df$Attachments=="Нет",]$Attachments <- FALSE

#Приведем дату к правильному формату
df$Date <- strptime(df$Date, format="%d.%m.%Y %H:%M:%S")
df$Date <- as.POSIXct(df$Date)

#Числовые показатели приведем к числовому типу
df$Likes <- as.numeric(df$Likes)
df$Reposts <- as.numeric(df$Reposts)

#Добавим время дня для каждой записи (в часах)
df$Time <- (as.numeric(format(df$Date, "%H"))*3600+
                    as.numeric(format(df$Date, "%M"))*60+
                    as.numeric(format(df$Date, "%S")))/3600

#и день недели, в который была опубликована запись
#не забудем при этом привести новую переменную к фактору с правильным порядком уровней
df$WeekDay <- weekdays(df$Date)
df$WeekDay <- factor(df$WeekDay,levels=c("понедельник","вторник","среда",                                                 "четверг","пятница","суббота","воскресенье"))

Общая информация

Посмотрим на общие характеристики нашего набора данных:

Всего записей в массиве: 371. Среднее количество лайков: 36.74. Репостов:7.76.

Зависимость от даты

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

#приведем датафрейм к длинному формату для того, чтобы удобнее было строить график
df_long <-  gather(df[c("Date","Likes","Reposts")],Action,Value, Likes, Reposts)

LikesDatePlot <- function(df){
ggplot(df_long,aes(Date, Value, color=Action))+
        geom_line()+
        geom_smooth( se=F)+
        xlab("Даты (год-месяц)")+
        ylab("Число действий")+
        theme_bw()+
        theme(axis.text.x = element_text(angle=-45))+
        scale_color_manual(name="Тип действия",values=c("lightgreen","blue"),
                                labels=c("Лайки","Репосты"))
}

LikesDatePlot(df_long)

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

#Удаление выбросов
hlimL <- quantile(df$Likes,0.75, na.rm = T)+
        1.5*(quantile(df$Likes,0.75, na.rm = T)-quantile(df$Likes,0.25, na.rm = T))
hlimR <- quantile(df$Reposts,0.75, na.rm = T)+
        1.5*(quantile(df$Reposts,0.75, na.rm = T)-quantile(df$Reposts,0.25, na.rm = T))
df_clear <- filter(df, Likes<=hlimL & Reposts<=hlimR)
df_long <- gather(df_clear[c("Date","Likes","Reposts")],Action,Value, Likes, Reposts)

Теперь график выглядит немного более ровно:

LikesDatePlot(df_long)

corL <- cor.test(df_clear$Likes, as.numeric(df_clear$Date))
corR <- cor.test(df_clear$Reposts, as.numeric(df_clear$Date))

Видно, что количество лайков растет в среднем с течением времени, в то время как количество репостов изменяется значительно меньше. Вероятно, с течением времени растет и число участников группы, что обуславливает и рост лайков. Однако информации о численности группы нет в исходных данных, поэтому однозначно судить об этом нельзя. При этом графики и лайков, и репостов имеют довольно сильный разброс по вертикали: записи с низким количество лайков/репостов встречаются как в 2014 году, так и в 2016. Это говорит о том, что нельзя говорить о сильной связи между датой и активностью пользователей. Это же подтверждают и невысокие коэффициенты корреляции между лайками и датой 0.28(значимый, p-value 0). И особенно между репостами и датой: 0.07 (не значим, , p-value 0.25). Обратите так же внимание на увеличение частоты записей примерно с начала 2016 года.

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

Связь лайков и репостов

ggplot(df_clear,aes(Likes, Reposts))+
        geom_line(color = "lightgreen")+
        xlab("Количество лайков")+
        ylab("Количество репостов")+
        geom_smooth(se=F)+
        theme_bw()

corLR <- cor.test(df_clear$Likes, df_clear$Reposts)

Между собой эти величины связаны более тесно: коэф. корреляции 0.73, p-value 0. Это вполне логично: чем больше репостов, тем больше людей видят запись, а значит и больше лайков.

Как и ожидалось, гипотеза о тесной связе лайков и репостов подтверждена.

Зависимость от дня недели и времени дня

Для начала посмотрим на количество записей по дням недели:

#введем новый датафрейм, сгруппировав старый
df_WD <- df_clear %>% group_by(WeekDay) %>% summarise(LikesMean = mean(Likes),
                                                      RepostsMean = mean(Reposts),
                                                        Posts = n())
#применим тот же прием, что и для графика с датами
df_WD <- gather(df_WD,Action,ActionCount,LikesMean,RepostsMean)

ggplot(df_WD,aes(WeekDay, Posts))+
        geom_bar(stat = "identity", fill = "lightgreen")+
        xlab("Дни недели")+
        ylab("Количество записей")+
        theme_bw()

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

ggplot(df_WD,aes(WeekDay, ActionCount, fill = Action))+
        geom_bar(stat = "identity", position = "dodge")+
        xlab("Дни недели")+
        ylab("Среднее количество действий")+
        scale_fill_manual(name="Тип действия",values=c("lightgreen","blue"),
                           labels=c("Лайки","Репосты"))+
        theme_bw()+
        theme(axis.text.x = element_text(angle = 45, hjust = 1))

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

Тот факт, что администраторы группы предпочитают выкладывать записи в рабочее время, подтверждается и графиком зависимости лайков и репостов от времени суток. Обратите внимание, как много значений сгруппировано в диапазоне от 12 до 17 часов дня:

ggplot(df_clear,aes(Time, Likes))+
        geom_line(color = "lightgreen")+
        xlab("Время дня")+
        ylab("Количество лайков")+
        geom_smooth(se=F)+
        scale_x_continuous(breaks = c(0:24))+
        theme_bw()

ggplot(df_clear,aes(Time, Reposts))+
        geom_line(color = "lightgreen")+
        xlab("Время дня")+
        ylab("Количество репостов")+
        geom_smooth(se=F)+
        scale_x_continuous(breaks = c(0:24))+
        theme_bw()

Содержание записи

И последний признак, по которому мы будем анализировать активность записей - ее содержание. Поскольку объем документа ограничен, рассмотрим только один вариант разделения записей по их содержанию - содержит ли запись ссылку на сайт http://stepik.org или нет.

Ссылка может содержаться как в тексте записи, так и непосредственно в ссылке, прикрепленной к записи:

#добавим новую переменную в датафрейм, указывающую на наличие ссылки на Stepik
df_clear$Stepic <- grepl("stepi(c|k).org", df_clear$Text)|grepl("stepi(c|k).org", df_clear$Link)

#% процент записей, содержащих ссылку
ratio <- round(100*nrow(df_clear[df_clear$Stepic==T,])/nrow(df_clear),2)

#средния значения лайков и репостов для записей, содержащих и не содержащих ссылки на сайт
mLS <- round(mean(df_clear[df_clear$Stepic==T,]$Likes),2)
mLnS <- round(mean(df_clear[df_clear$Stepic==F,]$Likes),2)

mRS <- round(mean(df_clear[df_clear$Stepic==T,]$Reposts),2)
mRnS <-round(mean(df_clear[df_clear$Stepic==F,]$Reposts),2)

Записей, содержащих ссылку на портал 75%.

Среднее число лайков Среднее число репостов
С ссылкой 33.09 4.97
Без ссылки 30.37 3.37

Воспользовавшись непараметрическим критерием Манна-Уитни2, увидим, что различия в среднем количестве лайков незначимы, а вот для репостов - вполне:

Ltest <- wilcox.test(df_clear[df_clear$Stepic==T,]$Likes, df_clear[df_clear$Stepic==F,]$Likes)
Rtest <- wilcox.test(df_clear[df_clear$Stepic==T,]$Reposts, df_clear[df_clear$Stepic==F,]$Reposts)
Значение статистики p-уровень
Лайки 5491.5 0.5528
Репосты 6557.5 0.003

Наша гипотеза о зависимости активности от содержимого записи частично подтвердилась (для репостов).

Выводы

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


  1. Подробное описание Api приведено тут: https://vk.com/dev/main

  2. Применить обычный t-test нельзя, так как величины распределены не нормально. Доказательство этого не приводится в целях экономии места, но в этом можно убедиться с помощью любого теста на нормальность, например, Шапиро-Уилка. Подробнее о непараметрических критериях и их преимуществах рассказывается в курсе “Основы статистики. Часть 2”