查看原文
其他

软件应用 | 如何用Stata绘制带指向性箭头标注的图像

数据Seminar 2022-12-31

The following article is from Stata and Python数据分析 Author 爬虫俱乐部

本文转载自公众号Stata and Python数据分析

本文作者:邱   沣,河南大学经济学院

导读

众所周知,Stata拥有强大的画图功能,除了常见的条形图、折线图、饼图等等,我们也可以使用Stata画出一些有趣的小图形,今天要介绍的就是使用pcarrowi命令,绘制带指向性箭头标注的图像。

Part1pcarrowi命令介绍

pcarrowi命令可以在绘图中加入指向性箭头并在后面跟上所要标注的文本,它脱胎于pcarrow命令(绘制带有箭头的成对坐标图),命令使用规范如下:

twoway pcarrowi immediate_values [,  options]

其中immediate_values指的是#y1 #x1 #y2 #x2 [(#_clockposstyle)] ["text for label"]

#y1 #x1 #y2 #x2 分别指的是箭头的起点和终点的坐标;

(#_clockposstyle)指的是箭头尾部所跟的标注内容的位置,一般为 1-12,而这些方位又恰好与时钟的12个点数位置相符,所以还是很方便使用的;

"text for label"就很明显了,指的是我们要标注的内容,一般都用双引号引用起来。当然我们也可以将内容放在 text() 里当作 options 跟在其后。需要注意的是:使用text()命令时,需要在标注内容前加上坐标,比如:text(1.25 2.60 "标注内容")

Part2绘制单个箭头

接下来我们先举一些简单的例子,大家就知道该如何使用pcarrowi这个命令了。

比如我们画一个从坐标 (1 , 2) 到 (3 , 2) 的箭头并配上标注“爬虫俱乐部”,这里需要注意:命令中坐标点的输入是 (y , x) 而不是 (x , y)。

twoway pcarrowi 2  1  3  2  (6) "爬虫俱乐部" ,aspect(2) plotregion(margin(vlarge)) 
*转换标注位置
twoway pcarrowi 2  1  3  2  (3) "爬虫俱乐部" ,aspect(2) plotregion(margin(vlarge))

如上述程序所述,标注“爬虫俱乐部”的位置分别在时钟的六点钟和三点钟方向,其中aspect(2)为设置绘图区域纵横比为2,当然这里可更改为任意比例。plotregion选项可以设置绘图边缘大小。比如:

twoway pcarrowi 2  1  3  2  (6) "爬虫俱乐部" ,aspect(1) plotregion(margin(vlarge)) //设置纵横比为1
twoway pcarrowi 2  1  3  2  (6) "爬虫俱乐部" ,aspect(2) plotregion(margin(small)) //设置内部区域边际为小

Part3绘制多个箭头

下面我们来看如何在一个坐标系中绘制多个箭头:

twoway pcarrowi 0  0  0  1  (3) "3 o'clock" 0  0  1  0 (12) "12 o'clock", aspect(1) headlabel plotregion(margin(vlarge))

其中headlabel指的是标注在箭头的头部,而不是尾部。

通过简单地添加同样格式的对箭头的设定就能实现绘制多个箭头及进行标注。那如果我们想绘制多个且长短不一的箭头该怎么实现呢?

twoway pcarrowi 2  2  2  4  (3) "3 o'clock" 2  2  4  2 (12) "12 o'clock"  2  2  2  0  (9) "9 o'clock", aspect(1) headlabel plotregion(margin(vlarge))

通过设置不同的起点、终点坐标就可以画出方向、长短不同的箭头,这里我们就绘制出来了简约版时钟中的八时十五秒(八点的看作时针,十二点的看作分针)。通过上边这些例子,我们可以看出如何画出箭头以及设置标注的位置。

紧接着我们看如何标注散点图中的特殊点,也就是如何在图形中添加多个指向性箭头标注。

sysuse auto,clear
twoway qfitci mpg weight,stdf || scatter mpg weight,ms(O) || pcarrowi 41 2200 41 2060 (3) "VW Diesel" 31 3460 28 3280 (3) "Plymouth Arrow"35 2250 35 2070 (3) "Datsun 210 and Subaru",legend(order(1 2 3))

首先我们绘制出散点图,并使用qfitci命令进行二次拟合并画出95%的置信区间,这时我们想标注那些特殊点就可以使用pcarrowi命令了,通过这些点的坐标我们可以确定箭头的终点,比如(41,2200),然后根据我们的所需就可以自定义箭头的起点,比如(41 2060),最后加上位置符(3)和所需标注内容就可以绘制出带标注的箭头了。

可以看出我们只要精准定义了坐标,就能很容易地绘制出所需长短的箭头了,接下来我们来看一下如何设置箭头的颜色,粗细,大小等。

Part4如何设置箭头的样式

我们在日常的使用中,如何根据具体需求个性化地设置箭头标注呢?首先,可以借助 mstyle() 选项来设置总样式,可有p1-p15可选择。

1设置大小

  • msize(msiz) :箭头大小

  • barbsize(barb):箭头填充部分的大小

  • mlabsize :标注部分字体大小

    其中选项从小到大有:

    vtiny 、tiny、vsmall、small、medsmall、medium、medlarge、large、vlarge、huge、vhuge、ehuge

    当然也能自定义大小,help size可获取具体方式。

接下来我们一步步演示如何设置箭头和标注的大小,先看如何设置单个箭头:

twoway pcarrowi 2  1  3  2  (3) "爬虫俱乐部" ,msize(vlarge) aspect(2) plotregion(margin(vlarge))

通过msize选项,我们改变了箭头的大小。

twoway pcarrowi 2  1  3  2  (3) "爬虫俱乐部" ,barbsize(vlarge) aspect(2) plotregion(margin(vlarge))

加入barbsize选项后我们就可以对箭头内部进行填充,并设置填充部分的大小,无此选项的话,箭头就只有外部轮廓线。

twoway pcarrowi 2  1  3  2  (3) "爬虫俱乐部" ,mlabsize(large) aspect(2) plotregion(margin(vlarge))

使用mlabsize我们可以使标注部分字体变得更大。

那么如何同时设置多个箭头和标注的大小呢?

twoway pcarrowi 2  2  2  4  (3) "3 o'clock" 2  2  3.4  2 (12) "12 o'clock"  2  2  1.5  0.6 (8) "8 o'clock", ///
msize(large) barbsize(large) mlabsize(vlarge) aspect(1) headlabel plotregion(margin(vlarge))

在上边的程序中我们同时使用了三个选项,对箭头,填充部分和标注内容的大小都进行了定义,进一步,可以不可以分别定义每个箭头和标注的大小呢?当然是可以的!

twoway (pcarrowi 2  2  2  4  (3) "3 o'clock" ,msize(medium)  aspect(1) mlabsize(large) headlabel plotregion(margin(vlarge))) ///
(pcarrowi 2  2  3.4  2 (12) "12 o'clock",msize(medlarge) barbsize(medlarge) mlabsize(large) headlabel plotregion(margin(vlarge))) ///
(pcarrowi  2  2  1.5  0.6 (8) "8 o'clock", msize(vlarge) barbsize(vlarge) mlabsize(large) headlabel plotregion(margin(vlarge)))

其实很简单,如案例所示分别将其用 ( ) 分隔起来就好了,这样每个箭头之间都是独立的部分,可以进行单独的操作。

2设置颜色和粗细

  • mcolor(mc) :箭头的颜色和不透明度,包含内外

  • mfcolor(mfc) :箭头"填充"颜色和不透明度

  • mlcolor(mlc) :箭头轮廓颜色和不透明度

    其中颜色选项就不胜枚举了,常用的有:black、blue、gold、green、yellow等,其他更多选项可以通过 help colorstyle获取。

  • mlwidth(mlw) :箭头轮廓厚度(粗细)

    其中选项从薄到厚有:none、vvvthin、vvthin、vthin、thin、medthin、medium、medthick、thick、vthick、vvthick、vvvthick

    当然也能自定义厚度(粗细),help size可获取具体方式

  • mlstytle(mlsty) :轮廓厚度(粗细)和颜色

    与上文类似,有p1-p15可供选择,更多样式选择可以通过help style 获取

同样的我们先来看如何设置单个箭头的颜色和粗细。

twoway pcarrowi 2  1  3  2  (6) "爬虫俱乐部", mcolor(red)  msize(vlarge) aspect(2) plotregion(margin(vlarge))
twoway pcarrowi 2  1  3  2  (6) "爬虫俱乐部", mcolor(red)  mfcolor(yellow) msize(vlarge) barbsize(large) aspect(2) plotregion(margin(vlarge))

这里需要注意的是mfcolor要与barbsize搭配使用,只有设置了箭头填充部分后才能给其定义颜色。而barbsize不能和mlwidth搭配使用,不然箭头加粗就会被箭头填充部分的内容覆盖掉。

twoway pcarrowi 2  1  3  2  (6) "爬虫俱乐部", mcolor(red)  mlwidth(vthick) msize(vlarge)  aspect(2) plotregion(margin(vlarge))

设置多个箭头的颜色和粗细如下:

twoway (pcarrowi 2  2  2  4  (3) "3 o'clock" ,mcolor(blue)  mlwidth(thick) msize(medium) aspect(1) mlabsize(large) headlabel plotregion(margin(vlarge))) ///
(pcarrowi 2  2  3.4  2 (12) "12 o'clock",mcolor(gold) mlwidth(vthick) msize(medlarge) barbsize(medlarge) mlabsize(large) headlabel plotregion(margin(vlarge))) ///
(pcarrowi  2  2  1.5  0.6 (8) "8 o'clock", mcolor(red) mfcolor(gold)  mlwidth(vthick) msize(vlarge) barbsize(vlarge) mlabsize(large) headlabel plotregion(margin(vlarge)))

这里需要注意的是mcolor(red)mfcolor(gold)mlwidth(vthick)三者同时出现时,箭头加粗就会被填充部分的内容覆盖掉了,颜色由mcolor设定为主。

3设置角度

mangle():箭头的角度(箭头内角的大小)。括号里可以直接加入数字代指角度,比如 45 90 180,也可以输入 horizontal vertical 等。具体可见 help anglestyle

twoway pcarrowi 2  1  3  2  (3) "爬虫俱乐部",mangle(90) msize(vlarge)  aspect(2) plotregion(margin(vlarge))

这里我们设置箭头角度为90后,可以看到它折叠为一条直线了,这里我们只是举一个极端的例子供大家学习,一般还是小角度的使用比较多。

4设置箭杆的样式

  • lstyle (lsty):线条整体风格

  • lpattern (lp):线条连接方式,实线、虚线等。其中选项有:solid  dash  dot  dash_dot  shortdash  longdash  blank 等

  • lwidth (lw):线条粗细

  • lcolor (lc):线条颜色

整体风格,粗细和颜色的设定可以参考前面的介绍。

twoway pcarrowi 2  1  3  2  (6) "爬虫俱乐部" , ///
lp(dash_dot) lw(thick) lc(green) mlwidth(thick) mcolor(gold) msize(large)  mlabsize(large)  aspect(1) plotregion(margin(vlarge))

这样我们就通过命令设置了线条为交错的虚线,线条为粗,颜色为绿色。

Part5综合案例

我们通过一个案例看具体如何使用这些具体的选项,先看一下前面举过的例子:

sysuse auto,clear
twoway qfitci mpg weight,stdf || scatter mpg weight,ms(O) || ///
pcarrowi 41 2200 41 2060 (3) "VW Diesel" 31 3460 28 3280 (3) "Plymouth Arrow"35 2250 35 2070 (3) "Datsun 210 and Subaru", ///
mstyle(p10) msize(huge) mlabsize(medium) mcolor(blue) mlwidth(thick)  lp(dash) lw(thick) lc(gold) mangle(30) legend(order(1 2 3))

这里我们重新设置了箭头的大小,粗细和颜色,以及箭柱的连接方式,粗细和颜色,最后还设置了箭头的角度。通过刚刚介绍的这些选项我们可以自定义我们想要的内容。

我们再使用auto数据进行一个演示:

twoway scatter mpg weight if foreign==1 || lfit mpg weight if foreign==1||scatter mpg weight if foreign==0 || lfit mpg weight if foreign==0  ///
|| pcarrowi 17 2550 20 2750 (5)      /// 
             26 3050 23 2800 (5),     ///
mstyle(p14) msize(huge) barbsize(vlarge) mlabsize(huge) mcolor(gold) mlwidth(thick) mangle(20) lp(dash) lw(thick) lc(blue) ///
text(16.5 2500 "Foreign" 26.8 3100 "Domestic")xtitle("weight") ytitle("mpg")legend(order(1 "Foreign" 2 "Foreign" 3 "Domestic" 4 "Domestic") row(1))

这里不同的就是,我们用text选项定义了文本的位置。

最后我们画一个有趣的案例:简易时钟。

clear all 
set obs 12 
gen theta = 2*_pi*_n/12
gen x = cos(theta)
gen y = sin(theta)
forvalues i = 1/12{
local x`i' = x[`i']
local y`i' = y[`i']
}
twoway (pcarrowi 0 0 -0.25 -0.5 (8)  ,headlabel msize(large) lw(medthick) text(-0.6 -0.9  "8")) ///
       (pcarrowi 0 0 `x12' `y12' (12) "12" ,headlabel msize(large) lw(medthick)) ///
       (pcarrowi `x1' `y1' `x2' `y2',mstyle(sunflower)) ///
     (pcarrowi `x2' `y2' `x3' `y3',mstyle(sunflower)) ///
     (pcarrowi `x3' `y3' `x4' `y4',mstyle(sunflower)) ///
     (pcarrowi `x4' `y4' `x5' `y5',mstyle(sunflower)) ///
     (pcarrowi `x5' `y5' `x6' `y6',mstyle(sunflower)) ///
     (pcarrowi `x6' `y6' `x7' `y7',mstyle(sunflower)) ///
     (pcarrowi `x7' `y7' `x8' `y8',mstyle(sunflower)) ///
     (pcarrowi `x8' `y8' `x9' `y9',mstyle(sunflower)) ///
     (pcarrowi `x9' `y9' `x10' `y10',mstyle(sunflower)) ///
     (pcarrowi `x10' `y10' `x11' `y11',mstyle(sunflower)) ///
     (pcarrowi `x11' `y11' `x12' `y12',mstyle(sunflower)) ///
     (pcarrowi `x12' `y12' `x1' `y1',mstyle(sunflower)) ///
     ,aspect(1) plotregion(margin(vlarge)) legend(off)

首先我们生成12等分角,然后用cos和sin我们生成了相对应的坐标,接着我们将这些坐标首尾相连就形成了一个密闭的时钟表盘了,最后我们再用箭头绘制上时针和分针。

通过上述介绍我们可以看到小小箭头也大有文章可做,通过与不同的图形搭配,它既可以标注内容也可以画出一些有趣的图形。欢迎大家在此篇推文的基础上,再探索出更多的用法。




星标⭐我们不迷路!
想要文章及时到,文末“在看”少不了!

点击搜索你感兴趣的内容吧



往期推荐


统计计量 | 经典计量经济学教材推荐(含链接)

数据资源 | 人文社科开放数据库汇总(含文献链接)

数据可视化 | 造假防忽悠指南

数据治理 | 多人协同处理数据担心不安全?学会这一招,轻松管理你的数据团队

数据资源 | 收藏!数据资源下载网址大全

数据可视化 | 惊艳全球数据行业的15个例子

统计计量 | 今天,你PSM了吗?






数据Seminar




这里是大数据、分析技术与学术研究的三叉路口


推荐 | 青酱


    欢迎扫描👇二维码添加关注    

点击下方“阅读全文”了解更多

您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存