[Python] pnadasの基本的な使いかた

pandas の基本的な使い方、備忘録です。

公式

pandas: powerful Python data analysis toolkit

jupyter notebook を使っている時は、メソッドにカーソルを置いて、Shift + Tab でそのメソッドの説明が読めます。

DataFrameの生成と操作

CSVファイル

読み込み

pandas.read_csv

windows で日本語のファイルを扱う場合は、encoding='cp932'を引数にします。

>>> import pandas as pd
>>> df = pd.read_csv('test_load.csv') 

保存

pandas.DataFrame.to_csv

>>> df.to_csv('test_save.csv', index = False)

表の作成

ほとんどないですが、スクラッチからDataFrameを生成する場合です。

>>> df_grade = pd.DataFrame(data={'name':['Taro', 'Jiro', 'Saburo'], 'age':[5, 10, 15], 'grade':[50, 80, 70]})
>>> df_grade
     name  age  grade
0    Taro    5     50
1    Jiro   10     80
2  Saburo   15     70

列の取り出し

Series として取り出し

>>> df_grade['name']
0      Taro
1      Jiro
2    Saburo
Name: name, dtype: object

DataFrame として一列取り出し

>>> df_grade[['name']]
     name
0    Taro
1    Jiro
2  Saburo

DataFrame として複数列取り出し

>>> df_grade[['name', "age"]]
     name  age
0    Taro    5
1    Jiro   10
2  Saburo   15

行の取り出し

>>> df_grade[1:3]
     name  age  grade
1    Jiro   10     80
2  Saburo   15     70

行のフィルタリング

boolean の配列を作成し、ture の行のみ抽出することができます。

>>> arr_bool = df_grade["grade"] >= 70
>>> arr_bool
0    False
1     True
2     True
Name: grade, dtype: bool
>>> df_grade[arr_bool]
     name  age  grade
1    Jiro   10     80
2  Saburo   15     70

上の操作は1行で行えます。

>>> df_grade[df_grade["grade"] >= 70]
     name  age  grade
1    Jiro   10     80
2  Saburo   15     70

複数の条件で抜き出すこともできます。

# df[(条件) & (条件)]
# df[(条件) | (条件)]
>>> df_grade[(df_grade['grade'] >= 70) & (df_grade['age']>10)] 
     name  age  grade
2  Saburo   15     70

以下の関数も同じように行のフィルタリングに使うことができます。

pandas.DataFrame.query

loc及びilocよる取り出し

location や index location の略だと思います。

pandas.DataFrame.loc

pandas.DataFrame.iloc

>>> df_grade.loc[:,'name']
0      Taro
1      Jiro
2    Saburo
Name: name, dtype: object
>>> df_grade.loc[:,['name', 'age']]
     name  age
0    Taro    5
1    Jiro   10
2  Saburo   15
>>> df_grade.iloc[1:3,1:3]
   age  grade
1   10     80
2   15     70

列名の変更

pandas.DataFrame.rename

>>> df_grade.rename(columns={'name': 'first name'}) 
  first name  age  grade
0       Taro    5     50
1       Jiro   10     80
2     Saburo   15     70
>>> df_grade.rename(columns={'name': 'first name', 'age': 'full age'})
  first name  full age  grade
0       Taro         5     50
1       Jiro        10     80
2     Saburo        15     70

ソート

pandas.DataFrame.sort_values

>>> df_grade
     name  age  grade
0    Taro    5     50
1    Jiro   10     80
2  Saburo   15     70
>>> df_grade.sort_values('grade')
     name  age  grade
0    Taro    5     50
2  Saburo   15     70
1    Jiro   10     80

列の追加

>>> df_grade['gender']='m'
>>> df_grade
     name  age  grade gender
0    Taro    5     50      m
1    Jiro   10     80      m
2  Saburo   15     70      m

行の追加

pandas.DataFrame.append

>>> df_grade_f = pd.DataFrame(data={'name':['Hanako', 'Kanako', 'Nanako'], 'age':[8, 12, 16], 'grade':[55, 85, 75], 'gender':['f', 'f', 'f']})     
>>> df_grade_f
     name  age  grade gender
0  Hanako    8     55      f
1  Kanako   12     85      f
2  Nanako   16     75      f
>>> df_grade = df_grade.append(df_grade_f, ignore_index=True) 
>>> df_grade
     name  age  grade gender
0    Taro    5     50      m
1    Jiro   10     80      m
2  Saburo   15     70      m
3  Hanako    8     55      f
4  Kanako   12     85      f
5  Nanako   16     75      f

groupby

SQLのgroupbyと同じような感覚です。

pandas.DataFrame.groupby

集計関数

Aggregation

>>> df_grade[['gender', 'grade']].groupby('gender').mean()      
gender grade
f       71.666667
m       66.666667

ピボットテーブル

pandas.DataFrame.pivot

>>> df_grade.pivot_table(values='grade', index=['gender'], columns=['age'], aggfunc=sum)
age       5     8     10    12    15    16
gender
f        NaN  55.0   NaN  85.0   NaN  75.0
m       50.0   NaN  80.0   NaN  70.0   NaN

テーブルの結合

SQLの join と同じような感覚です。

pandas.DataFrame.merge

>>> print(df)
   user_id      name  score
0        0    tanaka     20
1        1    yamada     40
2        2  takahasi     30
3        3      sato     50

>>> print(df2)
   device_id  user_id weapon
0          0        2  sword
1          1        1  knife
2          2       10  arrow
3          3        5    lod
>>> df.merge(df2, left_on = 'user_id', right_on = 'user_id', how = "inner")
   user_id      name  score  device_id weapon
0        1    yamada     40          1  knife
1        2  takahasi     30          0  sword
>>>

また、キーに複数の列を指定したい場合は、on にキーとする列名のリストを渡します。

同じような関数でjoinもあります。

join は、デフォルトでindexを使ってjoin してくれます。

pandas.DataFrame.join

関数を列に適用

データ例を作成します。

>>> import numpy as np
>>> df_norm_data = pd.DataFrame(data = {'data1': np.random.normal(loc = 2, scale = 4, size = 1000), 'data2': np.random.normal(loc = 5, scale = 3, size = 1000)})
>>> df_norm_data.head(10)
      data1     data2
0  0.526135  4.127409
1 -0.768730  5.385454
2 -0.417630  8.570257
3  0.734564  4.505055
4 -3.589744  6.321659
5  0.140246 -2.551671
6  2.430789  5.759566
7 -5.400427  5.946560
8  5.438419  6.283404
9  5.050853  2.611055

関数を列に適用し、新しい列を作成する、または既存の列を変更することができます。

pandas.DataFrame.apply

>>> df_norm_data['data1'] = df_norm_data['data1'].apply(round, 'data1')
>>> df_norm_data.head()
   data1     data2
0      1  4.127409
1     -1  5.385454
2      0  8.570257
3      1  4.505055
4     -4  6.321659

統計分析

基本的な統計

ささっと基本的な統計を確認します。

pandas.DataFrame.describe

>>> df_norm_data.describe()
             data1        data2
count  1000.000000  1000.000000
mean      1.882876     4.891268
std       4.027441     3.085061
min      -9.993403    -4.048162
25%      -0.916317     2.745270
50%       1.850233     5.043616
75%       4.579636     6.874027
max      15.382466    14.683068

列数

>>> len(df_norm_data.columns) 
2
>>> df_norm_data.shape[1]
2

列が省略されてしまう時、表示する列数を指定します。

>>> pd.set_option('display.max_columns', 50)

行数

>>> len(df_norm_data)
1000
>>> df_norm_data.shape[0]
1000

もうちょっと行を見たいとき、見たくないときは、表示する行数を指定します。

>>> pd.set_option('display.max_rows', 50)

データの可視化

さくっとグラフにする。

pandas.DataFrame.plot

また、それぞれメソッドが準備されている場合もあります。

ちゃんとしたい時は、素直に matplotlib からいじった方が結局は仕事が速いです。

ヒストグラム

pandas.DataFrame.hist

pandas.DataFrame.plot.hist

>>> data1.hist();
array([[<matplotlib.axes._subplots.AxesSubplot object at 0x0000017318A22400>]],
      dtype=object)

散布図

pandas.DataFrame.plot.scatter

>>> df_norm_data.plot.scatter(x = 'data1', y = 'data2'); 
<atplotlib.axes._subplots.AxesSubplot object at 0x000001731685F780>

棒グラフ

pandas.DataFrame.plot.bar

>>> df_grade.plot.bar()
<matplotlib.axes._subplots.AxesSubplot object at 0x00000173168A6080>