今天给大家分享一个邪修技能:从论文图表中提取数据重新使用 Stata 或者 R 语言绘图。
经常我们会遇到一个问题,我们想使用参考文献中某个图表的数据,但是作者并不提供数据。这个时候该怎么办呢?
最近为了解决这个问题,我借助豆包编写了一个网页应用:getpicdata,应用的首页是这样的:

其他好用的应用大家也可以先自行探索。
可以使用附件中提供的离线文件访问这个应用。
首次打开加载速度会较慢,耐心等待即可。
该应用不仅可以提取单组 xy 数据,还可以提取多组。
本次课程我们将以两幅图为例演示该应用的使用方法。
单组 xy 图表的提取
对于单组 xy 图表的数据提取,我们以下面这幅图为例:

将该图片上传到我编写的这个应用里面:

第一步要做的事情就是手动在图上选择四个点:xmin,xmax, ymin, ymax, 需要注意,标记点并不需要刻意与点击点重合,只要鼠标点击位置准确即可:

在图上点击之后就会生成标记,标记放置的位置和和鼠标点击点有偏移,这个并不影响;然后就是 ymin 和 xmin 通常是一个位置,拖动标记点让两者重合即可。
然后看页面的左侧,设定四个值:

输入之后点击“确定坐标范围”。
下一步是设定数据组的名字,这个随便写就行,毕竟现在只有一组数据:

点击“添加数据点”。然后在图表上逐个数据点:

再次注意,标记点和鼠标点击点位置是有偏移的,这个并不会有影响,不要拖动让两者一致!
点击“保存当前数据组”就完成这组数据的添加了。

如果手动点击取点的时候有点击错的,也可以在这个表里面删除(保存数据组前,这个表的操作列里面可以点击删除某个点)。
最后就可以点击导出 csv 文件了:

这里我导出的文件名称为 chart_data_2025-09-08.csv。在 Stata 中读取:
cd "~/Desktop/如何从论文图表中提取数据重新使用 Stata 或者 R 语言绘图" import delimited using "chart_data_2025-09-08.csv", clear list
|
对这个数据进行简单的处理就可以再重新绘制这幅图了:
replace x = round(x)
tw conn y x, lp(solid) m(o) color(black) msize(small) xla(2005(2)2019) yla(10(2)20) ysc(range(10 20)) xti("图1 我国社会物流总费用占 GDP 比重逐年走势") yti("社会物流总费用占 GDP 比重(%)", bexpand justification(right)) note("注:数据源于历年《中国物流年鉴》。") sch(qlean)
gr export pic11.png, width(4800) replace
|

是不是几乎一模一样~
使用 R 语言绘制:
library(tidyverse)
data <- read_csv("chart_data_2025-09-08.csv")
data <- data %>% mutate(x = round(x))
data
ggplot(data, aes(x = x, y = y)) + geom_line(linetype = "solid", color = "black") + geom_point(shape = 16, size = 2, color = "black") + scale_x_continuous( breaks = seq(2005, 2019, by = 2), limits = c(2005, 2019) ) + scale_y_continuous( breaks = seq(10, 20, by = 2), limits = c(10, 20) ) + labs( x = "图1 我国社会物流总费用占 GDP 比重逐年走势", y = "社会物流总费用占 GDP 比重(%)", caption = "注:数据源于历年《中国物流年鉴》。" ) + theme_classic(base_family = cnfont) + theme( plot.caption = element_text(hjust = 1), axis.title.y = element_text(hjust = 1) ) -> p1
ggsave("pic11b.png", device = png, width = 8, height = 6)
|

还可以把数据也标注到图上:
tostring y, gen(label) format(%6.2f) force replace label = label + "%" egen pos = fill(12 6 12 6) tw conn y x, lp(solid) m(o) color(black) msize(small) xla(2005(2)2019) yla(10(2)20) ysc(range(10 20)) mlab(label) mlabvpos(pos) xti("图1 我国社会物流总费用占 GDP 比重逐年走势") yti("社会物流总费用占 GDP 比重(%)", bexpand justification(right)) note("注:数据源于历年《中国物流年鉴》。") sch(qlean)
gr export pic12.png, width(4800) replace
|

使用 R 语言:
data <- data %>% mutate( label = paste0(format(round(y, 2), nsmall = 2), "%"), pos = rep(c(12, 6), length.out = n()) )
data
ggplot(data, aes(x = x, y = y)) + geom_line(linetype = "solid", color = "black") + geom_point(shape = 1, size = 2, color = "black") + geom_text( aes(label = label, y = y + ifelse(pos == 12, 0.3, -0.3)), size = 3, color = "black", family = cnfont ) + scale_x_continuous( breaks = seq(2005, 2019, by = 2), limits = c(2005, 2019) ) + scale_y_continuous( breaks = seq(10, 20, by = 2), limits = c(10, 20), labels = function(x) paste0(x, "%") ) + labs( x = "图1 我国社会物流总费用占 GDP 比重逐年走势", y = "社会物流总费用占 GDP 比重(%)", caption = "注:数据源于历年《中国物流年鉴》。" ) + theme_classic(base_family = cnfont) + theme( plot.caption = element_text(hjust = 1), axis.title.y = element_text(hjust = 1) ) -> p2
ggsave("pic12b.png", device = png, width = 8, height = 6)
|

多组 xy 图表的提取
下面我们再来看下多组 xy 图表数据的提取,这个更为实用,例如下面这个回归系数 + 置信区间的图:

同样的步骤、上传图表、设置四至范围、添加第一组数据:

然后输入第二组数据的名字:ymin,点击取点:

第三组 ymax:

导出数据:chart_data_2025-09-08 (1).csv
然后就可以使用 Stata 绘制这个图表了:

再使用 R 语言:
data <- read_csv("chart_data_2025-09-08 (1).csv") data
data <- data %>% mutate(x = round(x)) %>% group_by(group, x) %>% mutate(id = row_number()) %>% ungroup() %>% pivot_wider( names_from = group, values_from = y, values_fill = NA ) %>% select(-id) %>% mutate( ymax = ifelse(x == -1, beta, ymax), ymin = ifelse(x == -1, beta, ymin) )
|

关于该应用的更多用法,大家还可以继续深入探索
点击这里跳转到 RStata 短书平台获取附件:如何从论文图表中提取数据重新使用 Stata 或者 R 语言绘图
评论