Анализ активности пользователей Digida: различия между версиями

Материал из Поле цифровой дидактики
Нет описания правки
Метка: ручная отмена
 
(не показано 18 промежуточных версий 2 участников)
Строка 1: Строка 1:
{{Scripting Tutorials
{{AI system used
|Description=Цель: проанализировать активность пользователей Digida за последние 12 месяцев, выявить паттерны использования платформы, определить самых активных участников и сезонные колебания активности.
|AI system used=Perplexity
|Field_of_knowledge=Математика, Информатика, Психология, Образование
|Возрастная категория=13
}}
{{RRecipe
|title=Анализ активности пользователей Digida за последний год
|author=Наталья Захарова
|date={{#time:Y-m-d}}
|description=Анализ активности пользователей платформы Digida за последние 12 месяцев с использованием R
|tags=анализ данных, активность пользователей, Digida, R, статистика
}}
}}
; Исходные данные:
: Все события площадки до 06.04.2026 года - https://raw.githubusercontent.com/patarakin/stat-data/dc76a94554ecd09228ad4e21e95a94e9c422b1b8/datasets/csv/wiki_df_events_digid.csv
: Совместные действия участников  - https://raw.githubusercontent.com/patarakin/stat-data/dc76a94554ecd09228ad4e21e95a94e9c422b1b8/datasets/csv/wiki_df_team_digid.csv
=== Данные в таблице ===
=== График активности 2022 - 2026 ===
[[Файл:DinamycDigida.png|800px]]
=== Код для получения данных и графиков ===
<syntaxhighlight lang="R" line>
# Загрузка необходимых пакетов
library(httr)
library(jsonlite)
library(dplyr)
library(lubridate)
library(tidyr)
library(ggplot2)
library(patchwork)
# Корректный URL API
api_url <- "https://digida.mgpu.ru/api.php"
# Безопасное определение функции (если ещё не существует)
if (!exists("get_mw_data")) {
  get_mw_data <- function(action, params) {
    query_params <- c(action = action, format = "json", params)
    response <- GET(api_url, query = query_params)
   
    # Дополнительная проверка типа ответа
    if (http_type(response) != "application/json") {
      warning("Ответ не в формате JSON")
    }
   
    stop_for_status(response)
    fromJSON(content(response, "text"))
  }
}
# Загрузка данных с обработкой ошибок
data_loaded <- FALSE
tryCatch({
  recent_edits <- get_mw_data("query", list(
    list = "recentchanges",
    rcprop = "user|timestamp|title|comment|type",
    rclimit = "500",
    rcshow = "!bot",
    rcend = format(Sys.Date() - 365, "%Y%m%d%H%M%S")
  ))
 
  users_list <- get_mw_data("query", list(
    list = "allusers",
    aulimit = "500"
  ))
 
  print("Данные успешно загружены!")
  data_loaded <- TRUE
}, error = function(e) {
  print(paste("Ошибка при загрузке данных:", e$message))
})
# Если данные не загружены, прерываем выполнение
if (!data_loaded) {
  stop("Не удалось загрузить данные. Прекращение выполнения.")
}
# Проверка прав на запись в текущей директории
can_write <- file.access(getwd(), mode = 2) == 0
if (!can_write) {
  stop("Нет прав на запись в текущую рабочую директорию. Выберите другую папку.")
}
# Очистка данных
clean_data <- recent_edits$query$recentchanges %>%
  as_tibble() %>%
  mutate(
    timestamp = ymd_hms(timestamp),
    date = as.Date(timestamp),
    day_of_week = wday(timestamp, label = TRUE, abbr = FALSE),
    hour_of_day = hour(timestamp),
    month = month(timestamp, label = TRUE),
    is_edit = type == "edit"
  ) %>%
  filter(date >= Sys.Date() - 365) %>%
  select(user, timestamp, date, day_of_week, hour_of_day, month, title, is_edit)
# Проверка на пустые данные
if (nrow(clean_data) == 0) {
  stop("Очищенные данные пусты. Проверьте параметры запроса к API.")
}
print(paste("Обработано записей:", nrow(clean_data)))
# Агрегация и анализ
user_summary <- clean_data %>%
  group_by(user) %>%
  summarise(
    total_actions = n(),
    edits_count = sum(is_edit),
    unique_pages = n_distinct(title),
    first_action = min(timestamp),
    last_action = max(timestamp)
  ) %>%
  arrange(desc(total_actions))
new_users <- clean_data %>%
  group_by(month) %>%
  summarise(new_users = n_distinct(user))
weekly_activity <- clean_data %>%
  group_by(day_of_week) %>%
  summarise(actions = n())
hourly_activity <- clean_data %>%
  group_by(hour_of_day) %>%
  summarise(actions = n())
top_10_users <- user_summary %>% head(10)
monthly_activity <- clean_data %>%
  group_by(month) %>%
  summarise(total_actions = n(), unique_users = n_distinct(user))
# Построение графиков
p1 <- ggplot(monthly_activity, aes(x = month, y = total_actions)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(title = "Динамика активности пользователей по месяцам",
      x = "Месяц", y = "Количество действий") +
  theme_minimal()
p2 <- ggplot(weekly_activity, aes(x = day_of_week, y = actions)) +
  geom_bar(stat = "identity", fill = "darkgreen") +
  labs(title = "Активность по дням недели",
      x = "День недели", y = "Количество действий") +
  theme_minimal()
p3 <- ggplot(hourly_activity, aes(x = hour_of_day, y = actions)) +
  geom_line(color = "red", size = 1) +
  labs(title = "Активность по часам суток",
      x = "Час дня", y = "Количество действий") +
  scale_x_continuous(breaks = 0:23) +
  theme_minimal()
combined_plot <- (p1 | p2) / p3
# Создаём папку для сохранения графиков
output_dir <- "saved_plots"
if (!dir.exists(output_dir)) {
  dir.create(output_dir)
  print(paste("Создана папка для графиков:", output_dir))
}
# Функция для безопасного сохранения графиков
safe_save_plot <- function(plot_obj, filename, width, height, dpi = 300) {
  if (!inherits(plot_obj, "ggplot")) {
    print(paste("Предупреждение: объект не является графиком ggplot — пропуск сохранения", filename))
    return(FALSE)
  }
 
  full_path <- file.path(output_dir, filename)
 
  tryCatch({
    ggsave(
      filename = full_path,
      plot = plot_obj,
      width = width,
      height = height,
      dpi = dpi,
      device = "png"
    )
    print(paste("График сохранён:", normalizePath(full_path)))
    TRUE
  }, error = function(e) {
    print(paste("Ошибка сохранения", filename, ":", e$message))
    FALSE
  })
}
# Сохранение всех графиков
print("Начинаем сохранение графиков...")
# Объединённый график
safe_save_plot(
  combined_plot,
  "activity_analysis_2023_2024.png",
  width = 12,
  height = 8
)
# График по месяцам
safe_save_plot(
  p1,
  "monthly_activity_2023_2024.png",
  width = 8,
  height = 6
)


== Цель исследования ==
# График по дням недели
Анализ пользовательской активности на платформе Digida для выявления:
safe_save_plot(
* паттернов использования платформы;
  p2,
* сезонных колебаний активности;
  "weekly_activity_2023_2024.png",
* ключевых участников сообщества;
  width = 8,
* оптимальных временных слотов для взаимодействия.
  height = 6
)


== Источники данных ==
# График по часам
* API MediaWiki платформы Digida;
safe_save_plot(
* период анализа: последние 12 месяцев;
  p3,
* метрики: регистрации, правки страниц, просмотры.
  "hourly_activity_2023_2024.png",
  width = 8,
  height = 6
)


== Методология ==
# Финальная проверка — список сохранённых файлов
1. Извлечение данных через API MediaWiki.
print("\n---")
2. Очистка и предобработка данных в R.
print("Проверка сохранённых файлов:")
3. Статистический анализ активности.
saved_files <- list.files(output_dir, pattern = ".png", full.names = TRUE)
4. Визуализация результатов.
if (length(saved_files) > 0) {
5. Формулировка выводов и рекомендаций.
  print("Успешно сохранены файлы:")
  print(saved_files)
} else {
  print("Файлы не найдены в папке", output_dir)
}


== Код анализа ==
print("Анализ завершён!")
<syntaxhighlight lang="r">


</syntaxhighlight>
</syntaxhighlight>


== Результаты анализа ==
=== Результаты выполнения кода ===
После успешного выполнения скрипт:
 
1. Загружает данные о действиях пользователей из API за последний год.
 
2. Очищает и структурирует данные.
 
3. Анализирует активность по месяцам, дням недели и часам суток.
 
4. Определяет топ‑10 активных пользователей.
 
5. Строит и сохраняет 4 графика в папке saved_plots.


=== График 1: Общая динамика активности ===
6. Выводит сводную информацию о результатах.
[[Файл:activity_analysis_2023_2024.png|800px|Динамика активности пользователей]]


=== Таблица 1: Топ‑10 активных пользователей ===
[[Файл:Действия пользователей.png|800px]]
{| class="wikitable sortable"
[[Файл:Топ-10.png|800px]]
|-
[[Файл:Активность по дням недели.png|800px]]
! № !! Пользователь !! Всего действий !! Правки !! Уникальных страниц !! Период активности
|-
{{#for: user in top_10_users}}
| {{#index}} || {{user$user}} || {{user$total_actions}} || {{user$edits_count}} || {{user$unique_pages}} || {{format(user$first_action, "%d.%m.%Y")}} – {{format(user$last_action, "%d.%m.%Y")}}
|-
{{/for}}
|}


=== Таблица 2: Активность по месяцам ===
=== Объединённый график ===
{| class=“wikitable”
[[Файл:Объединённый график.png| 800px]]
|-
! Месяц !! Всего действий !! Уникальных пользователей
|-
{{#for: month in monthly_activity}}
| {{monthmonth}} || {{monthtotal_actions}} || {{month$unique_users}}
|-
{{/for}}
|}


=== График 4: Топ‑10 пользователей по количеству правок ===
На графике указаны динамика активности пользователей по месяцам, активность по дням недели, активность по часам суток.
<chart type=“bar” width=“800” height=“400”>
----
title: Топ-10 пользователей по количеству правок
[[Категория:BigDataWorks]]
xAxisTitle: Пользователи
[[Категория: RRecipe]]
yAxisTitle: Количество правок
data:
{{#for: user in top_10_users}}
{{useruser}}: {{useredits_count}}
{{/for}}
</chart>

Текущая версия от 10:37, 16 апреля 2026


Исходные данные
Все события площадки до 06.04.2026 года - https://raw.githubusercontent.com/patarakin/stat-data/dc76a94554ecd09228ad4e21e95a94e9c422b1b8/datasets/csv/wiki_df_events_digid.csv
Совместные действия участников - https://raw.githubusercontent.com/patarakin/stat-data/dc76a94554ecd09228ad4e21e95a94e9c422b1b8/datasets/csv/wiki_df_team_digid.csv

Данные в таблице

График активности 2022 - 2026

Код для получения данных и графиков

# Загрузка необходимых пакетов
library(httr)
library(jsonlite)
library(dplyr)
library(lubridate)
library(tidyr)
library(ggplot2)
library(patchwork)

# Корректный URL API
api_url <- "https://digida.mgpu.ru/api.php"

# Безопасное определение функции (если ещё не существует)
if (!exists("get_mw_data")) {
  get_mw_data <- function(action, params) {
    query_params <- c(action = action, format = "json", params)
    response <- GET(api_url, query = query_params)
    
    # Дополнительная проверка типа ответа
    if (http_type(response) != "application/json") {
      warning("Ответ не в формате JSON")
    }
    
    stop_for_status(response)
    fromJSON(content(response, "text"))
  }
}

# Загрузка данных с обработкой ошибок
data_loaded <- FALSE
tryCatch({
  recent_edits <- get_mw_data("query", list(
    list = "recentchanges",
    rcprop = "user|timestamp|title|comment|type",
    rclimit = "500",
    rcshow = "!bot",
    rcend = format(Sys.Date() - 365, "%Y%m%d%H%M%S")
  ))
  
  users_list <- get_mw_data("query", list(
    list = "allusers",
    aulimit = "500"
  ))
  
  print("Данные успешно загружены!")
  data_loaded <- TRUE
}, error = function(e) {
  print(paste("Ошибка при загрузке данных:", e$message))
})

# Если данные не загружены, прерываем выполнение
if (!data_loaded) {
  stop("Не удалось загрузить данные. Прекращение выполнения.")
}

# Проверка прав на запись в текущей директории
can_write <- file.access(getwd(), mode = 2) == 0
if (!can_write) {
  stop("Нет прав на запись в текущую рабочую директорию. Выберите другую папку.")
}

# Очистка данных
clean_data <- recent_edits$query$recentchanges %>%
  as_tibble() %>%
  mutate(
    timestamp = ymd_hms(timestamp),
    date = as.Date(timestamp),
    day_of_week = wday(timestamp, label = TRUE, abbr = FALSE),
    hour_of_day = hour(timestamp),
    month = month(timestamp, label = TRUE),
    is_edit = type == "edit"
  ) %>%
  filter(date >= Sys.Date() - 365) %>%
  select(user, timestamp, date, day_of_week, hour_of_day, month, title, is_edit)

# Проверка на пустые данные
if (nrow(clean_data) == 0) {
  stop("Очищенные данные пусты. Проверьте параметры запроса к API.")
}

print(paste("Обработано записей:", nrow(clean_data)))

# Агрегация и анализ
user_summary <- clean_data %>%
  group_by(user) %>%
  summarise(
    total_actions = n(),
    edits_count = sum(is_edit),
    unique_pages = n_distinct(title),
    first_action = min(timestamp),
    last_action = max(timestamp)
  ) %>%
  arrange(desc(total_actions))

new_users <- clean_data %>%
  group_by(month) %>%
  summarise(new_users = n_distinct(user))

weekly_activity <- clean_data %>%
  group_by(day_of_week) %>%
  summarise(actions = n())

hourly_activity <- clean_data %>%
  group_by(hour_of_day) %>%
  summarise(actions = n())

top_10_users <- user_summary %>% head(10)
monthly_activity <- clean_data %>%
  group_by(month) %>%
  summarise(total_actions = n(), unique_users = n_distinct(user))

# Построение графиков
p1 <- ggplot(monthly_activity, aes(x = month, y = total_actions)) +
  geom_bar(stat = "identity", fill = "steelblue") +
  labs(title = "Динамика активности пользователей по месяцам",
       x = "Месяц", y = "Количество действий") +
  theme_minimal()

p2 <- ggplot(weekly_activity, aes(x = day_of_week, y = actions)) +
  geom_bar(stat = "identity", fill = "darkgreen") +
  labs(title = "Активность по дням недели",
       x = "День недели", y = "Количество действий") +
  theme_minimal()

p3 <- ggplot(hourly_activity, aes(x = hour_of_day, y = actions)) +
  geom_line(color = "red", size = 1) +
  labs(title = "Активность по часам суток",
       x = "Час дня", y = "Количество действий") +
  scale_x_continuous(breaks = 0:23) +
  theme_minimal()

combined_plot <- (p1 | p2) / p3

# Создаём папку для сохранения графиков
output_dir <- "saved_plots"
if (!dir.exists(output_dir)) {
  dir.create(output_dir)
  print(paste("Создана папка для графиков:", output_dir))
}

# Функция для безопасного сохранения графиков
safe_save_plot <- function(plot_obj, filename, width, height, dpi = 300) {
  if (!inherits(plot_obj, "ggplot")) {
    print(paste("Предупреждение: объект не является графиком ggplot — пропуск сохранения", filename))
    return(FALSE)
  }
  
  full_path <- file.path(output_dir, filename)
  
  tryCatch({
    ggsave(
      filename = full_path,
      plot = plot_obj,
      width = width,
      height = height,
      dpi = dpi,
      device = "png"
    )
    print(paste("График сохранён:", normalizePath(full_path)))
    TRUE
  }, error = function(e) {
    print(paste("Ошибка сохранения", filename, ":", e$message))
    FALSE
  })
}

# Сохранение всех графиков
print("Начинаем сохранение графиков...")

# Объединённый график
safe_save_plot(
  combined_plot,
  "activity_analysis_2023_2024.png",
  width = 12,
  height = 8
)

# График по месяцам
safe_save_plot(
  p1,
  "monthly_activity_2023_2024.png",
  width = 8,
  height = 6
)

# График по дням недели
safe_save_plot(
  p2,
  "weekly_activity_2023_2024.png",
  width = 8,
  height = 6
)

# График по часам
safe_save_plot(
  p3,
  "hourly_activity_2023_2024.png",
  width = 8,
  height = 6
)

# Финальная проверка — список сохранённых файлов
print("\n---")
print("Проверка сохранённых файлов:")
saved_files <- list.files(output_dir, pattern = ".png", full.names = TRUE)
if (length(saved_files) > 0) {
  print("Успешно сохранены файлы:")
  print(saved_files)
} else {
  print("Файлы не найдены в папке", output_dir)
}

print("Анализ завершён!")

Результаты выполнения кода

После успешного выполнения скрипт:

1. Загружает данные о действиях пользователей из API за последний год.

2. Очищает и структурирует данные.

3. Анализирует активность по месяцам, дням недели и часам суток.

4. Определяет топ‑10 активных пользователей.

5. Строит и сохраняет 4 графика в папке saved_plots.

6. Выводит сводную информацию о результатах.

Объединённый график

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