df <- read.csv("data_5.csv", sep = ";")
#удалим пустые строки
df <- subset(df, EXT1 != "NULL")
#переведем все значения в числовые
df[] <- lapply(df, function(x) as.numeric(x))
library(reshape2)
library(ggplot2)
create_correlation_heatmap <- function(df, scale_name) {
scale_questions <- df[, grepl(scale_name, names(df))]
cor_matrix <- cor(scale_questions)
melted_cor_matrix <- melt(cor_matrix)
ggplot(data = melted_cor_matrix, aes(x = Var1, y = Var2, fill = value)) +
geom_tile() +
scale_fill_gradient2(low = "blue", high = "red", mid = "white",
midpoint = 0, limit = c(-1,1), space = "Lab",
name="Корреляция") +
theme_minimal() +
theme(axis.text.x = element_text(angle = 45, hjust = 1)) +
labs(x = "", y = "", title = paste("Корреляции вопросов", scale_name))
}
Создаём тепловую карту корреляций для шкалы “Экстраверсия”:
create_correlation_heatmap(df, "EXT")
Инвертируем вопросы 2, 4, 6, 8, 10 для шкалы “Экстраверсия”.
create_correlation_heatmap(df, "EST")
Инвертируем вопросы 2, 4 для шкалы “Эмоциональная стабильность”.
create_correlation_heatmap(df, "AGR")
Инвертируем вопросы 1, 3, 5, 7 для шкалы “Доброжелательность”.
create_correlation_heatmap(df, "CSN")
Инвертируем вопросы 2, 4, 6, 8 для шкалы “Добросовестность”.
create_correlation_heatmap(df, "OPN")
Инвертируем вопросы 2, 4, 6 для шкалы “Открытость к опыту”.
invert_questions <- list(
EXT = c(2, 4, 6, 8, 10),
EST = c(2, 4),
AGR = c(1, 3, 5, 7),
CSN = c(2, 4, 6, 8),
OPN = c(2, 4, 6)
)
for (scale in names(invert_questions)) {
for (q in invert_questions[[scale]]) {
question_name <- paste(scale, q, sep = "")
df[[question_name]] <- 5 - df[[question_name]]
}
}
scales_questions <- list(
EXT = grep("EXT", names(df), value = TRUE),
AGR = grep("AGR", names(df), value = TRUE),
CSN = grep("CSN", names(df), value = TRUE),
EST = grep("EST", names(df), value = TRUE),
OPN = grep("OPN", names(df), value = TRUE)
)
means <- sapply(scales_questions, function(questions) {
rowMeans(df[, questions], na.rm = TRUE)
})
means_df <- as.data.frame(means)
head(means_df)
## EXT AGR CSN EST OPN
## 1 1.9 3.1 3.2 2.5 4.0
## 2 2.1 3.0 2.7 3.3 2.1
## 3 3.2 2.8 3.2 2.1 3.0
## 4 2.3 2.5 3.3 2.4 3.0
## 5 3.3 3.8 1.7 3.1 4.3
## 6 3.9 3.7 2.4 2.6 3.7
library(factoextra)
## Welcome! Want to learn more? See two factoextra-related books at https://goo.gl/ve3WBa
pca_result <- prcomp(means_df, scale. = TRUE)
pca_data <- data.frame(PC1 = pca_result$x[,1], PC2 = pca_result$x[,2])
ggplot(pca_data, aes(x = PC1, y = PC2)) +
geom_point() +
theme_classic() +
labs(title = "PCA",
x = "Первая главная компонента",
y = "Вторая главная компонента")
Мне кажется, что кластеры выделить нельзя потому что получился такой круг.
Проверим с помощью графика каменистой осыпи:
wss <- sapply(1:10, function(k){kmeans(means_df, k, nstart = 10)$tot.withinss})
k <- 1:10
ggplot(data.frame(k, wss), aes(x = k, y = wss)) +
geom_line() +
geom_point() +
scale_x_continuous(breaks = 1:10) +
theme_classic()
По графику локтя тоже не видно сгиба, который означал бы идеальное количество кластеров
ratings <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2022/2022-01-25/ratings.csv')
details <- readr::read_csv('https://raw.githubusercontent.com/rfordatascience/tidytuesday/master/data/2022/2022-01-25/details.csv')
merged_data <- merge(ratings, details, by = "id")
library(corrplot)
## corrplot 0.92 loaded
col <- colorRampPalette(c("red", "white", "blue"))(200)
our_columns <- merged_data[, c("playingtime", "minplayers", "maxplayers", "year", "minage", "average")]
cor_matrix <- cor(our_columns)
corrplot(cor_matrix, method = "circle", col = col, type = "upper", order = "hclust", tl.col="black", tl.srt=45)
На первый взгляд, средний рейтинг отрицательно связан с минимальным количеством игроков, и немного отрицательно - с максимальным количеством игроков. То есть более высокие оценки ставят играм для небольшого количества игроков. Рейтинг умеренно положительно связан с минимальным возрастом игрока, со временем игры и с годом выпуска. Значит, игроки предпочитают более длинные игры, которые вышли недавно и рассчитаны на взрослых пользователей. Максимальное количество игроков немного положительно связано с минимальным, а год выхода не сильно положительно связан с минимальным возрастом игрока.
library(reshape2)
boxplot(our_columns$playingtime, main = "Время игры")
В переменной “время игры” есть один выброс, где значение составляет больше 50000 - удалим его:
our_columns <- our_columns[!(our_columns$playingtime > 50000), ]
boxplot(our_columns$minplayers, main = "Минимальное количество игроков")
boxplot(our_columns$maxplayers, main = "Максимальное количество игроков")
В переменной “максимальное количество игроков” есть два выброса, где значение составляет больше 300 - удалим их:
our_columns <- our_columns[!(our_columns$maxplayers > 300), ]
boxplot(our_columns$year, main = "Год выхода")
В переменной “год выхода” есть два выброса, где значение составляет больше 2100 - удалим их:
our_columns <- our_columns[!(our_columns$year > 2100), ]
boxplot(our_columns$minage, main = "Минимальный возраст игрока")
В переменной “минимальный возраст игрока” есть два выброса, где значение составляет больше 18 - удалим их:
our_columns <- our_columns[!(our_columns$minage > 18), ]
boxplot(our_columns$average, main = "Средний рейтинг", col = "lightcyan")
hist(our_columns$playingtime, main = "Время игры", breaks = 5, col = "skyblue")
Для переменной “время игры” характерно ассиметричное распределение: в основном время игры небольшое, но есть немного игр с большим временем партии
hist(our_columns$minplayers, main = "Минимальное количество игроков", breaks = 10, col = "skyblue")
у переменной “минимальное количество игроков” распределение больше похоже на нормальное, но для него характерен длинный правый хвост - наблюдается правосторонняя ассиметрия
hist(our_columns$maxplayers, main = "Максимальное количество игроков", breaks = 15, col = "skyblue")
Распределение переменной “максимальное количество игроков” не похоже на нормальное: в основном, количество игроков небольшое, но есть игры с очень большим максимальным количеством игроков
hist(our_columns$year, main = "Год выхода", breaks = 30, col = "skyblue")
Распределение переменной “год выхода” не похоже на нормальное: в основном игры вышли в районе 20-21 века, но есть игры, которые вышли очень давно
hist(our_columns$minage, main = "Минимальный возраст игрока", breaks = 30, col = "skyblue")
Распределение переменной “Минимальный возраст игрока” не очень похоже на нормальное, но напоминает его: наверное производители указывают минимальный возраст исходя из справил цензурирования, поэтому определенные возраста встречаются чаще: так, часто встречается возраст 7+, но очень редко - 8+, поэтому нормальное распределение не соблюдается
hist(our_columns$average, main = "Средний рейтинг", breaks = 30, col = "skyblue")
Распределение переменной “Средний рейтинг” напоминает нормальное с центром, немного сдвинутым в правую часть: у большинства игр рейтинг выше, чем 5/10. Так как выборка большая, мы не можем проверить нормальность тестом Шапиро-Уилка, но можем использовать тест Андерсона-Дарлинга:
library(nortest)
ad.test(our_columns$average)
##
## Anderson-Darling normality test
##
## data: our_columns$average
## A = 16.839, p-value < 2.2e-16
P-value < 2.2e-16, значит можем отклонить нулевую гипотезу о нормальности распределения
Так как распределения всех переменных ненормальные, для анализа корреляций будем использовать непараметрические критерии:
cor.test(our_columns$average, our_columns$playingtime, method = "spearman")
## Warning in cor.test.default(our_columns$average, our_columns$playingtime, :
## Cannot compute exact p-value with ties
##
## Spearman's rank correlation rho
##
## data: our_columns$average and our_columns$playingtime
## S = 1.0755e+12, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## 0.3603078
По результатам теста Спирмена можно сказать, что существует умеренная положительная корреляция между средним рейтингом и временем игры на уровне значимости < 2.2e-16. Она составила 0.36
cor.test(our_columns$average, our_columns$minplayers, method = "spearman")
## Warning in cor.test.default(our_columns$average, our_columns$minplayers, :
## Cannot compute exact p-value with ties
##
## Spearman's rank correlation rho
##
## data: our_columns$average and our_columns$minplayers
## S = 2.0589e+12, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## -0.2246103
Между переменными “Средний рейтинг” и “Минимальное количество игроков” существует небольшая отрицательная корреляция, которая составила -0.22 на уровне значимости < 2.2e-16.
cor.test(our_columns$average, our_columns$maxplayers, method = "spearman")
## Warning in cor.test.default(our_columns$average, our_columns$maxplayers, :
## Cannot compute exact p-value with ties
##
## Spearman's rank correlation rho
##
## data: our_columns$average and our_columns$maxplayers
## S = 2.009e+12, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## -0.1949419
Между переменными “Средний рейтинг” и “Максимальное количество игроков” существует небольшая отрицательная корреляция, которая составила -0.22 на уровне значимости < 2.2e-16
cor.test(our_columns$average, our_columns$year, method = "spearman")
## Warning in cor.test.default(our_columns$average, our_columns$year, method =
## "spearman"): Cannot compute exact p-value with ties
##
## Spearman's rank correlation rho
##
## data: our_columns$average and our_columns$year
## S = 9.6268e+11, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## 0.4274025
Между годом выхода игры и средним рейтингом существует умеренная положительная связь, которая составила 0.43 на уровне значимости < 2.2e-16
cor.test(our_columns$average, our_columns$minage, method = "spearman")
## Warning in cor.test.default(our_columns$average, our_columns$minage, method =
## "spearman"): Cannot compute exact p-value with ties
##
## Spearman's rank correlation rho
##
## data: our_columns$average and our_columns$minage
## S = 1.2087e+12, p-value < 2.2e-16
## alternative hypothesis: true rho is not equal to 0
## sample estimates:
## rho
## 0.2810745
Между минимальным возрастом игрока и средним рейтингом игры наблюдается небольшая положительная корреляция. Она составила 0.28 на уровне значимости < 2.2e-16
Результаты статистических тестов частично совпали с начальными предположениями, сделанными на основе тепловой карты корреляций. Только для переменной “год выхода” на тепловой карте наблюдалась совсем небольшая связь со средним рейтингом, а по результатам теста Спирмена она оказалась самой высокой из остальных переменных. Наверное, так получилось, потому что в матрице корреляций как базовый метод указан параметрический критерий Пирсона.
births <- scan("http://robjhyndman.com/tsdldata/data/nybirths.dat")
birthstimeseries <- ts(births, frequency=12, start=c(1946,1))
library(ggplot2)
library(gganimate)
library(zoo)
dates <- seq(as.Date("1946-01-01"), by = "month", length.out = length(birthstimeseries))
births_df <- data.frame(date = dates, births = as.vector(birthstimeseries))
plot <- ggplot(births_df, aes(x = date, y = births)) +
geom_line(color = "coral") +
geom_point(color = "coral4") +
labs(title = 'Количество рождённых в Нью-Йорке') +
scale_x_date(date_breaks = "1 year", date_labels = "%Y") +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1)) +
theme_classic()
#animation <- animate(plot + transition_reveal(Date),
#nframes = 100, fps = 10, width = 400, height = 300, renderer = gifski_renderer())
#save_gif(animation, "births_ny.gif", width = 400, height = 300, fps = 10)
На анимации мы можем увидеть увеличение количества рождений после войны, время “беби-бума”.
births_df$year <- format(births_df$date, "%Y")
births_df$month <- format(births_df$date, "%m")
average_births_by_month <- aggregate(births ~ month, data=births_df, FUN=mean)
ggplot(average_births_by_month, aes(x = as.integer(month), y = births, group = 1)) +
geom_line(color = "coral") +
geom_point(color = "coral4") +
scale_x_continuous(breaks = 1:12) +
labs(title = 'Среднее количество рождённых в месяц', x = "Месяц", y = "Среднее количество рождений") +
theme_classic() +
theme(axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1))
По графику среднего количества рождений для каждого месяца можно увидеть пик рождений летом и осенью, а также небольшой пик в марте и снижение числа рождений в конце осени и зимой.
В одном из kaggle-ноутбуков девушка проанализировала рождения в США с 1994 по 2014 год, и обнаружила такойе распределение частоты рождений:
И согласно этим данным, пик рождений
наблюдается летом и в начале осени, а спад происходит в начале осени и
зимой. Хотя эта закономерность не совсем точная, потому что в декабре за
эти годы родилось больше людей, чем в июне.
Спасибо вам большое за задания!🤟🤟