suppressWarnings(library(tidyverse))
## ── Attaching core tidyverse packages ──────────────────────── tidyverse 2.0.0 ──
## ✔ dplyr 1.1.4 ✔ readr 2.1.5
## ✔ forcats 1.0.0 ✔ stringr 1.5.1
## ✔ ggplot2 3.5.1 ✔ tibble 3.2.1
## ✔ lubridate 1.9.4 ✔ tidyr 1.3.1
## ✔ purrr 1.0.2
## ── Conflicts ────────────────────────────────────────── tidyverse_conflicts() ──
## ✖ dplyr::filter() masks stats::filter()
## ✖ dplyr::lag() masks stats::lag()
## ℹ Use the conflicted package (<http://conflicted.r-lib.org/>) to force all conflicts to become errors
library(lubridate)
library(dplyr)
library(skimr)
## Warning: 程辑包'skimr'是用R版本4.3.3 来建造的
df <- read.csv("./nobel_winners.csv")
df <- df %>%
set_names(c('获奖年份','学科','奖项名称','获奖原因','获奖份额',
'获奖人id','获奖类别','姓名','生日','城市','国家','性别',
'组织名称','组织城市','组织国家','死亡日期','死亡城市','死亡国家'))
# 新增一列获奖年龄
df <- df %>% mutate( 获奖年龄=(获奖年份-year(生日)) )
head(df,5)
有没有重复数据
duplicate_rows <- df %>%
group_by(获奖年份,学科,奖项名称,获奖原因,获奖份额,获奖人id,获奖类别,姓名, 生日,性别,国家,死亡日期,死亡城市,死亡国家,获奖年龄) %>%
filter(n() > 1) %>%
ungroup() %>%
arrange(获奖年份,学科,奖项名称,获奖原因,获奖份额,获奖人id,获奖类别,姓名, 生日,性别,国家,死亡日期,死亡城市,死亡国家,获奖年龄)
head(duplicate_rows,5)
有重复数据。因为一个人属于多个组织会产生重复记录
去重,生成df_unique
df_unique <- df %>%
distinct(获奖年份,学科,奖项名称,获奖原因,获奖份额,获奖人id,获奖类别,姓名, 生日,性别,国家,死亡日期,死亡城市,死亡国家,获奖年龄)
# 每一列缺失值数量
df_unique %>% map_df(~ sum(is.na(.)))
# 找出性别的缺失值
df_na_gender <- df_unique %>%
filter(is.na(性别))
skim_results <- skim(df_unique)
print(skim_results)
## ── Data Summary ────────────────────────
## Values
## Name df_unique
## Number of rows 911
## Number of columns 15
## _______________________
## Column type frequency:
## character 12
## numeric 3
## ________________________
## Group variables None
##
## ── Variable type: character ────────────────────────────────────────────────────
## skim_variable n_missing complete_rate min max empty n_unique whitespace
## 1 学科 0 1 5 10 0 6 0
## 2 奖项名称 0 1 26 53 0 579 0
## 3 获奖原因 88 0.903 24 343 0 565 0
## 4 获奖份额 0 1 3 3 0 4 0
## 5 获奖类别 0 1 10 12 0 2 0
## 6 姓名 0 1 6 88 0 904 0
## 7 生日 30 0.967 10 10 0 866 0
## 8 性别 26 0.971 4 6 0 2 0
## 9 国家 26 0.971 4 45 0 121 0
## 10 死亡日期 318 0.651 10 10 0 582 0
## 11 死亡城市 335 0.632 4 30 0 291 0
## 12 死亡国家 329 0.639 5 44 0 50 0
##
## ── Variable type: numeric ──────────────────────────────────────────────────────
## skim_variable n_missing complete_rate mean sd p0 p25 p50 p75 p100
## 1 获奖年份 0 1 1969. 32.8 1901 1946 1975 1997 2016
## 2 获奖人id 0 1 463. 270. 1 228. 457 698. 937
## 3 获奖年龄 30 0.967 59.5 12.4 17 50 60 69 90
## hist
## 1 ▃▃▅▇▇
## 2 ▇▇▇▇▇
## 3 ▁▃▇▇▂
award_cnt <- df_unique %>% count(学科,name='获奖次数')%>%arrange(desc(获奖次数))%>%mutate(学科 = factor(学科, levels = unique(学科)))
# 画图
award_cnt %>% ggplot(aes(x = 学科, y = 获奖次数, fill = 学科)) +
geom_col() +
geom_text(aes(label = 获奖次数), vjust = -0.25) +
labs(title = "诺贝尔奖各学科获奖次数") +
theme(
legend.position = "none",
axis.text.x = element_text(angle = 45, hjust = 1), # 旋转 x 轴标签
plot.title = element_text(hjust = 0.5, face = "bold") # 居中并加粗标题
)
df_unique%>%distinct(获奖类别)
name_unique <- df_unique %>% filter(获奖类别=="Individual") %>% distinct(姓名,获奖人id,生日)
# 新增列 出生世纪
name_unique <- name_unique %>%
mutate(
出生世纪 = case_when(
substr(生日, 1, 2) == "18" ~ "19世纪",
substr(生日, 1, 2) == "19" ~ "20世纪",
substr(生日, 1, 2) == "20" ~ "21世纪",
TRUE ~ "未知"# 处理其他情况,返回NA
)
)
# 新增列 出生年代_10年区间
name_unique <- name_unique %>%
mutate(
出生年代_10年区间 = substr(生日, 1, 3)%>% paste0("0")
)
# 出生世纪统计
name_cnt_sj <- name_unique %>% count(出生世纪,name=("人数"))%>%arrange(desc(人数))
name_cnt_sj
#出生年代_10年区间统计
name_cnt_10y <- name_unique %>% count(出生年代_10年区间,name='人数')%>%arrange(desc(人数)) #%>%mutate(学科 = factor(学科, levels = unique(学科)))
# 画图 出生年代
name_cnt_10y %>% ggplot(aes(x = 出生年代_10年区间, y = 人数, fill = 出生年代_10年区间)) +
geom_col() +
geom_text(aes(label = 人数), vjust = -0.25) +
labs(title = "诺贝尔获奖者出生年代") +
theme(
legend.position = "none",
axis.text.x = element_text(angle = 45, hjust = 1), # 旋转 x 轴标签
plot.title = element_text(hjust = 0.5, face = "bold") # 居中并加粗标题
)
# 新增一列 获奖年代
df_unique <- df_unique %>% mutate( 获奖年代 = substr(获奖年份,1,3) %>% paste0('0') )
# 筛选个人获奖
df_unique_individual = df_unique <- df_unique %>% filter(获奖类别=="Individual")
# 获奖年代分布
award_cnt_10y <- df_unique_individual %>%
count(获奖年代,name='获奖次数')
award_cnt_10y %>% ggplot(aes(x = 获奖年代, y = 获奖次数, fill = 获奖年代)) +
geom_col() +
geom_text(aes(label = 获奖次数), vjust = -0.25) +
labs(title = "诺贝尔奖获奖年代分布_总体") +
theme(
legend.position = "none",
axis.text.x = element_text(angle = 45, hjust = 1), # 旋转 x 轴标签
plot.title = element_text(hjust = 0.5, face = "bold") # 居中并加粗标题
)
# 各学科获奖年代分布
award_cnt_subject_10y <- df_unique_individual %>%
count(获奖年代,学科,name='获奖次数')
ggplot(award_cnt_subject_10y, aes(x = 获奖年代, y = 获奖次数, color = 学科, group = 学科)) +
geom_line(size = 1, alpha = 0.7) + # 添加半透明折线
geom_point(size = 3, alpha = 0.7) + # 添加半透明数据点
geom_text(aes(label = 获奖次数), vjust = -0.25, check_overlap = TRUE) + # 避免标签重叠
scale_color_brewer(palette = "Set1") + # 使用高对比度的颜色调色板
labs(
title = "诺贝尔奖获奖年代分布_分学科",
x = "获奖年代",
y = "获奖次数"
) +
theme(
legend.position = "right", # 将图例放置在右侧
axis.text.x = element_text(angle = 45, hjust = 1), # 旋转 x 轴标签
plot.title = element_text(hjust = 0.5, face = "bold") # 居中并加粗标题
) +
facet_wrap(~ 学科, scales = "free_y",ncol = 1) # 按学科分面绘制,Y轴尺度自由调整
## Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
## ℹ Please use `linewidth` instead.
## This warning is displayed once every 8 hours.
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
## generated.
总体男性占比94.7% ,女性占比5.3%
所有学科中,女性占比最高的是诺贝尔和平奖14%,男性占比最高的是物理,占比99%
# 各个学科的性别比例
gendr_per <- df_unique_individual %>%count(性别, name = "人数") %>%
pivot_wider(
names_from = 性别,
values_from = 人数,
values_fill = list(人数 = 0)
) %>%
rename(女生人数 = Female, 男生人数 = Male) %>%
mutate(
总人数= 女生人数 + 男生人数,
女生人数占比 = 女生人数 / 总人数,
男生人数占比 = 男生人数 / 总人数
)
gendr_per
category_gendr_per <- df_unique_individual %>%
count(学科, 性别, name = "人数") %>%
pivot_wider(
names_from = 性别,
values_from = 人数,
values_fill = list(人数 = 0)
) %>%
rename(女生人数 = Female, 男生人数 = Male) %>%
mutate(
总人数 = 女生人数 + 男生人数,
女生人数占比 = 女生人数 / 总人数,
男生人数占比 = 男生人数 / 总人数
)%>%
arrange(desc(男生人数占比))
category_gendr_per
#平均年龄和获奖数量 用不同的公式聚合计算
age_award_cnt <- df_unique_individual %>% group_by(学科) %>% summarise(
平均年龄 = mean(获奖年龄,na.rm = TRUE),
获奖数量 = n()
)
# 散点图 两个指标为横纵轴,按照颜色分组
ggplot(age_award_cnt, aes(x = 平均年龄, y = 获奖数量, color = 学科)) +
geom_point(size = 3) + # 设置点的大小
labs(title = "各学科的平均年龄与获奖数量",
x = "平均年龄",
y = "获奖数量") +
theme_minimal() + # 使用简洁的主题
scale_color_brewer(palette = "Set1") # 使用颜色调色板
明细如图
最年轻的获奖者是Malala Yousafzai,在17岁获得了诺贝尔和平奖
youngest_awardees <- df_unique_individual %>%
filter(!is.na(获奖年龄)) %>% # 忽略获奖年龄为 NA 的行
group_by(学科) %>%
arrange(学科, 获奖年龄) %>% # 按学科和获奖年龄排序
slice(1) %>% # 取每组的第一条记录
ungroup() %>%
arrange(获奖年龄)
youngest_awardees <- youngest_awardees[, c("姓名", "学科","获奖年龄")]
youngest_awardees
couttyr_unique <- df_unique_individual %>% distinct(国家)
df_china <- df %>% filter(df$国家=='China')
df_china <- df_china[,c("姓名","获奖年份","学科","奖项名称","获奖类别","国家","城市","性别","组织国家","组织城市","组织名称")]
df_china
# 各个学科获奖平均年龄
age_award_gender <- df_unique_individual %>% group_by(性别) %>%
summarise(平均年龄=mean(获奖年龄,na.rm=T),获奖次数=n())
age_award_gender
age_award_gender_subject <- df_unique_individual %>% group_by(学科,性别) %>%
summarise(平均年龄=mean(获奖年龄,na.rm=T),获奖次数=n(),.groups = 'drop' ) %>%
pivot_wider(
names_from = 性别, # 将学科作为列名
values_from = c(平均年龄, 获奖次数), # 将平均年龄和获奖次数作为值
names_sep = "_" # 使用下划线分隔列名
)
age_award_gender_subject <- age_award_gender_subject %>%
mutate(年龄差=(平均年龄_Male-平均年龄_Female))%>%
arrange(desc(年龄差))
age_award_gender_subject
4个人获奖2次
2个人多学科获奖
# 多次获奖人数 获奖次数>=2 4人
# many_award <- df_unique_individual %>% count(姓名,获奖人id,name='获奖次数')%>% arrange(desc(获奖次数))%>%filter(获奖次数>=2)
# many_award
# # 不同学科获奖
# many_award_diff_subject <- df_unique_individual %>% distinct(姓名,获奖人id,学科) %>% count(姓名,获奖人id,name='获奖学科数')%>% arrange(desc(获奖学科数))%>%filter(获奖学科数>=2)
# many_award_diff_subject
award_summary <- df_unique_individual %>%
group_by(姓名, 获奖人id) %>%
summarise(
获奖次数 = n(),
获奖学科数 = n_distinct(学科),
.groups = 'drop'
) %>%
arrange(desc(获奖次数))%>%
filter(获奖次数>=2)
award_summary
df_clean <- df_unique_individual %>%
distinct(姓名,国家,死亡国家)%>%
mutate_at(
vars(
国家, 死亡国家),
~ ifelse(str_detect(., "\\("), str_extract(., "(?<=\\().*?(?=\\))"), .)
) %>%
mutate_at(
vars(国家, 死亡国家),
~ case_when(
. == "scotland" ~ "united kingdom",
. == "northern ireland" ~ "united kingdom",
str_detect(., "czech") ~ "czechia",
str_detect(., "germany") ~ "germany",
TRUE ~ .
)
)
# 死亡地分布
df_clean %>%
count(死亡国家, name = '获奖人数', sort = TRUE) %>%
slice_max(order_by = 获奖人数, n = 10)
# 出生地分布
df_clean %>%
count(国家, name = '获奖人数', sort = TRUE) %>%
rename(出生国家 = 国家) %>%
slice_max(order_by = 获奖人数, n = 10)