Rを用いて大阪市住民投票のいろいろなデータを探して相関関係をみる

はじめに

今回はRを用いて先に行われた大阪市住民投票の結果からいくつかのデータを探して相関分析をしてみます。今回は興味本位でいくつかのデータ探し、それらしいデータを取り込んで分析してみました。 なお、サンプルソースとデータは以下のgithubにありますので、動かして確認いただければと思います。コードはvote.Rです。

https://github.com/tokomakoma123/my_R

投票データの処理

利用データ

以下に住民投票の速報データがありましたので、これを切り取ってCSV形式にしました。

http://www.city.osaka.lg.jp/contents/wdu240/sokuho/tohyo_data_10.html

作成したCSVデータは以下の通りです。

区名,賛成,反対
北区,"36,019","25,001"
都島区,"30,135","26,671"
福島区,"21,586","17,267"
此花区,"17,597","18,872"
中央区,"24,336","20,657"
西区,"26,094","19,160"
港区,"21,410","23,351"
大正区,"16,646","21,211"
天王寺区,"18,327","20,815"
浪速区,"13,563","12,189"
西淀川区,"23,670","28,337"
淀川区,"48,566","38,903"
東淀川区,"43,388","41,340"
東成区,"20,689","20,667"
生野区,"25,396","29,190"
旭区,"23,145","28,048"
城東区,"46,728","45,784"
鶴見区,"29,859","29,752"
阿倍野区,"30,434","32,446"
住之江区,"33,184","36,880"
住吉区,"38,623","45,950"
東住吉区,"34,079","37,322"
平野区,"46,072","56,959"
西成区,"25,298","28,813"

Rのプログラム

次にこのデータを用いてRを使って処理します。

#
# 得票数のデータを処理する
#
vote = read.csv("data/vote.csv",header=TRUE,stringsAsFactor=FALSE)

vote$賛成 <- as.numeric(gsub(",", "",vote$賛成)) # 数値化する
vote$反対 <- as.numeric(gsub(",", "",vote$反対)) # 数値化する

vote <- transform(vote,
                  反対率 = (vote$/ vote$小計) * 100)

# 賛成 - 反対のグラフを描く

barplot(t(vote[,5]), names.arg = vote[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,ylab="反対 - 賛成")

するとこんなグラフになりました。

R1.png

若干Rのプログラムは違いますが、ここまでは前回同じことをやりました。

有権者数のデータを追加する

利用データ

投票データに有権者数のデータを追加します。有権者数がなぜ必要かというと、得票数は すでにわかっているのですが、投票率を知りたいからです。

実は得票率と有権者数が表になっているサイトがあることを後からしりました。

http://ja.wikipedia.org/wiki/大阪市特別区設置住民投票

でもこの中から区名と有権者数のデータを手で抜き出します。

区名     有権者数
北区     94,128
都島区   82,237
福島区   56,798
此花区   54,470
中央区   71,819
西区     70,287
港区     66,673
大正区   55,159
天王寺区  54,774
浪速区    48,936
西淀川区  75,827
淀川区    138,515
東淀川区  136,353
東成区    61,085
生野区    83,886
旭区     74,371
城東区    132,091
鶴見区    85,852
阿倍野区  85,354
住之江区  100,867
住吉区    123,549
東住吉区  105,456
平野区    155,527
西成区    90,062

Rプログラム

このデータをこれまで加工したデータにくっつけます。merge関数を使うことで2つのデータフレームを結合します。

# テーブル形式(スペース区切り)のデータを読み込む

yukensya <- read.table("data/yukensya.dat",header=T)

# カンマ(,)を取り除き、文字列->数値変換する

yukensya$有権者数 <- as.numeric(gsub(",","",yukensya$有権者数))

# 2つのデータフレームを結合する
# これまでのデータフレームと有権者のデータフレームを2つのキーでジョインする

vote <- merge(x = vote, y = yukensya, by.x = "区名", by.y = "区名", all = TRUE)

# 投票率を(賛成票 + 反対票) / 有権者数で計算する

vote <- transform(vote,
                   投票率 = (vote$小計 / vote$有権者数) * 100)

年齢データを追加する

今回の投票で高齢者では反対票が多いということだったので、実際にどうかを調べるために、平均年齢の情報を探して、これまでのデータに追加します。

利用データ

データを切り出したあとで、データの出所を探したのですが、見つかりませんでした。見つかったら、このサイトを更新します。

自治体名    平均年齢           15才未満     15~64才     65才以上
大阪市西成区    52.19才         9,071人    69,435人    41,285人
大阪市生野区    47.12才        14,205人    82,742人    36,102人
大阪市旭区      46.62才        10,378人    57,478人    24,263人
大阪市大正区    46.36才        8,513人     43,058人    17,585人
大阪市東住吉区  46.19才        15,842人    80,731人    33,635人
大阪市阿倍野区  45.68才        12,864人    67,213人    25,630人
大阪市住之江区  45.35才        15,445人    82,120人    28,911人
大阪市此花区    45.30才        7,961人     41,950人    15,545人
大阪市住吉区    45.22才        19,112人    98,097人    37,393人
大阪市東成区    45.19才        9,078人     51,820人    18,577人
大阪市港区      45.04才        9,967人     54,559人    19,896人
大阪市平野区    44.42才        28,494人    122,469人    48,180人
大阪市都島区    44.24才        11,617人    69,011人    20,718人
大阪市城東区    44.08才        21,903人    106,951人    36,210人
大阪市淀川区    43.80才        18,256人    117,819人    34,061人
大阪市浪速区    43.76才        3,609人     43,967人    11,548人
大阪市西淀川区  43.76才        13,488人    62,777人    20,685人
大阪市北区      43.62才        9,077人     78,636人    20,032人
大阪市東淀川区   43.14才        19,980人    118,866人    35,775人
大阪市福島区     43.01才        7,611人     46,011人    12,785人
大阪市中央区     42.94才        6,129人     59,337人    13,215人
大阪市天王寺区    42.74才        8,588人    46,849人    12,680人
大阪市鶴見区     41.48才        18,308人    70,672人    21,539人
大阪市西区       41.04才        8,597人     61,864人    12,585人

Rのプログラム

Rでスペース区切りのデータを読み込んで処理します。結合するために区名の"大阪市"を削除したり、数値データの"才"、"人"などの文字を取り除き、数値化します。そして同じように結合しますが、 平均年齢と65才以上の人数のみ利用します。

#
# 年齢データを読み込む
#

age <-read.table("data/age.txt",stringsAsFactor=FALSE,header=T)
names(age) <- c("区","平均年齢","年齢15才未満","年齢15から64才未満","年齢65才以上")

# 区のデータを整形する("大阪市"を削除する)

age$<- substr(age$,4,nchar(age$))

# 不要なカンマがある場合は取り除き、数値データに変換する

age$平均年齢 <- as.numeric(substr(age$平均年齢,1,nchar(age$平均年齢)-1))

age$年齢15才未満 <-
  as.numeric(gsub(",","",substr(age$年齢15才未満,1,nchar(age$年齢15才未満)-1)))

age$年齢15から64才未満 <-
  as.numeric(gsub(",","",substr(age$年齢15から64才未満,1,nchar(age$年齢15から64才未満)-1)))

age$年齢65才以上 <-
  as.numeric(gsub(",","",substr(age$年齢65才以上,1,nchar(age$年齢65才以上)-1)))

#でもやっぱり平均年齢と年齢65才以上しか使わないので、不要な項目は削除する

age <- age[,c(1,2,5)]

#これまでのデータフレームと結合する

vote <- merge(x = vote, y = age, by.x = "区名", by.y = "区", all = TRUE)

生活保護データを追加する

今の市長は生活保護に厳しいと言われているのでそのデータでも分析してみます。

利用データ

http://www.city.osaka.lg.jp/fukushi/page/0000086901.html

区     世帯数    人員    保護率(‰)
北区    2,175    2,598    21.4
都島区    2,695    3,345    32.1
福島区    762    939    13.0
此花区    2,104    2,871    43.5
中央区    1,871    2,207    24.5
西区    1,330    1,603    17.6
港区    3,313    4,298    52.5
大正区    2,835    3,856    58.3
天王寺区    1,278    1,596    21.4
浪速区    5,130    6,138    90.3
西淀川区    2,854    3,775    39.3
淀川区    5,165    6,610    37.9
東淀川区    8,025    10,993    62.8
東成区    2,990    3,781    47.3
生野区    7,462    9,330    72.2
旭区    3,648    4,743    52.5
城東区    4,198    5,500    33.3
鶴見区    2,102    3,126    27.9
阿倍野区    2,640    3,277    30.1
住之江区    4,891    6,957    56.5
住吉区    7,392    9,926    64.2
東住吉区    6,751    8,588    66.7
平野区    9,535    13,738    69.9
西成区    25,293    27,793    235.6

Rプログラム

保護人員数と有権者数で保護率を算出します。そして結合します。

#
# 各区の生活保護データを読む
# http://www.city.osaka.lg.jp/fukushi/page/0000086901.html

hogo <-read.table("data/hogo.txt",head=T)
names(hogo) <- c("区","保護世帯数", "保護人員数", "保護率")
hogo <- hogo[,1:4]

#カンマを削除し、数値データに変換する
hogo$保護世帯数 <- as.numeric(gsub(",","",hogo$保護世帯数))
hogo$保護人員数 <- as.numeric(gsub(",","",hogo$保護人員数))
hogo$保護率 <- as.numeric(gsub(",","",hogo$保護率))

#これまでのデータフレームにマージする
vote <- merge(x = vote, y = hogo[,c(1,3)], by.x = "区名", by.y = "区", all = TRUE)

vote <- transform(vote,
                   保護率 = (vote$保護人員数 / vote$有権者数) * 100)

人口の統計データを追加する

利用データ

人口に関するデータを以下のサイトから取り出します。

http://www.city.osaka.lg.jp/shimin/cmsfiles/contents/0000130/130263/shiryou05-1.pdf

区名 世帯数 総数 男 女 1世帯あたり人員 人口密度 面積
北区 59,377 105,204 50,937 54,267 1.77 10,184 10.33
都島区 48,769 102,062 49,720 52,342 2.09 16,870 6.05
福島区 31,819 63,670 30,271 33,399 2.00 13,634 4.67
此花区 29,142 64,914 31,518 33,396 2.23 3,997 16.24
中央区 45,349 73,259 34,131 39,128 1.62 8,250 8.88
西区 46,431 78,342 37,180 41,162 1.69 15,066 5.20
港区 39,255 83,796 40,969 42,827 2.13 10,607 7.90
大正区 31,115 71,433 35,170 36,263 2.30 7,575 9.43
天王寺区 32,838 66,772 31,019 35,753 2.03 13,911 4.80
浪速区 37,432 57,936 29,911 28,025 1.55 13,258 4.37
西淀川区 41,957 96,142 47,550 48,592 2.29 6,756 14.23
淀川区 88,844 170,949 84,794 86,155 1.92 13,524 12.64
東淀川区 91,973 177,952 88,643 89,309 1.93 13,430 13.25
東成区 37,714 78,951 37,664 41,287 2.09 17,352 4.55
生野区 62,669 134,988 64,514 70,474 2.15 16,108 8.38
旭区 44,188 93,732 44,900 48,832 2.12 14,878 6.30
城東区 74,931 164,824 78,909 85,915 2.20 19,575 8.42
鶴見区 44,677 110,148 53,097 57,051 2.47 13,499 8.16
阿倍野区 48,934 107,779 50,063 57,716 2.20 17,993 5.99
住之江区 55,758 127,892 61,456 66,436 2.29 6,158 20.77
住吉区 73,491 157,085 73,780 83,305 2.14 16,819 9.34
東住吉区 61,637 133,985 63,679 70,306 2.17 13,742 9.75
平野区 86,791 200,483 95,527 104,956 2.31 13,103 15.30
西成区 74,297 129,801 76,573 53,228 1.75 17,660 7.35

Rプログラム

同様に男女で賛成、反対の票と関係があるかを分析するために男女比率を求めます。あと、1世帯あたりの人員数、人口密度も分析に利用するので、これらのデータをこれまでのデータにマージします。

# 人口の統計データをマージする
#http://www.city.osaka.lg.jp/shimin/cmsfiles/contents/0000130/130263/shiryou05-1.pdf

# 遅まきながら、数値データからカンマを取り去って数値化する関数を追加する
to.numeric <- function(str) {
  return (as.numeric(gsub(",","",str)))
}
city <- read.table("data/city.dat",header=T)

city$世帯数 = to.numeric(city$世帯数)
city$総数 = to.numeric(city$総数)
city$= to.numeric(city$)
city$= to.numeric(city$)
city$1世帯あたり人員 = to.numeric(city$1世帯あたり人員)
city$人口密度 = to.numeric(city$人口密度)
city$面積 = to.numeric(city$面積)

city <- transform(city,
                   男性比率 = (city$/city$総数) * 100)
city <- city[,c(1,3,6,7,9)]

vote <- merge(x = vote, y = city, by.x = "区名", by.y = "区名", all = TRUE)

収入のデータを追加する

利用データ

大阪府の年収1000万円世帯比率と平均年収(2014/6/23記事)というのがあるのでこのデータを利用します。 http://media.yucasee.jp/posts/index/14177/2

区名 平均年収 高額年収比率
天王寺区 509万円 9.85%
福島区 455万円 5.17%
西区 451万円 5.94%
都島区 443万円 6.46%
鶴見区 443万円 4.39%
旭区 441万円 6.76%
西淀川区 436万円 3.81%
北区 433万円 4.96%
阿倍野区 426万円 9.40%
淀川区 426万円 4.76%
中央区 423万円 5.05%
城東区 423万円 5.05%
東成区 416万円 5.19%
住之江区 411万円 4.77%
東住吉区 402万円 5.40%
住吉区 393万円 4.14%
港区 389万円 3.26%
大正区 382万円 3.27%
東淀川区 371万円 3.09%
浪速区 369万円 4.12%
平野区 366万円 3.22%
此花区 365万円 2.93%
生野区 356万円 3.31%
西成区 266万円 1.13%

Rプログラム

平均収入と高額年収比率を分析で利用するために追加します。

income <- read.table("data/income.dat",stringsAsFactor=FALSE,header=T)
income$平均年収 <- to.numeric(substr(income$平均年収,1,nchar(income$平均年収)-2))
income$高額年収比率 <- to.numeric(substr(income$高額年収比率,1,nchar(income$高額年収比率)-1))

vote <- merge(x = vote, y = income, by.x = "区名", by.y = "区名", all = TRUE)

利用するデータを個別にグラフ化する

利用するデータを視覚化します。分かりやすくするために順番にソートしてから表示します。

反対票 - 賛成票

x <- vote[with(vote,order(-vote$)),] 
barplot(x$, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,main='差')

R1.png

平野区住吉区、旭区が反対票が多く、北区、淀川区、西区が賛成票が多いです。

反対票率

x <- vote[with(vote,order(-vote$反対率)),] 
barplot(x$反対率, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,main='反対率')

R2.png

有権者数で割って率に直すと、反対は大正区平野区、旭区になり、賛成は北区、西区、福島区となります。

保護率

x <- vote[with(vote,order(-vote$保護率)),] 
barplot(x$保護率, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,main='保護率')

R3.png

生活保護率は圧倒的に西成区が多く、浪速区生野区平野区になります。 少ないのは福島区、西区、北区です。

投票率

x <- vote[with(vote,order(-vote$投票率)),] 
barplot(x$投票率, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,xlab='区',ylab='投票率',main='投票率')

R4.png

投票率はさほど大きな差は見られませんが、阿倍野区天王寺区城東区が高く、浪速区、西成区、東淀川区が低いです。

平均年齢

x <- vote[with(vote,order(-vote$平均年齢)),]
barplot(x$平均年齢, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,xlab='区',ylab='平均年齢',main='平均年齢')

R5.png

平均年齢は西成区が突出して高く、そのあとは生野区、旭区、大正区が続きます。若いのは西区、鶴見区天王寺区です。

年齢65才以上の人口

x <- vote[with(vote,order(-vote$年齢65才以上)),]
barplot(x$年齢65才以上, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,xlab='区',ylab='年齢65才以上',main='年齢65才以上')

R6.png

平均年齢よりも65才以上の数には差が見られます。平野区、西成区、住吉区でこの年齢層の数が多いです。浪速区、西区、天王寺区は少ないです。

1世帯あたりの人員数

x <- vote[with(vote,order(-vote$1世帯あたり人員)),]
barplot(x$1世帯あたり人員, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,xlab='区',ylab='1世帯あたり人員',main='1世帯あたり人員')

R7.png

世帯あたりの人員数は鶴見区平野区大正区が多いです。少ないのは浪速区中央区、西区です。

人口密度

x <- vote[with(vote,order(-vote$人口密度)),] 
barplot(x$人口密度, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,xlab='区',ylab='人口密度',main='人口密度')

R8.png

人口密度は城東区阿倍野区、西成区が高く、此花区住之江区西淀川区が低いです。

男性比率

x <- vote[with(vote,order(-vote$男性比率)),] 
barplot(x$男性比率, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,xlab='区',ylab='男性比率',main='男性比率')

R9.png

こちらは西成区、浪速区東淀川区が高いですが、東淀川区以降はさほど変わりません。低いのは阿倍野区天王寺区中央区です。

平均年収

x <- vote[with(vote,order(-vote$平均年収)),] 
barplot(x$平均年収, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,xlab='区',ylab='平均年収',main='平均年収')

R10.png

平均年収の突出しているのは天王寺区でその後、福島区、西区が続きます。 逆に低いのは西成区、生野区此花区です。

年収1000万以上の高額年収比率

x <- vote[with(vote,order(-vote$高額年収比率)),] 
barplot(x$高額年収比率, names.arg = x[,1],
        col = c("#eeeeee"), beside = TRUE,las = 2,xlab='区',ylab='高額年収比率',main='高額平均比率')

R11.png

天王寺区阿倍野区が突出しており、旭区が続きます。低いのは西成区が抜けており、此花区東淀川区になります。

相関を計算してグラフ化する

これらのデータから相関のグラフを描きます。相関はcor(x,y)で求めることが出来ます。相関は一般的に0.7以上が強い相関、0.4以上は相関がある、0.2以上で弱い相関関係となります。

parで3 x 3のプロット領域を確保し、その中に9個の相関グラフを描きます。

par(mfrow=c(3,3)) 

# 1. 反対率と平均年齢の相関グラフを描く

x <- vote$反対率
y <- vote$平均年齢
plot(x, y,xlab='反対率',ylab='平均年齢',pch=16, main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))


# 2. 反対率と65才以上の比率の相関グラフを描く

x <- vote$反対率
y <- vote$年齢65才以上/vote$総数

plot(x, y,xlab='反対率',ylab='年齢65才以上',pch=16, main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))


# 3. 反対率と平均年齢の相関グラフを描く

x <- vote$反対率
y <- vote$保護率
plot(x, y, xlab='反対率',ylab='保護率',pch=16, main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))

# 4. 反対率と生活保護率の相関グラフを描く

x <- vote$反対率
y <- vote$投票率
plot(x, y, pch=16, xlab='反対率',ylab='投票率',main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))

# 5. 反対率と世帯あたりの人員数の相関グラフを描く

x <- vote$反対率
y <- vote$1世帯あたり人員
plot(x, y, pch=16, xlab='反対率',ylab='1世帯あたり人員',main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))

# 6. 反対率と人口密度の相関グラフを描く

x <- vote$反対率
y <- vote$人口密度
plot(x, y, pch=16, xlab='反対率',ylab='人口密度',main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))

# 7. 反対率と男性比率の相関グラフを描く

x <- vote$反対率
y <- vote$男性比率
plot(x, y, pch=16, xlab='反対率',ylab='男性比率',main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))

# 8. 反対率と平均年収の相関グラフを描く

x <- vote$反対率
y <- vote$平均年収
plot(x, y, pch=16, xlab='反対率',ylab='平均年収',main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))

# 9.反対率と高額年収比率(年収1000万円以上の割合)の相関グラフを描く

x <- vote$反対率
y <- vote$高額年収比率
plot(x, y, pch=16, xlab='反対率',ylab='高額年収比率',main=sprintf("相関係数 = %5.3f",cor(x,y))); abline(lm(y ~ x))

R12.png

年齢65才以上の人口/総人口つまり年齢65才以上の占める割合の多い区で反対票が多いことが分かりました。この相関係数は0.7近いもので強い相関が認められます。

つぎに家族の人員構成も0.636とそれなりに強い相関があることにあります。大きな家族を持つ区ほど反対の割合が多いことになるということです。

平均年齢と反対率もそれなりの相関をもつことが分かりました。 その後、保護率、投票率が続きます。

逆相関が見られるのは平均年収です。つまり年収が高い区ほど賛成に投じた割合が高いのです。

おわりに

今回ははじめてRを使って実際のデータの分析を行いました。統計の初学者でRもはじめたばかりですので、分析結果にはおかしいところがあるかも知れません。でも興味のある事象に関して自分でデータを収集して実際に分析を行うことは好奇心がそそられます。また、実践力の観点でもプラスになるかと思います。今後もこのような取り組みを行なって行きたいと思います。