Python:在留外国人の詳細を円グラフで表示する

その買うを、もっとハッピーに。|ハピタス

在留外国人数を、国籍別、在留資格別に円グラフ化してみたいと思います。我が国日本は、在留外国人数が順調に増加しているのが微笑ましいのですが、私が生きている間に一刻も早く、在留外国人数が1000万人の大台を超えてもらいたいものです。多くの日本人がそのことを切に願っているはずだし、それが、日本がこの先生きのこる唯一の道だと言っても決して過言ではありません。

スポンサーリンク

国籍別在留外国人数

import tabula

df = tabula.read_pdf("http://www.moj.go.jp/content/001289225.pdf",
             output_format='dataframe',
             pages = '1',
             encoding='utf-8',
             java_options=None,
             pandas_options=None,
             multiple_tables=False)
df[4:6].head(2)
Unnamed: 0 Unnamed: 1 Unnamed: 2 平成20年末 平成21年末 平成22年末 平成23年末 平成24年末 平成25年末 平成26年末 平成27年末 平成28年末 平成29年末 平成30年末 Unnamed: 14 Unnamed: 15
4 NaN NaN NaN (2008) (2009) (2010) (2011) (2012) (2013) (2014) (2015) (2016) (2017) (2018) NaN NaN
5 NaN 総 数 NaN 2,144,682 2,125,571 2,087,261 2,047,349 2,033,656 2,066,445 2,121,831 2,232,189 2,382,822 2,561,848 2,731,093 100.0 6.6
df1 = df[['Unnamed: 1','平成30年末']][6:18].drop(7)
df1 = df1.set_index(['Unnamed: 1'])
df1
平成30年末
Unnamed: 1
764,720
449,634
ト ナ ム 330,835
ィ リ ピ ン 271,289
ラ ジ ル 201,865
パ ー ル 88,951
60,684
57,500
NaN 56,346
52,323
の 他 396,946
df1.index=['中国','韓国','ベトナム','フィリピン','ブラジル','ネパール','台湾','米国',\
          'インドネシア','タイ','その他'] 
df1
平成30年末
中国 764,720
韓国 449,634
ベトナム 330,835
フィリピン 271,289
ブラジル 201,865
ネパール 88,951
台湾 60,684
米国 57,500
インドネシア 56,346
タイ 52,323
その他 396,946
for i, col in enumerate(df1.columns):
    df1.iloc[:, i] = df1.iloc[:, i].str.replace(',', '')
df1 = df1.apply(pd.to_numeric, errors="coerce").astype(int)
%matplotlib inline
from matplotlib.pyplot import *
from matplotlib.font_manager import FontProperties
from matplotlib import rcParams

style.use('classic')
fp = FontProperties(fname='/usr/share/fonts/opentype/ipaexfont-gothic/ipaexg.ttf', size=54)
rcParams['font.family'] = fp.get_name()
c      = [(x/22.0, x/77.0, .9) for x in range(len(df1))] 

fig, ax = subplots(figsize=(18,10))
_,texts,autotexts = ax.pie(df1['平成30年末'],labels=df1.index,colors=c,shadow=True,\
 explode=(0,0.1,0,0,0,0.1,0,0.1,0.,0.1,0.),autopct='%1.2f%%',wedgeprops = {'linewidth': 3},\
  textprops={'fontsize': 25},startangle=65,pctdistance=.85,labeldistance=1.1,radius=1.2);
#texts.set_fontsize(50)
setp(autotexts, size=20, weight="bold");
setp(texts, size=25, weight="bold");
for autotext in autotexts:
    autotext.set_color('white')

在留外国人の4人に3人の国籍が、中国、韓国、ベトナム、フィリピン、ブラジルの5カ国で占められているというのは驚きではないでしょうか。diversity(多様性)に欠けていると言わざるを得ません。このグラフは、日本がもっと中近東・アフリカからも移民・難民をどんどん受け入れる必要があることを如実に物語っています。特に、イスラム系移民を、ドイツのように100万人単位で受け入れるべきでしょう。
スポンサーリンク

在留資格別在留外国人数

import tabula

df2 = tabula.read_pdf("http://www.moj.go.jp/content/001289225.pdf",
             output_format='dataframe',
             pages = '4',
             encoding='utf-8',
             java_options=None,
             pandas_options=None,
             multiple_tables=False)
df3 = df2[1:2]
df3
日本人の国籍・地域 計 特別永住者 中長期在留者 永住者 留学 技能実習 技術・ 人文知識・ Unnamed: 7 定住者 家族滞在 Unnamed: 10 特定活動 その他
1 総 数 2,731,093 321,416 2,409,677 771,568 337,000 328,360 225,724 NaN 192,014 182,452 142,381 62,956 167,222
df3.drop(['中長期在留者','Unnamed: 7'], axis=1,inplace=True)
df3.rename(columns={'日本人の国籍・地域 計':'総数','技術・ 人文知識・':'技術・人文知識・国際業務','Unnamed: 10':'日本人の配偶者等'},inplace=True)
df3
総数 特別永住者 永住者 留学 技能実習 技術・人文知識・国際業務 定住者 家族滞在 日本人の配偶者等 特定活動 その他
1 総 数 2,731,093 321,416 771,568 337,000 328,360 225,724 192,014 182,452 142,381 62,956 167,222
for i, col in enumerate(df3.columns):
    df3.iloc[:, i] = df3.iloc[:, i].str.replace('総 数','').str.replace(',','')
df3 = df3.apply(pd.to_numeric, errors="coerce").astype(int)
df3.index=['外国人数']
df3
総数 特別永住者 永住者 留学 技能実習 技術・人文知識・国際業務 定住者 家族滞在 日本人の配偶者等 特定活動 その他
外国人数 2731093 321416 771568 337000 328360 225724 192014 182452 142381 62956 167222
df3.drop(['総数'], axis=1,inplace=True)
df3
特別永住者 永住者 留学 技能実習 技術・人文知識・国際業務 定住者 家族滞在 日本人の配偶者等 特定活動 その他
外国人数 321416 771568 337000 328360 225724 192014 182452 142381 62956 167222
k=df3.T.sort_values('外国人数',ascending=False)
m=[]
for i in k['外国人数']:
    m.append(i)
n=[]
for i in k.T.columns:
    n.append(i)
c = cm.inferno_r(np.linspace(.2,.5, 10))

fig, ax = subplots(figsize=(18,10))
_,texts,autotexts = ax.pie(m,labels=n,colors=c,shadow=True,\
 explode=(0,0.1,0,0,.15,0.1,0,0.1,0.,0.1,),autopct='%1.2f%%',wedgeprops = {'linewidth': 3},\
  textprops={'fontsize': 25},startangle=0,pctdistance=.75,labeldistance=1.1,radius=1.2);
#texts.set_fontsize(50)
setp(autotexts, size=25, weight="black",color='black')
setp(texts, size=25, weight="heavy",color='black');

よくよく考えると、これだけでは人数が分からないので人数も表示する必要があります。

fig, ax = subplots(figsize=(18,10))
def func(pct, allvals):
    absolute = int(pct/100.*np.sum(allvals))
    return "{:.1f}%\n({:,}人)".format(pct, absolute)
c = cm.spring_r(np.linspace(0.1, 0.5, 10))
wedges,texts,autotexts = ax.pie(m,labels=n,shadow=True,colors=c,\
 explode=(0,0.1,0,0,.15,0.1,0,0.1,0.,0.1,),autopct=lambda pct: func(pct, m),wedgeprops = {'linewidth': 3},\
  textprops={'fontsize': 25},startangle=0,pctdistance=.80,labeldistance=1.1,radius=1.2);
setp(autotexts, size=16, weight="black",color='k')
setp(texts, size=25, weight="heavy",color='black');

ただ、これだと文字が小さ過ぎて見辛いので、矢印付きで表示してみます。その前に、intをstrに変換する必要があります。

e = []
for i in m:
    e.append(str(i))
c=[]
for i in range(len(e)):
    d=e[i][:len(e[i])-4]+'万'+e[i][-4:]
    c.append(d)
f=["{}({}人)".format(n_, c_) for c_, n_ in zip(c, n)]
fig, ax = subplots(figsize=(18,10))

wedges,texts,autotexts = ax.pie(m,shadow=True,labeldistance=1,radius=1.2,\
 explode=(0.1,0.,0.1,0.,.15,0.,0.1,0.,0.1,0.,),wedgeprops = {'linewidth': 3},\
  autopct='%1.2f%%',textprops={'fontsize': 25},startangle=160,\
   pctdistance=.75,counterclock=False)

plt.setp(autotexts, size=35, weight="bold",color='w')

bbox_props = dict(boxstyle="square,pad=0.3", fc="w", ec="k", lw=0.72)
kw = dict(arrowprops=dict(arrowstyle="-"),
          bbox=bbox_props, zorder=0, va="center")

for i, p in enumerate(wedges):
    ang = (p.theta2 - p.theta1)/2 + p.theta1
    y = np.sin(np.deg2rad(ang))
    x = np.cos(np.deg2rad(ang))
    horizontalalignment = {-1: "right", 1: "left"}[int(np.sign(x))]
    connectionstyle = "angle,angleA=0,angleB={}".format(ang)
    kw["arrowprops"].update({"connectionstyle": connectionstyle})
    ax.annotate(f[i], xy=(x, y), xytext=(1.5*np.sign(x), 1.45*y),size=30,
                horizontalalignment=horizontalalignment, **kw)

移民とは、永住権保持者、もしくは、将来的に永住権獲得の権利を持つ外国人のことを指すので、日本の場合は、定住者、日本人の配偶者、特別永住者と永住者がそれに当たるのだろうと思われます。なので、現時点で、本当の意味での移民に当たる在留外国人の数は、総在留外国人数の半分程度ということになります。残りの在留外国人のうち、どのくらいの人々が将来的に永住権を獲得できるのかは未知数です。少子化が人類史上未曾有のペースで進行している日本の場合、今後、貴重な若い留学生と技能実習生が永住権を取得しやすいように法整備し、子持ちの若い移民・難民を積極的に受け入れていくことが唯一の生き残りに道だと言えます。

1947年〜2018年の出生数と婚姻・離婚件数の推移をプロット
1950年〜2017年の日本人女性の年代別出産数推移をグラフ化
1908年〜2017年の平均婚姻年齢(初婚・全婚姻)をグラフ化
若年・中年・高年・超高年層死亡数推移(1950年〜2017年)
日本の右肩下がりの出生数と右肩上がりの死亡者数をグラフ化する
日本の交通事故死亡者数の推移を性別・年齢別に棒グラフ化する
過去38年間の10カ国の国民一人当たりGDP推移をグラフ化する
Python:国籍別に在留外国人数の多い市町村を抽出する
Python:在留外国人比率の高い市町村を条件別に抽出する
Python:年齢別交通事故死亡数を死亡割合に変換する
Python:日本人の年代別・性別死亡数を視覚化して考察する
Python:日本人の年齢別死亡者数の推移をプロットして考察する
Python:1950年〜2017年の年齢別自殺数推移を棒グラフ化する
Python:結婚適齢期女性が最も余っている都市を探し出す

スポンサーリンク
スポンサーリンク