Pandasは内部でNumPyを利用しており、二次元配列を「テーブル」として扱えるように機能を追加しています。ここでは、DataFrameの扱い方を中心にPandasの基本的な使い方を確認します。
インストール
pipenv
を利用している場合、以下のようにインストールします。
$ pipenv install pandas
プログラムから利用するにはimportが必要です。
慣習的にpandasをimportするときは pd
と別名をつけます。
import pandas as pd
import numpy as np
df = pd.DataFrame(
np.random.randn(6, 4),
index=list('ABCDEF'),
columns=['col1', 'col2', 'col3', 'col4']
)
print(df)
col1 col2 col3 col4
A -1.801003 0.567649 -1.500904 -0.239381
B -0.719186 -0.966656 1.726989 0.906241
C 0.242600 2.890311 -0.321324 -0.457311
D -0.999545 0.845195 -0.830634 0.332034
E 0.430159 1.964199 0.162262 0.596390
F 0.145257 -0.418800 0.653118 1.253135
Series|一次元配列
Seriesは、一次元配列
のデータ構造を管理します。
オブジェクト生成方法
class pandas.Series(data=None, index=None, dtype=None, name=None, copy=False, fastpath=False)
以下、生成例です。
>>> pd.Series([54, 21, 94, 74])
0 54
1 21
2 94
3 74
dtype: int64
NumPyの ndarray
とは異なり、indexを数値以外にすることもできます。
>>> pd.Series([54, 21, 94, 74], index=['A', 'B', 'C', 'D'])
A 54
B 21
C 94
D 74
dtype: int64
dictionaryを渡す形式でも利用できます。
>>> dict = {'A': 54, 'B': 21, 'C': 94, 'D': 74}
>>> pd.Series(dict)
A 54
B 21
C 94
D 74
dtype: int64
Pandasの date_rangeメソッド
を利用すると、連続した日付データを生成できます。
生成した日付データからSeriesオブジェクトを生成することもできます。
>>> date = pd.date_range('20180101', periods=4)
>>> date
DatetimeIndex(['2018-01-01', '2018-01-02', '2018-01-03', '2018-01-04'], dtype='datetime64[ns]', freq='D')
>>>
>>> pd.Series(date)
0 2018-01-01
1 2018-01-02
2 2018-01-03
3 2018-01-04
dtype: datetime64[ns]
参考
- http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.html
- http://pandas.pydata.org/pandas-docs/stable/dsintro.html#series
DataFrame|二次元配列、テーブル
DataFrameは、 二次元配列
のデータ構造を管理します。単純な二次元配列のデータではなく、column(列)
index(行)
をラベル付けできるテーブル形式のデータ構造になります。
オブジェクト生成方法
class pandas.DataFrame(data=None, index=None, columns=None, dtype=None, copy=False)
以下、生成例です。
>>> pd.DataFrame([[180, 68, 1, '19801122'], [164, 54, 2, '19900411']])
0 1 2 3
0 180 68 1 19801122
1 164 54 2 19900411
DataFrameは、複数のSeriesオブジェクトにラベル付けして、まとめて管理することができるデータ構造と考えることができます。身長、体重といったSeries単位でデータを持っているのであれば、以下のように生成できます。
>>> height = pd.Series([180, 164], index=['yamada', 'suzuki'])
>>> weight = pd.Series([68, 54], index=['yamada', 'suzuki'])
>>> sex = pd.Series([1, 2], index=['yamada', 'suzuki'])
>>> birthday = pd.Series(['19801122', '19900411'], index=['yamada', 'suzuki'])
>>>
>>> pd.DataFrame({
... 'height': height,
... 'weight': weight,
... 'sex': sex,
... 'birthday': birthday
... })
height weight sex birthday
yamada 180 68 1 19801122
suzuki 164 54 2 19900411
人物単位でデータを持っているのであれば、以下のように生成できます。
>>> yamada = [180, 68, 1, '19801122']
>>> suzuki = [164, 54, 2, '19900411']
>>>
>>> pd.DataFrame(
... [yamada, suzuki],
... index=['yamada', 'suzuki'],
... columns=['height', 'weight', 'sex', 'birthday'],
... )
height weight sex birthday
yamada 180 68 1 19801122
suzuki 164 54 2 19900411
他にも、read_csv
read_clipboard
pandas.io.sql.read_sql
などを利用してDataFrameオブジェクトを生成することができます。
- read_csv
- csvを読み込みDataFrameオブジェクトを生成
- read_clipboard
- クリップボードに保存されている内容を読み込みDataFrameオブジェクトを生成
- pandas.io.sql.read_sql
- SELECT文の実行結果からDataFrameオブジェクトを生成
主な属性
ndim(次元数)
shape(各次元の配列サイズ)
size(要素数)
などNumPyの ndarray
と同様に利用できます。
Pandasでは加えて、values
columns
index
なども利用できます。
>>> df = pd.DataFrame(
... np.random.randn(6, 4),
... index=list('ABCDEF'),
... columns=['col1', 'col2', 'col3', 'col4']
... )
>>>
>>> df.ndim
2
>>>
>>> df.shape
(6, 4)
>>>
>>> df.size
24
>>>
>>> df.dtypes
col1 float64
col2 float64
col3 float64
col4 float64
dtype: object
>>>
>>> df.values
array([[ 0.86228608, -1.52049619, -0.86636716, 0.14673805],
[ 0.87420066, -0.1262851 , -0.45114235, -0.94013396],
[ 0.39502002, 0.21415237, 0.02878306, 1.11859551],
[-0.57662159, 1.16036366, 1.36461432, -0.53426026],
[-2.1305967 , -0.03367391, -1.88627092, 0.65179348],
[-0.74469153, -0.72749726, 0.08043063, 1.95564312]])
>>>
>>> df.columns
Index(['col1', 'col2', 'col3', 'col4'], dtype='object')
>>>
>>> df.index
Index(['A', 'B', 'C', 'D', 'E', 'F'], dtype='object')
valuesの型はNumPyの ndarray
になります。
>>> df.values.__class__.__name__
'ndarray'
転置行列(行と列を入れ替えた行列)も簡単に生成できます。
>>> df
col1 col2 col3 col4
A 0.862286 -1.520496 -0.866367 0.146738
B 0.874201 -0.126285 -0.451142 -0.940134
C 0.395020 0.214152 0.028783 1.118596
D -0.576622 1.160364 1.364614 -0.534260
E -2.130597 -0.033674 -1.886271 0.651793
F -0.744692 -0.727497 0.080431 1.955643
>>>
>>> df.T
A B C D E F
col1 0.862286 0.874201 0.395020 -0.576622 -2.130597 -0.744692
col2 -1.520496 -0.126285 0.214152 1.160364 -0.033674 -0.727497
col3 -0.866367 -0.451142 0.028783 1.364614 -1.886271 0.080431
col4 0.146738 -0.940134 1.118596 -0.534260 0.651793 1.955643
loc
を利用すると、index、columnの 値
を指定してデータを取得できます。iloc
を利用すると、index、columnの 番号
を指定してデータを取得できます。
>>> df
height weight sex birthday
yamada 180 68 1 19801122
suzuki 172 54 2 19900411
tanaka 170 66 1 19850904
takahashi 149 40 2 19900222
>>>
>>> df.loc['yamada']
height 180
weight 68
sex 1
birthday 19801122
Name: yamada, dtype: object
>>>
>>> df.loc['yamada':'suzuki', 'height':'weight']
height weight
yamada 180 68
suzuki 172 54
>>>
>>> df.loc['yamada':'suzuki', ['height', 'sex']]
height sex
yamada 180 1
suzuki 172 2
>>>
>>> df.iloc[0]
height 180
weight 68
sex 1
birthday 19801122
Name: yamada, dtype: object
>>>
>>> df.iloc[0:2, 0:2]
height weight
yamada 180 68
suzuki 172 54
メソッドで情報確認( info, describe )
infoメソッド
データ構造を確認できます。
>>> df.info()
<class 'pandas.core.frame.DataFrame'>
Index: 6 entries, A to F
Data columns (total 4 columns):
col1 6 non-null float64
col2 6 non-null float64
col3 6 non-null float64
col4 6 non-null float64
dtypes: float64(4)
memory usage: 400.0+ bytes
上記のように、「nullではないデータの数」「変数の型」を確認できます。
describeメソッド
count(総数)
mean(平均)
std(標準偏差)
などの統計量をまとめて確認できます。
>>> df.describe()
col1 col2 col3 col4
count 6.000000 6.000000 6.000000 6.000000
mean -0.220067 -0.172239 -0.288325 0.399729
std 1.166167 0.902502 1.084695 1.070771
min -2.130597 -1.520496 -1.886271 -0.940134
25% -0.702674 -0.577194 -0.762561 -0.364011
50% -0.090801 -0.079980 -0.211180 0.399266
75% 0.745470 0.152196 0.067519 1.001895
max 0.874201 1.160364 1.364614 1.955643
参考
- http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.html
- http://pandas.pydata.org/pandas-docs/stable/dsintro.html#dataframe
DataFrame操作(SQLと比較)
http://pandas.pydata.org/pandas-docs/stable/comparison_with_sql.html でも解説されていますが、DataFrameはテーブル形式のデータ構造なので、SQLのような感覚でデータを扱うことができます。
SELECT
SELECT height, sex
FROM df
LIMIT 3;
>>> df = pd.DataFrame(
... [[180, 68, 1, '19801122'], [172, 54, 2, '19900411'], [170, 66, 1, '19850904'], [149, 40, 2, '19900222']],
... index=['yamada', 'suzuki', 'tanaka', 'takahashi'],
... columns=['height', 'weight', 'sex', 'birthday'],
... )
>>>
>>> df
height weight sex birthday
yamada 180 68 1 19801122
suzuki 172 54 2 19900411
tanaka 170 66 1 19850904
takahashi 149 40 2 19900222
>>>
>>> df[['height', 'sex']].head(3)
height sex
yamada 180 1
suzuki 172 2
tanaka 170 1
列の追加
例として「年齢」を追加してみます。
>>> df
height weight sex birthday
yamada 180 68 1 19801122
suzuki 172 54 2 19900411
tanaka 170 66 1 19850904
takahashi 149 40 2 19900222
>>>
>>>
>>> def getAge(birthday):
... today = int(pd.to_datetime('today').strftime('%Y%m%d'))
... return int((today - int(birthday)) / 10000)
...
>>>
>>> df['age'] = df['birthday'].apply(lambda date: getAge(date))
>>>
>>> df
height weight sex birthday age
yamada 180 68 1 19801122 38
suzuki 172 54 2 19900411 28
tanaka 170 66 1 19850904 33
takahashi 149 40 2 19900222 28
applyメソッド
で日付から年齢を算出する関数を適用しています。
WHERE
条件指定
SELECT *
FROM df
WHERE height > 170 AND sex = 1;
>>> df
height weight sex birthday
yamada 180 68 1 19801122
suzuki 172 54 2 19900411
tanaka 170 66 1 19850904
takahashi 149 40 2 19900222
>>>
>>> df[(df['height'] > 170) & (df['sex'] == 1)]
height weight sex birthday
yamada 180 68 1 19801122
IS NOT NULL
の判定
SELECT *
FROM df
WHERE height IS NOT NULL;
notnaメソッド
を利用します。
>>> df.loc[df['height'] == 172, 'height'] = np.nan
>>>
>>> df
height weight sex birthday
yamada 180.0 68 1 19801122
suzuki NaN 54 2 19900411
tanaka 170.0 66 1 19850904
takahashi 149.0 40 2 19900222
>>>
>>> df[df['height'].notna()]
height weight sex birthday
yamada 180.0 68 1 19801122
tanaka 170.0 66 1 19850904
takahashi 149.0 40 2 19900222
ORDER BY
SELECT *
FROM df
ORDER BY height DESC;
並び替えを変更するには、sort_valuesメソッド
を利用します。
デフォルトは ascending(昇順)
です。降順にするには、ascending
を False
にします。
>>> df
height weight sex birthday
yamada 180.0 68 1 19801122
suzuki NaN 54 2 19900411
tanaka 170.0 66 1 19850904
takahashi 149.0 40 2 19900222
>>>
>>> df.sort_values(by='height', ascending=False)
height weight sex birthday
yamada 180.0 68 1 19801122
tanaka 170.0 66 1 19850904
takahashi 149.0 40 2 19900222
suzuki NaN 54 2 19900411
GROUP BY
例1
SELECT sex, COUNT(*)
FROM df
GROUP BY sex;
>>> df
height weight sex birthday
yamada 180.0 68 1 19801122
suzuki NaN 54 2 19900411
tanaka 170.0 66 1 19850904
takahashi 149.0 40 2 19900222
>>>
>>> df.groupby('sex').size()
sex
1 2
2 2
dtype: int64
例2
SELECT sex, AVG(height), AVG(weight)
FROM tips
GROUP BY sex;
>>> df
height weight sex birthday
yamada 180.0 68 1 19801122
suzuki NaN 54 2 19900411
tanaka 170.0 66 1 19850904
takahashi 149.0 40 2 19900222
>>>
>>> df.groupby('sex').agg({'height': np.mean, 'weight': np.mean})
height weight
sex
1 175.0 67
2 149.0 47
JOIN
下記データを結合してみます。
>>> df1 = pd.DataFrame({'key': ['A', 'B', 'C', 'D'], 'value': np.random.randn(4)})
>>> df2 = pd.DataFrame({'key': ['B', 'B', 'D', 'E'], 'value': np.random.randn(4)})
>>>
>>> df1
key value
0 A -0.533587
1 B -1.784564
2 C 0.712881
3 D -0.665603
>>>
>>> df2
key value
0 B -2.200250
1 B -0.380191
2 D -0.086180
3 E 2.167892
INNER JOIN
SELECT *
FROM df1
INNER JOIN df2
ON df1.key = df2.key;
>>> pd.merge(df1, df2, on='key')
key value_x value_y
0 B -2.140503 -1.273683
1 B -2.140503 0.397336
2 D -0.490544 -0.042907
LEFT OUTER JOIN
SELECT *
FROM df1
LEFT JOIN df2
ON df1.key = df2.key;
>>> pd.merge(df1, df2, on='key', how='left')
key value_x value_y
0 A 0.034928 NaN
1 B -2.140503 -1.273683
2 B -2.140503 0.397336
3 C -1.678950 NaN
4 D -0.490544 -0.042907
UPDATE
UPDATE df
SET sex = 0
WHERE sex = 2;
>>> df
height weight sex birthday
yamada 180.0 68 1 19801122
suzuki NaN 54 2 19900411
tanaka 170.0 66 1 19850904
takahashi 149.0 40 2 19900222
>>>
>>> df.loc[df['sex'] == 2, 'sex'] = 0
>>>
>>> df
height weight sex birthday
yamada 180.0 68 1 19801122
suzuki NaN 54 0 19900411
tanaka 170.0 66 1 19850904
takahashi 149.0 40 0 19900222
DELETE
DELETE FROM df
WHERE sex = 1;
>>> df
height weight sex birthday
yamada 180.0 68 1 19801122
suzuki NaN 54 0 19900411
tanaka 170.0 66 1 19850904
takahashi 149.0 40 0 19900222
>>>
>>> df = df.loc[df['sex'] == 1]
>>>
>>> df
height weight sex birthday
yamada 180.0 68 1 19801122
tanaka 170.0 66 1 19850904