教育データ分析入門 1(第4回)2

  • 4.2 変数とデータの型
  • 4.3 データ構造
    • 4.3.1 タプル
    • 4.3.2 セット
    • 4.3.3 ディクショナリ
  • 4.4 リストで利用する関数
    • 4.4.1 enumerate()
    • 4.4.2 range()
    • 4.4.3 map()
    • 4.4.4 リスト内包表記
  • 練習問題

4.2 変数とデータの型¶

  • 多くのプログラミング言語では、変数を使用する前に宣言する必要があり、データの型を指定しなければならないが、Pythonにそのような制約はない。
In [1]:
#変数aに整数の2を代入
a = 2

#変数bに整数の5を代入
b = 5

#変数cにaとbを足したものを代入
c = a + b    

#変数dに少数点以下を含む数値を代入
d = 1.05

#変数eに文字列”Noel”を代入
e = "Noel"

#変数aの型を出力
type(a)        
Out[1]:
int

データの型が異なると演算の意味も異なる。

In [2]:
x = '1'
y = "6"
z = x + y
z
# 文字列の足し算
Out[2]:
'16'

算術演算

In [3]:
a += b         # aとbを足した結果をaに代入
a -= b         # aからbをひいた結果をaに代入
a *= b         # aにbをかけけた結果をaに代入
a /= b          # aをbでわった結果をaに代入
a **= b         # aのb乗をaに代入

4.3 データ構造¶

4.3.1 タプル¶

  • タプルとは()で括った構造。リストと似ているが、1度作ったタプルは変更できない。
In [4]:
T = (1,2,3,4,5)  
In [5]:
# これはエラー
T.append(6)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
Cell In[5], line 2
      1 # これはエラー
----> 2 T.append(6)

AttributeError: 'tuple' object has no attribute 'append'

4.3.2 セット¶

  • 順番が保持さない、重複要素が削除されるリスト
In [6]:
S = set([1,2,2,2,4,4,5])
S
Out[6]:
{1, 2, 4, 5}
In [7]:
# 要素を追加する場合
S.add(1)
S
Out[7]:
{1, 2, 4, 5}

4.3.3 ディクショナリ¶

  • ひとつの要素にキーと値がある。
  • 順番が保持されない。
In [8]:
# ディクショナリの生成
D = {"S001":25,"S002":40,"S003":50}
In [9]:
# 値の取り出し
D["S002"]
Out[9]:
40
In [10]:
# 要素の追加
D["S004"] = 90
In [11]:
# keyの取得
D.keys()
Out[11]:
dict_keys(['S001', 'S002', 'S003', 'S004'])
In [12]:
# 値の取得
D.values()
Out[12]:
dict_values([25, 40, 50, 90])
In [13]:
# 以下のようにすると全ての値が取得できる

for i in D.keys():
    print(D[i])
25
40
50
90
In [14]:
# 両方同時に
for k,v in D.items():
    print(k,v)

# 順番は保持されない
S001 25
S002 40
S003 50
S004 90

ディクショナリのメソッド

メソッド 意味
D.update({"S005":20,"S006":10}) ディクショナリとディクショナリを連結
D.pop("S001") キーを指定して要素を削除。返ってくる値は削除した要素の値
D.clear() 全ての要素の削除
D.has_key("S002") 指定したキーがあるかどうか。返ってくる値はTrue/False

4.4 リストで利用する関数¶

4.4.1 enumerate()¶

In [15]:
# enumerate()m
# 要素の順番と値を返す

L = [10,25,30]

for i, v in enumerate(L):
    print(i,v)
0 10
1 25
2 30

4.4.2 range()¶

In [16]:
# range関数
#0からn-1の整数列
r = range(5)
list(r)
Out[16]:
[0, 1, 2, 3, 4]
In [17]:
# nからm-1の整数列
r = range(5,10)
list(r)
Out[17]:
[5, 6, 7, 8, 9]
In [18]:
# nからm-1の公差lの整数列
r = range(1,20,3)
list(r)
Out[18]:
[1, 4, 7, 10, 13, 16, 19]
In [19]:
L = []
for i in range(101):
    L.append(i)
In [20]:
print(L)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99, 100]
In [21]:
L = ["pen","apple","grape"]

for i in range(len(L)):
    print(L[i])
pen
apple
grape

4.4.3 map()¶

  • リストの要素がリストの場合、二重for文を用いて処理をしていたが、map()を利用するとより短くかける。
In [22]:
L = [[10,44,27,32,56,72,34,90],[19,10,89,61,25,66]]

# 2つの組の平均点の計算

for i in L:
    n = 0
    for j in i:
        n += j
    print(n/len(i))
45.625
45.0
  • map()は第一引数に関数、第二引数にリスト(のようなもの)を指定する。
  • 第二引数の各要素に対して第一引数の関数を適用する。
In [23]:
import numpy as np

A = list(map(np.average,L))
A
Out[23]:
[np.float64(45.625), np.float64(45.0)]

4.4.4 リスト内包表記¶

In [24]:
X = [48,60,29,80,77]

x_m = np.average(X)
x_std = np.std(X)

X_T = []
for i in X:
    X_T.append((i-x_m)/x_std)

X_T
Out[24]:
[np.float64(-0.5713086317569043),
 np.float64(0.06347873686187842),
 np.float64(-1.576388632069977),
 np.float64(1.1214576845598496),
 np.float64(0.9627608424051539)]
  • 上のようにfor文を用いた処理の結果を保存するために空のリストを処理前に用意をしていたが、以下のようにリストの中にfor文を書くことが可能である。
  • これによってコードが短くなる。
  • しかし、複雑な処理になると分かりにくくなる。
In [25]:
X_T2 = [(i - np.average(X))/np.std(X) for i in X]
X_T2
Out[25]:
[np.float64(-0.5713086317569043),
 np.float64(0.06347873686187842),
 np.float64(-1.576388632069977),
 np.float64(1.1214576845598496),
 np.float64(0.9627608424051539)]

演習問題¶

../DATA01/options.csvはあるテストの解答データです。正解は以下です。採点をし、各問題の正答率と選択肢の選択率を求めなさい。

ANS = [2,3,4,1,3,3,1,1,4,1,4,1,3,1,2]

In [26]:
import pandas as pd

df = pd.read_csv("../DATA01/options.csv",index_col=0)
df.head()
Out[26]:
Q01 Q02 Q03 Q04 Q05 Q06 Q07 Q08 Q09 Q10 Q11 Q12 Q13 Q14 Q15
S001 2 3 4 1 3 3 1 1 4 1 1 1 3 2 3
S002 2 3 4 1 3 3 1 1 4 1 1 1 3 3 2
S003 2 4 4 1 3 3 1 1 4 3 4 4 3 4 4
S004 2 4 4 1 3 3 1 1 1 1 3 1 1 1 1
S005 2 3 4 1 3 3 1 1 4 1 4 3 1 3 2
In [27]:
ID = df.index
dft = df.T
ANS = [2,3,4,1,3,3,1,1,4,1,4,1,3,1,2]

# 採点
M = []

for i in ID:
    tmp = []
    for j,k in zip(ANS,dft[i]):
        if j == k:
            tmp.append(1)
        else:
            tmp.append(0)
    M.append(tmp)

df_mrkd = pd.DataFrame(index = df.columns)


for i,j in zip(ID,M):
    df_mrkd[i] = j

df_mrkd2 = df_mrkd.T

df_mrkd2.head()
Out[27]:
Q01 Q02 Q03 Q04 Q05 Q06 Q07 Q08 Q09 Q10 Q11 Q12 Q13 Q14 Q15
S001 1 1 1 1 1 1 1 1 1 1 0 1 1 0 0
S002 1 1 1 1 1 1 1 1 1 1 0 1 1 0 1
S003 1 0 1 1 1 1 1 1 1 0 1 0 1 0 0
S004 1 0 1 1 1 1 1 1 0 1 0 1 0 1 0
S005 1 1 1 1 1 1 1 1 1 1 1 0 0 0 1
In [28]:
# 選択肢の選択率
N = []

for i in df.columns:
    op1 = len(df[df[i] == 1])/11
    op2 = len(df[df[i] == 2])/11
    op3 = len(df[df[i] == 3])/11
    op4 = len(df[df[i] == 4])/11
    N.append([op1,op2,op3,op4])
In [29]:
df_op = pd.DataFrame(index = [1,2,3,4])

for i,j in zip(df.columns,N):
    df_op[i] = j
In [30]:
df_op2 = df_op.T
df_op2["ANS"] = ANS
df_op2
Out[30]:
1 2 3 4 ANS
Q01 0.000000 1.000000 0.000000 0.000000 2
Q02 0.000000 0.090909 0.636364 0.272727 3
Q03 0.000000 0.000000 0.000000 1.000000 4
Q04 1.000000 0.000000 0.000000 0.000000 1
Q05 0.000000 0.000000 1.000000 0.000000 3
Q06 0.000000 0.000000 1.000000 0.000000 3
Q07 1.000000 0.000000 0.000000 0.000000 1
Q08 1.000000 0.000000 0.000000 0.000000 1
Q09 0.181818 0.000000 0.090909 0.727273 4
Q10 0.636364 0.000000 0.272727 0.090909 1
Q11 0.272727 0.000000 0.090909 0.636364 4
Q12 0.818182 0.000000 0.090909 0.090909 1
Q13 0.181818 0.000000 0.545455 0.272727 3
Q14 0.272727 0.181818 0.272727 0.272727 1
Q15 0.272727 0.545455 0.090909 0.090909 2

練習問題¶

6人が最初に1000円持っていて、0番から5番までの番号が付いています。サイコロを2個振り、最初のサイコロの出た目の番号の人が2番目のサイコロの出た目の番号の人に10円を支払います。支払う人の所持金が0円の場合は支払う必要はありません。このゲームをたくさん(例えば100000回とか)繰り返すとたくさんお金を持っている人とほとんど持っていない人に別れてしまうことが知られています。

ディクショナリ、range()、for文を用いて、実際に調べて見ましょう。

0から5のランダムな数字は以下で発生することができます。

In [31]:
from numpy.random import randint
randint(6)
Out[31]:
2