欢迎大家参加明晚 8 点的直播课:「R 语言:如何绘制上市公司投资网络图」
最近给大家分享了上市公司子公司数据,里面绘制了一副上市公司的投资网络图:
1999~2023 年上市公司子公司经纬度及其所处的省市区县数据:https://rstata.duanshu.com/#/brief/course/24376370188e4622b124f4a3199e395b
这幅图使用 R 语言绘制。今天我们一起来学习下如何在 R 语言中绘制这样的网络图。
在附件中我准备了三份数据:
-
-
-
前两份数据来源于国泰安数据库,我选择了 2023 年的数据为样本。第三份数据爬取自天眼查,只保留了关键变量。
上市公司对外投资公司列表数据(截止 2023 年 8 月):https://rstata.duanshu.com/#/brief/course/c5a0234d9e9847b1bcbec3d29d2200b6
首先我们使用前两份数据绘制。
加载所需 R 包:
library(tidyverse)
library(tidygraph)
library(ggraph)
读取和处理数据:
haven::read_dta("2023年上市公司子公司数据.dta") -> df1
haven::read_dta("2023年上市公司列表.dta") -> df2
df1 %>%
rename(股票代码 = 证券代码) %>%
left_join(df2) %>%
mutate(投资比例 = if_else(is.na(直接持股),
间接持股, 直接持股)) %>%
select(股票名称 = 股票简称, 被投资公司名称 = 子公司名称,
投资比例) -> df3
df3
#> # A tibble: 114,991 × 3
#> 股票名称 被投资公司名称 投资比例
#>
#> 1 广济药业 武穴长投广济生物医药产业投资基金合伙企业(有限合伙) 50
#> 2 广济药业 广济药业(孟州)有限公司 97.4
#> 3 广济药业 广济药业(济宁)有限公司 90
#> 4 格林美 格林美(郴州)固体废物处理有限公司 100
#> 5 中国人寿 中国人寿-沪发1号股权投资计划 99.2
#> 6 永安期货 浙江中邦实业发展有限公司 100
#> 7 世纪华通 江苏酷动乐创网络科技有限公司 51
#> 8 博士眼镜 江西博士新云程商贸有限公司 60
#> 9 远达环保 重庆远达碳基环保科技有限公司 51
#> 10 谱尼测试 谱尼测试科技(天津)有限公司 100
#> # ℹ 114,981 more rows
去除部分词汇:
df3 %>%
mutate(被投资公司名称 = str_remove_all(被投资公司名称, "有限公司|有限责任公司|股份有限公司")) -> df3a
不过大多数公司的子公司都非常少、绘制所有公司的投资网络图也非常耗时,因此我们值选择子公司数量最多的 20 家公司:
df3a %>%
count(股票名称, sort = T) %>%
slice(1:20) %>%
select(-n) %>%
inner_join(df3a) -> df3b
df3b
#> # A tibble: 9,103 × 3
#> 股票名称 被投资公司名称 投资比例
#>
#> 1 新城控股 上海麦鹏置业 96.9
#> 2 新城控股 天津新城恒瑞房地产开发 99.0
#> 3 新城控股 上海骋崧企业管理 99.2
#> 4 新城控股 上海铭世置业 99.0
#> 5 新城控股 北京新城万隆房地产开发 1
#> 6 新城控股 兴化新城恒昇商业运营管理 99.0
#> 7 新城控股 香港创贤发展 99.0
#> 8 新城控股 南昌恒韵房地产开发 99.1
#> 9 新城控股 合肥新城亿盛房地产 95.8
#> 10 新城控股 武汉新城创置置业 95.2
#> # ℹ 9,093 more rows
转换成 tbl_graph 数据:
as_tbl_graph(df3b) %>%
mutate(size = centrality_degree(mode = 'out')) -> df4
df4
#> # A tbl_graph: 9118 nodes and 9103 edges
#> #
#> # A directed multigraph with 19 components
#> #
#> # Node Data: 9,118 × 2 (active)
#> name size
#>
#> 1 新城控股 1225
#> 2 荣盛发展 806
#> 3 怡亚通 552
#> 4 豫园股份 523
#> 5 华能国际 504
#> 6 爱尔眼科 476
#> 7 海大集团 455
#> 8 中航产融 452
#> 9 欧普康视 438
#> 10 国电电力 428
#> # ℹ 9,108 more rows
#> #
#> # Edge Data: 9,103 × 3
#> from to 投资比例
#>
#> 1 1 21 96.9
#> 2 1 22 99.0
#> 3 1 23 99.2
#> # ℹ 9,100 more rows
然后就可以绘图了:
df4 %>%
ggraph(layout = "kk") +
geom_edge_link(aes(edge_colour = factor(from),
edge_width = 投资比例), show.legend = F,
arrow = grid::arrow(type = "closed", length = unit(0.02, "inches"))) +
geom_node_point(aes(color = name,
size = size), show.legend = F) +
geom_node_text(aes(label = name, size = size, color = name), vjust = 1,
hjust = 1, check_overlap = T,
family = cnfont, show.legend = F) +
scale_edge_width(range = c(0.05, 0.2)) +
scale_size_continuous(range = c(0.2, 1)) +
scale_color_manual(values = sample(paletteer::paletteer_d("ggsci::default_igv", 51), length(df4), replace = T)) +
scale_edge_color_manual(values = sample(paletteer::paletteer_d("ggsci::default_igv", 51), nrow(as.list(df4)$edges), replace = T)) +
theme_graph(background = 'grey20',
base_family = cnfont) -> p1
不过这个图难以体现“网络”关系,我们再试试被投资最多的 20 家子公司对应的上市公司投资网络:
df3a %>%
count(被投资公司名称, sort = T) %>%
slice(1:20) %>%
select(-n) %>%
left_join(df3a) %>%
distinct(股票名称) %>%
left_join(df3a) -> df3c
as_tbl_graph(df3c) %>%
mutate(size = centrality_degree(mode = 'out')) -> df4
df4
#> # A tbl_graph: 1116 nodes and 1255 edges
#> #
#> # A directed acyclic multigraph with 9 components
#> #
#> # Node Data: 1,116 × 2 (active)
#> name size
#>
#> 1 长飞光纤 73
#> 2 博创科技 13
#> 3 长虹美菱 24
#> 4 四川长虹 147
#> 5 中科美菱 2
#> 6 贝特瑞 35
#> 7 中国宝安 222
#> 8 中集集团 57
#> 9 中集车辆 101
#> 10 华润三九 121
#> # ℹ 1,106 more rows
#> #
#> # Edge Data: 1,255 × 3
#> from to 投资比例
#>
#> 1 1 20 100
#> 2 1 21 100
#> 3 1 22 51
#> # ℹ 1,252 more rows
df4 %>%
ggraph(layout = "kk") +
geom_edge_link(aes(edge_colour = factor(from),
edge_width = 投资比例), show.legend = F,
arrow = grid::arrow(type = "closed", length = unit(0.02, "inches"))) +
geom_node_point(aes(color = name,
size = size), show.legend = F) +
geom_node_text(aes(label = name, size = size, color = name), vjust = 1,
hjust = 1, check_overlap = T,
family = cnfont, show.legend = F) +
scale_edge_width(range = c(0.05, 0.2)) +
scale_size_continuous(range = c(0.2, 1)) +
scale_color_manual(values = sample(paletteer::paletteer_d("ggsci::default_igv", 51), length(df4), replace = T)) +
scale_edge_color_manual(values = sample(paletteer::paletteer_d("ggsci::default_igv", 51), nrow(as.list(df4)$edges), replace = T)) +
theme_graph(background = 'grey20',
base_family = cnfont) -> p2
依然难以体现网络关系,这可能是因为国泰安的子公司数据收集自上市公司年报,里面只包含了上市公司认定的子公司,并不是所有上市公司有参股的公司,因此我们再试试从天眼查上爬取得到的数据,和国泰安提供的数据不同,该数据一个是反映了历年累计的投资记录,另一个是只要有投资占比都包含在内:
haven::read_dta("上市公司被投资公司列表.dta") -> df
# 20 家公司
df %>%
count(被投资公司名称, sort = T) %>%
filter(被投资公司名称 != "") %>%
slice(1:20) %>%
left_join(df) %>%
distinct(股票名称) %>%
left_join(df) -> df3a
df3a %>%
mutate(被投资公司名称 = str_remove_all(被投资公司名称, "有限公司|有限责任公司|股份有限公司")) -> df3a
as_tbl_graph(df3a) %>%
mutate(size = centrality_degree(mode = 'out')) -> df4
df4
df4 %>%
ggraph(layout = "kk") +
geom_edge_link(aes(edge_colour = factor(from),
edge_width = 投资比例), show.legend = F,
arrow = grid::arrow(type = "closed", length = unit(0.02, "inches"))) +
geom_node_point(aes(color = name,
size = size), show.legend = F) +
geom_node_text(aes(label = name, size = size, color = name), vjust = 1,
hjust = 1, check_overlap = T,
family = cnfont, show.legend = F) +
scale_edge_width(range = c(0.05, 0.2)) +
scale_size_continuous(range = c(0.2, 1)) +
scale_color_manual(values = sample(paletteer::paletteer_d("ggsci::default_igv", 51), length(df4), replace = T)) +
scale_edge_color_manual(values = sample(paletteer::paletteer_d("ggsci::default_igv", 51), nrow(as.list(df4)$edges), replace = T)) +
theme_graph(background = 'grey20',
base_family = cnfont) -> p3
这样效果更好~
更多关于网络图绘制的内容可以学习:
R 语言文本分析:https://geodatasci.duanshu.com/#/course/970c074747e54302a0ab0214e751eed6
使用 R 语言绘制中国地图 + 空间网络图:https://geodatasci.duanshu.com/#/course/45f58efbaf404043a9e756edb057c6b1
文献计量从0到SCI(五)R语言分析SCI论文研究国家和机构:
https://geodatasci.duanshu.com/#/course/575e40f19889490aacbbe1bac8d40386
直播信息
欢迎大家参加明晚 8 点的直播课:「R 语言:如何绘制上市公司投资网络图」
-
直播地址:腾讯会议(需要报名 地理数据科学 培训班参加)
-
更多关于 地理数据科学培训班 会员的更多信息可添加微信咨询:
附件下载(点击文末的阅读原文即可跳转):
https://geodatasci.duanshu.com/#/course/ccef302a76174eadaa0392a7a2467451