へっぽこ研究者、立ち上がるってよ

あなたを応援するブログ

松尾研究室データサイエンティスト育成講座、第二章後半の解答

松尾研究室データサイエンティスト育成講座の練習問題、第二章後半の解答の解答です。

今までの解答は以下のまとめページを参照ください。

www.oyakuni.com

2.1.3 Pandasの基礎

練習問題1

以下のデータに対して、Moneyが500以上の人を絞り込んで、レコードを表示させてください。

from pandas import Series,DataFrame
import pandas as pd
<200b>
attri_data1 = {'ID':['1','2','3','4','5']
        ,'sex':['F','F','M','M','F']
        ,'Money':[1000,2000,500,300,700]
        ,'name':['Saito','Horie','Kondo','Kawada','Matsubara']}
<200b>
attri_data_frame1 = DataFrame(attri_data1)

#ここから解答

#Money500以上に絞り込む
attri_data_frame2=attri_data_frame1[attri_data_frame1["Money"]>=500]
print(attri_data_frame2)

結果

  ID sex  Money       name
0  1   F   1000      Saito
1  2   F   2000      Horie
2  3   M    500      Kondo
4  5   F    700  Matsubara

練習問題2

上記のデータに対して、男女別(MF別)の平均Moneyを求めてください。

attri_data_frame2.groupby("sex")["Money"].mean()

結果

sex
F    1233.333333
M     500.000000
Name: Money, dtype: float64

練習問題3

上記のデータに対して、以下のデータの同じIDの人をキーとして、データをマージしてください。そして、MoneyとMathとEnglishの平均を求めてください。

attri_data2 = {'ID':['3','4','7']
        ,'Math':[60,30,40]
        ,'English':[80,20,30]}

attri_data_frame2 = DataFrame(attri_data2)

#ここから解答
attri_data_frame3=pd.merge(attri_data_frame1,attri_data_frame2)
#numeric_only=Trueとすることでデータ型がfloat,int,boolのカラムのみで平均を計算
attri_data_frame3.mean(numeric_only=True)

結果

Money      400.0
Math        45.0
English     50.0
dtype: float64

2.1.4 Matplotlibの基礎

練習問題1

import matplotlib.pyplot as plt
import matplotlib as mpl
import seaborn as sns
%matplotlib inline

#配列の作成
x=np.arange(-10,11)
y=5*x+3

plt.plot(x,y)
plt.grid(True)

結果

f:id:do1208:20190526105818p:plain

練習問題2

先ほどのsin関数に加えて、cos関数のグラフも書いてください。

# 先ほどのsin関数を表示

# 2行2列のグラフの1つ目
plt.subplot(2,2,1)
x = np.linspace(-10, 10,100)
plt.plot(x, np.sin(x)) 

# 2行2列のグラフの2つ目
plt.subplot(2,2,2)
y = np.linspace(-10, 10,100)
plt.plot(y, np.sin(2*y)) 

plt.grid(True)

#ここから回答
# 2行2列のグラフの3つ目
plt.subplot(2,2,3)
z = np.linspace(-10,10,100)
plt.plot(z, np.cos(z))

# 2行2列のグラフの4つ目
plt.subplot(2,2,4)
a = np.linspace(-10,10,100)
plt.plot(a, np.cos(2*a))

結果

f:id:do1208:20190526110456p:plain

練習問題3

0から1の値をとる一様乱数を1000個、2組発生させて、それぞれのヒストグラムを書いてみましょう。結果はどうなっていますか。また、1000個だけではなく、100個や10000個などでも実施してみましょう。何かわかることはありますか。なお、それぞれのヒストグラムは別のグラフに表示するために、plt.subplotを利用してください。なお、一様乱数とは、ある数から数まで等確率で発生する乱数のことをいい、np.random.uniformを使ってください。

random.seed(10)
norm_random_sample_data1=[random.uniform(0,1,1000)]

random.seed(11)
norm_random_sample_data2=[random.uniform(0,1,1000)]

plt.subplot(3,2,1)
plt.hist(norm_random_sample_data1,range=(0,1))
plt.grid(True)

plt.subplot(3,2,2)
plt.hist(norm_random_sample_data2,range=(0,1))
plt.grid(True)

random.seed(10)
norm_random_sample_data1=[random.uniform(0,1,100)]

random.seed(11)
norm_random_sample_data2=[random.uniform(0,1,100)]

plt.subplot(3,2,3)
plt.hist(norm_random_sample_data1,range=(0,1))
plt.grid(True)

plt.subplot(3,2,4)
plt.hist(norm_random_sample_data2,range=(0,1))
plt.grid(True)

random.seed(10)
norm_random_sample_data1=[random.uniform(0,1,10000)]

random.seed(11)
norm_random_sample_data2=[random.uniform(0,1,10000)]

plt.subplot(3,2,5)
plt.hist(norm_random_sample_data1,range=(0,1))
plt.grid(True)

plt.subplot(3,2,6)
plt.hist(norm_random_sample_data2,range=(0,1))
plt.grid(True)

結果

f:id:do1208:20190526111306p:plain 数が増えるとばらつきが減ることが分かる。

2.2総合問題

乱数を発生させる方法を使って、円周率を求めるプログラムを作成してみましょう。(なお、このアプローチをモンテカルロ法といいます)

(1)一様分布に従う乱数を2組発生させて、それぞれ10,000個の一様乱数を作ってみましょう。なお、一様乱数とは、ある数から数まで等確率で発生する乱数のことをいい、np.random.uniformを使います。使い方としては、0から1までの数を10個発生させる場合は、np.random.uniform(0.0, 1.0, 10)とします。

(2)x−y軸を使った中心(0,0)、半径1の円と、長さ1の正方形を考え、円の面積は 𝜋 となり、正方形の面積は1となります。ここで先ほどのxとyの組み合わせの乱数10000個のうち、円の内部に入る点は何組あるでしょうか。ここで、円の内部に入るとは、x−y座標の原点から点 (x, y) のベクトルの長さを求め、それが1より小さくなる場合を判定基準とします。なお、その長さを求めるために、ユークリッドノルム( 𝑥2+𝑦2⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯⎯√ )を使い、 math.hypot(x,y)で計算できます。(さらに、余裕があれば、円の中に入ったxとyの組み合わせと外に出たxとyの組み合わせをプロットして図にしてみましょう。)

#問一
import numpy as np
import numpy.random as random
import matplotlib.pyplot as plt
from pandas import Series,DataFrame
import pandas as pd
import math

random.seed(20)
ransu1=random.uniform(-1.0,1.0,1000)

random.seed(21)
ransu2=random.uniform(-1.0,1.0,1000)

#問2
count = 0
over =0
for x,y in zip(ransu1,ransu2):
    if math.hypot(x,y)<1:
        count += + 1
        plt.plot(x,y,"o") 
    else:
        over += 1

#個数を表示        
print("内部に入っている組数:",count)
print("内部に入っていない組数:",over)

結果

内部に入っている組数: 774
内部に入っていない組数: 226

f:id:do1208:20190526112424p:plain

(3)半径1の1/4の円の面積と長さ1の長方形の面積の比は、 𝜋/4:1 となりますので、これと先ほどの結果を利用して、円周率を求めてみましょう。

#shape関数で配列の大きさを取得
pai=4*(count/(ransu1.shape[0]))
print("円周率:",pai)

結果

円周率: 3.096