1. はじめに
今回は以前の記事の続きになります。
各項目の通し番号も、前回の記事の続きとなるようになっています。
2. 10 minutes to pandas 続き
(5). マージ
ここで扱うのは、データに他のデータを連結したり、付加したりするメソッドです。
(5)-1. 連結
・concat()メソッド
df = pd.DataFrame(np.random.randn(10, 4)) #DataFrameオブジェクトの生成
pieces = [df[:3], df[3:7], df[7:]] #バリューの分割
pd.concat(pieces) #valueの結合ここでは、単純にデータの分割->結合を行なっています。
戻り値
| 0 | 1 | 2 | 3 | |
|---|---|---|---|---|
| 0 | 0.890756 | 0.901530 | -0.765555 | 1.050202 |
| 1 | -0.271121 | 0.593950 | 1.824453 | 0.614195 |
| 2 | 0.952880 | 1.262962 | 0.619088 | 0.786609 |
| 3 | -1.242715 | -0.259757 | -0.441338 | 0.073672 |
| 4 | -1.943991 | -0.156803 | 0.008432 | -2.172710 |
| 5 | 0.941596 | 1.562745 | -0.236899 | 0.885822 |
| 6 | -0.881871 | -1.691723 | 0.720165 | 0.041064 |
| 7 | -2.468225 | 0.391067 | 0.829695 | -0.100468 |
| 8 | 0.550700 | -1.314055 | 1.370246 | 0.488189 |
| 9 | -0.124805 | 0.190150 | 0.345547 | -0.401358 |
(5)-2. 結合
・merge()メソッド
left = pd.DataFrame({'key': ['foo', 'foo'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'foo'], 'rval': [4, 5]})
pd.merge(left, right, on='key') #keyを基準にDataFrameオブジェクトを結合させる戻り値
| key | lval | rval | |
|---|---|---|---|
| 0 | foo | 1 | 4 |
| 1 | foo | 1 | 5 |
| 2 | foo | 2 | 4 |
| 3 | foo | 2 | 5 |
left = pd.DataFrame({'key': ['foo', 'bar'], 'lval': [1, 2]})
right = pd.DataFrame({'key': ['foo', 'bar'], 'rval': [4, 5]})
pd.merge(left, right, on='key') #もう1つの例ここでは、fooとbarが一致しているので、カラムが追加される形になっています。
戻り値
| key | lval | rval | |
|---|---|---|---|
| 0 | foo | 1 | 4 |
| 1 | bar | 2 | 5 |
(5)-3. 付加
・append()メソッド
#rowにDataFrameを付加
df = pd.DataFrame(np.random.randn(8, 4), columns=['A','B','C','D'])
s = df.iloc[3]
df.append(s, ignore_index=True) #df.iloc[3]がインデックス8に付加されているここでは、新たにインデックスが追加されています。
戻り値
| A | B | C | D | |
|---|---|---|---|---|
| 0 | 2.715159 | 0.782455 | -0.594675 | -0.570256 |
| 1 | -0.329114 | -0.186522 | 1.022586 | -2.380807 |
| 2 | 0.954745 | -2.141672 | -0.022732 | -1.165014 |
| 3 | 0.443555 | 0.300922 | 1.675571 | 0.367578 |
| 4 | 0.676451 | 0.410647 | 0.405250 | -2.991596 |
| 5 | -0.887430 | 0.135306 | 0.260099 | 0.667514 |
| 6 | -0.538035 | -0.761003 | -0.413540 | -0.988319 |
| 7 | -0.455442 | -0.564329 | 1.090382 | -0.372395 |
| 8 | 0.443555 | 0.300922 | 1.675571 | 0.367578 |
ここで登場したメソッド等は以下になります。
- concat()…データを結合させるメソッド
- merge()…DataFrameオブジェクトを結合させる
- * 引数: left,right=DataFrameオブジェクト、on=結合の基準をインデックスかカラムかを指定
- DataFrame.append()…DataFrameにrowを付加するメソッド。
- * 引数: ignore_index=付加するrowのラベルを使用するかどうか(Trueなら使用しない)
(6). グルーピング
groupbyメソッドでグループ単位で分割や適用、結合などができます。
.groupby()メソッド
df = pd.DataFrame({'A' : ['foo', 'bar', 'foo', 'bar', 'foo', 'bar', 'foo', 'foo'],
'B' : ['one', 'one', 'two', 'three', 'two', 'two', 'one', 'three'],
'C' : np.random.randn(8),
'D' : np.random.randn(8)})
df.groupby('A').sum() #Aグループを同一バリューごとにカテゴライズし、各カラムの値を合計する戻り値
| C | D | |
|---|---|---|
| A | ||
| bar | -1.934583 | -0.343288 |
| foo | 0.762228 | -1.428246 |
df.groupby(['A','B']).sum() #グループ化をA->Bで行う戻り値
| C | D | ||
|---|---|---|---|
| A | B | ||
| bar | one | -0.760050 | -0.479678 |
| three | -1.515467 | -0.274024 | |
| two | 0.340934 | 0.410415 | |
| foo | one | 1.455895 | -0.354460 |
| three | 0.157338 | 0.450135 | |
| two | -0.851006 | -1.523920 |
ここで登場したメソッド等は以下になります。
- DataFrame.groupby() …グループごとに沿った対応をするメソッド -> Gruoupby型
- GroupBy.sum()…グループに沿って合計を出すメソッド
(7). 再整形
ここでは、データの整形を行うメソッドを扱っています。
(7)-1. スタック
インデックスを複数重ね合わせるようなことができます。
tuples = list(zip(*[['bar', 'bar', 'baz', 'baz', 'foo', 'foo', 'qux', 'qux'],
['one', 'two', 'one', 'two', 'one', 'two', 'one', 'two']])) #zip(*引数)で引数を展開する -> listでタプルをリストに変換
index = pd.MultiIndex.from_tuples(tuples, names=['first', 'second']) #タプルのリストをインデックスに転換する
df = pd.DataFrame(np.random.randn(8, 2), index=index, columns=['A', 'B'])
df2 = df[:4]
df2戻り値
| A | B | ||
|---|---|---|---|
| first | second | ||
| bar | one | 0.656057 | -0.108284 |
| two | -0.659357 | -0.505724 | |
| baz | one | 0.379070 | 0.972001 |
| two | -0.110854 | -0.328280 |
上記のデータ構造をさらにマルチインデックスのようにします。
・stack()メソッド
stacked = df2.stack() #DataFrame、Seriesのカラムをインデックスに入れ、マルチインデックスのような形にする
stacked戻り値
first second
bar one A 0.427586
B -1.005260
two A 0.095713
B 2.812249
baz one A -0.244172
B -1.650703
two A -0.789093
B -0.349003
dtype: float64
・unstack()メソッド
stacked.unstack() #スタックされたDataFrame,Seriesをカラムのある状態に戻す戻り値
| A | B | ||
|---|---|---|---|
| first | second | ||
| bar | one | 0.656057 | -0.108284 |
| two | -0.659357 | -0.505724 | |
| baz | one | 0.379070 | 0.972001 |
| two | -0.110854 | -0.328280 |
(7)-2. ピボットテーブル
・pivot_table()メソッド
df = pd.DataFrame({'A' : ['one', 'one', 'two', 'three'] * 3,
'B' : ['A', 'B', 'C'] * 4,
'C' : ['foo', 'foo', 'foo', 'bar', 'bar', 'bar'] * 2,
'D' : np.random.randn(12),
'E' : np.random.randn(12)})
pd.pivot_table(df, values='D', index=['A', 'B'], columns=['C'])
#スプレッドシートスタイルのピボットテーブル(データの要約)を返す。(引数の意味:DataFrameであるdfのバリューDのみが対象、A・Bがインデックス、Cがカラム)戻り値
| C | bar | foo | |
|---|---|---|---|
| A | B | ||
| one | A | 0.164288 | 0.511736 |
| B | 1.113288 | 1.218575 | |
| C | 0.140917 | 1.920049 | |
| three | A | 0.384494 | NaN |
| B | NaN | -0.954451 | |
| C | -0.900987 | NaN | |
| two | A | NaN | -1.876843 |
| B | 0.659083 | NaN | |
| C | NaN | -0.148574 |
ここで使用したメソッド等は以下になります。
- MultiIndex.from_tuples()…タプルのリストをマルチインデックスに変換する
- DataFrame.stacked()…カラムをインデックス相当に置き換え、マルチインデックスのようにするメソッド
- stucked DataFrame.unstacked()…スタックされたDataFrameをカラムのある状態にするメソッド
- pivot_table()…スプレッドシートスタイルのピボットテーブル(データの要約)を返す
(8). Time Series
Pandasでは、時間についてもこのモジュールで扱えるようになっています。
・resample()メソッド
rng = pd.date_range('1/1/2012', periods=100, freq='S')
ts = pd.Series(np.random.randint(0, 500, len(rng)), index=rng)
ts.resample('5Min').sum() #resample()…引数に合致する時間インデックスに会う情報を収集戻り値
2012-01-01 25017 Freq: 5T, dtype: int64
・tz_localize()メソッド
rng = pd.date_range('3/6/2012 00:00', periods=5, freq='D')
ts = pd.Series(np.random.randn(len(rng)), rng)
ts_utc = ts.tz_localize('UTC') #タイムゾーンを持ったawareな時間オブジェクトに変更
ts_utc戻り値
2012-03-06 00:00:00+00:00 -0.311405 2012-03-07 00:00:00+00:00 -0.399318 2012-03-08 00:00:00+00:00 -1.052087 2012-03-09 00:00:00+00:00 1.913156 2012-03-10 00:00:00+00:00 -0.516693 Freq: D, dtype: float64
・uz_convert()メソッド
ts_utc.tz_convert('US/Eastern') #引数の地域のタイムゾーンに変更戻り値
2012-03-05 19:00:00-05:00 -0.311405 2012-03-06 19:00:00-05:00 -0.399318 2012-03-07 19:00:00-05:00 -1.052087 2012-03-08 19:00:00-05:00 1.913156 2012-03-09 19:00:00-05:00 -0.516693 Freq: D, dtype: float64
・to_period()メソッド、to_timestamp()メソッド
#タイムインデックスの推移:月末基準(rng)->付きのみの表示(ps)->月初基準
rng = pd.date_range('1/1/2012', periods=5, freq='M')
ts = pd.Series(np.random.randn(len(rng)), index=rng)
ps = ts.to_period() #Datatimeインデックスからperiodタイムインデックスに変更
ps.to_timestamp() #月初日基準のdatetimeインデックスに変更戻り値
2012-01-01 0.628367 2012-02-01 -0.418007 2012-03-01 0.302071 2012-04-01 -0.099849 2012-05-01 0.575034 Freq: MS, dtype: float64
・asfreq()メソッド
#タイムインデックスの推移:クオーター(prng)->クオーターの最初の日の9時
prng = pd.period_range('1990Q1', '2000Q4', freq='Q-NOV')
ts = pd.Series(np.random.randn(len(prng)), prng)
ts.index = (prng.asfreq('M', 'e') + 1).asfreq('H', 's') + 9 #PeriodIndexを特定の頻度期間に変更
ts.head()戻り値
1990-03-01 09:00 0.705433 1990-06-01 09:00 -0.910949 1990-09-01 09:00 -0.280971 1990-12-01 09:00 1.644449 1991-03-01 09:00 2.460565 Freq: H, dtype: float64
ここで利用したメソッド等は以下になります。
- Series.resample()…引数に合致する時間インデックスでデータを再取得 -> Seriesオブジェクト
- Series.tz_localize(timezone)…引数のタイムゾーン情報を持つ時間オブジェクトに変更
- Seriestime.tz_convert(timezone)…引数のタイムゾーンの時間に変更
- Seriestime.to_period()…Datatimeインデックスをperiodタイムインデックスに変更
- Seriestime.to_timestamp()…月初日基準のdatetimeインデックスに変更
- period_range()…期間表示のタイムインデックスを返すメソッド -> PeriodIndex型
- PeriodIndex.asfreq()…PeriodIndexオブジェクトを特定のタイムインデックスに変換
(9). カテゴリー化
ここでは、カテゴリー化を行うメソッド等を行います。
・astype()メソッド
df = pd.DataFrame({"id":[1,2,3,4,5,6], "raw_grade":['a', 'b', 'b', 'a', 'a', 'e']})
df["grade"] = df["raw_grade"].astype("category") #"raw_grade"のデータを"category"型に変換
df["grade"]戻り値
0 a 1 b 2 b 3 a 4 a 5 e Name: grade, dtype: category Categories (3, object): [a, b, e]
・cat_categories属性
df["grade"].cat.categories = ["very good", "good", "very bad"] #新しいカテゴリーを割り当て[a,b,c]に相当
df["grade"]戻り値
0 very good 1 good 2 good 3 very good 4 very good 5 very bad Name: grade, dtype: category Categories (3, object): [very good, good, very bad]
・cat_set_categories()メソッド
df["grade"] = df["grade"].cat.set_categories(["very bad", "bad", "medium", "good", "very good"]) #新しいカテゴリーの割り当て[a,b,c]に相当
df["grade"]戻り値
0 very good 1 good 2 good 3 very good 4 very good 5 very bad Name: grade, dtype: category Categories (5, object): [very bad, bad, medium, good, very good]
・sort_values()メソッド
df.sort_values(by="grade") #gradeでのソート戻り値
| id | raw_grade | grade | |
|---|---|---|---|
| 5 | 6 | e | very bad |
| 1 | 2 | b | good |
| 2 | 3 | b | good |
| 0 | 1 | a | very good |
| 3 | 4 | a | very good |
| 4 | 5 | a | very good |
df.groupby("grade").size() #gradeカテゴリーをサイズを出す戻り値
grade very bad 1 bad 0 medium 0 good 2 very good 3 dtype: int64
ここで使用したメソッド等は以下になります。
- Categorical()…カテゴリー変数を表すメソッド。 -> Categorical型
- DataFrame.astype()…pandasオブジェクトを特定のデータ型に変換
- Series.cat.categories…新しいカテゴリーの割り当て
- Series.cat.set_categories()…新しいカテゴリーの割り当て
- Series.sort_values(category)…指定したカテゴリーでのソート
- GroupBy.size()…特定グループのサイズを集計
(10). プロット
ts = pd.Series(np.random.randn(1000), index=pd.date_range('1/1/2000', periods=1000))
ts = ts.cumsum()
ts.plot() #matplotlibを使ってグラフをプロット戻り値
・cumsum()メソッド
df = pd.DataFrame(np.random.randn(1000, 4), index=ts.index, columns=['A', 'B', 'C', 'D'])
df = df.cumsum()
plt.figure(); df.plot(); plt.legend(loc='best') #セミコロンは1行に複数の文を書く場合の記法(非推奨)
#plt.figure()…Figureオブジェクトの生成
#plt.legend()…図の中で利用する凡例(左下のもの)を表示するもの戻り値
ここで使用したメソッドは以下になります。
- Series.plot()…matplotlibを用いてグラフにプロット
- Artistクラス…図のキャンバスをレンダリングするための抽象的な基底クラス
- Figureインスタンス…コールバックをサポートする
- plt.figure()…figureモジュール。プロットするすべての要素を含む、Artistクラスやfigureインスタンスを提供する
- plt.legend()…Legendモジュール。判例を表示させるためのもの。
- 引数: loc=凡例の位置の指定
- cumsum()…累積和を表すメソッド
(11). 他ファイルからのデータの取得
ここでは、他のファイル形式からデータを取得するメソッド等を扱います。
(11)-1. CSV
・to_csv()メソッド
df.to_csv('foo.csv') #DataFrameをcsvに書き込み
pd.read_csv('foo.csv') #CSVファイルをDataFrameで読み込む戻り値
| Unnamed: 0 | A | B | C | D | |
|---|---|---|---|---|---|
| 0 | 2000-01-01 | -0.885629 | 0.889656 | 0.633089 | 0.056821 |
| 1 | 2000-01-02 | -2.982219 | 0.403194 | 1.209124 | 1.959333 |
| 2 | 2000-01-03 | -3.104937 | 2.183357 | 2.995985 | 0.641896 |
| 3 | 2000-01-04 | -3.488287 | 2.844256 | 1.020145 | -0.520878 |
| 4 | 2000-01-05 | -3.099456 | 2.711296 | 2.700519 | -1.665338 |
| 5 | 2000-01-06 | -1.895860 | 2.238260 | 2.637793 | -1.817670 |
| 6 | 2000-01-07 | -3.712167 | 4.138061 | 2.972879 | -2.315594 |
| 7 | 2000-01-08 | -1.995269 | 4.160025 | 4.245503 | -3.365914 |
| 8 | 2000-01-09 | -1.764673 | 3.689517 | 4.425295 | -3.296960 |
| 9 | 2000-01-10 | -2.537773 | 3.289495 | 3.971328 | -3.323374 |
| 10 | 2000-01-11 | -3.804190 | 1.454533 | 4.160079 | -2.408422 |
| 11 | 2000-01-12 | -3.173957 | 0.832084 | 6.127438 | -2.184997 |
| 12 | 2000-01-13 | -2.570091 | 1.272821 | 6.690779 | -0.801479 |
| 13 | 2000-01-14 | -2.976794 | 1.128242 | 5.986204 | -1.114424 |
| 14 | 2000-01-15 | -2.965553 | -1.152257 | 7.227440 | -0.426281 |
| 15 | 2000-01-16 | -5.781928 | 0.400005 | 7.599222 | -1.256213 |
| 16 | 2000-01-17 | -6.307684 | 1.855003 | 7.607097 | -3.244378 |
| 17 | 2000-01-18 | -6.959026 | 1.597980 | 7.045685 | -2.287091 |
| 18 | 2000-01-19 | -6.335189 | 1.469277 | 6.135651 | -1.515488 |
| 19 | 2000-01-20 | -7.008508 | 2.551476 | 6.298826 | -0.652640 |
| 20 | 2000-01-21 | -7.566281 | 1.161019 | 5.501244 | -2.101572 |
| 21 | 2000-01-22 | -7.488703 | 1.006602 | 4.202419 | -2.114033 |
| 22 | 2000-01-23 | -7.596298 | 0.329308 | 4.716298 | -0.780222 |
| 23 | 2000-01-24 | -6.218714 | -0.100461 | 5.197134 | 2.144381 |
| 24 | 2000-01-25 | -6.300895 | 0.550133 | 5.437201 | 0.364817 |
| 25 | 2000-01-26 | -5.225494 | 0.996887 | 5.357027 | 2.128822 |
| 26 | 2000-01-27 | -5.632822 | -1.321599 | 6.161507 | 2.890215 |
| 27 | 2000-01-28 | -4.782846 | 1.264124 | 7.671574 | 1.493188 |
| 28 | 2000-01-29 | -3.644309 | 0.612344 | 8.555950 | 1.944154 |
| 29 | 2000-01-30 | -2.689048 | -0.333203 | 10.225348 | 2.428360 |
| … | … | … | … | … | … |
| 970 | 2002-08-28 | 13.878344 | 35.522961 | 33.972022 | 13.754965 |
| 971 | 2002-08-29 | 15.373984 | 35.459520 | 32.706937 | 12.694938 |
| 972 | 2002-08-30 | 16.299438 | 34.101410 | 33.313294 | 12.354133 |
| 973 | 2002-08-31 | 16.321877 | 33.259532 | 33.066046 | 13.003854 |
| 974 | 2002-09-01 | 17.725887 | 32.649524 | 32.876745 | 12.741271 |
| 975 | 2002-09-02 | 15.960280 | 34.014459 | 33.494971 | 11.525645 |
| 976 | 2002-09-03 | 17.620675 | 31.686272 | 32.934520 | 11.444935 |
| 977 | 2002-09-04 | 19.280634 | 32.952100 | 32.108330 | 12.894522 |
| 978 | 2002-09-05 | 19.322396 | 33.437386 | 32.391694 | 13.351699 |
| 979 | 2002-09-06 | 18.859502 | 33.735702 | 31.634264 | 15.322096 |
| 980 | 2002-09-07 | 18.090184 | 33.377534 | 30.123894 | 15.055033 |
| 981 | 2002-09-08 | 19.499584 | 34.683697 | 28.933912 | 15.674115 |
| 982 | 2002-09-09 | 20.023109 | 33.225232 | 28.036330 | 14.623939 |
| 983 | 2002-09-10 | 22.096491 | 33.460218 | 28.296707 | 15.325953 |
| 984 | 2002-09-11 | 21.175395 | 31.867608 | 27.874382 | 14.080145 |
| 985 | 2002-09-12 | 22.749132 | 31.554791 | 28.800649 | 12.878497 |
| 986 | 2002-09-13 | 20.679855 | 29.106203 | 28.781835 | 11.242140 |
| 987 | 2002-09-14 | 19.949693 | 30.343146 | 28.950727 | 11.268712 |
| 988 | 2002-09-15 | 19.827703 | 30.307741 | 29.634053 | 11.303194 |
| 989 | 2002-09-16 | 18.840929 | 30.488293 | 29.963994 | 10.921785 |
| 990 | 2002-09-17 | 19.096619 | 31.979511 | 29.268281 | 11.851570 |
| 991 | 2002-09-18 | 18.918941 | 33.580999 | 29.989735 | 11.241848 |
| 992 | 2002-09-19 | 17.525040 | 33.091925 | 28.303035 | 11.107315 |
| 993 | 2002-09-20 | 16.832517 | 32.695425 | 28.265794 | 10.618252 |
| 994 | 2002-09-21 | 15.993035 | 32.882886 | 29.083918 | 9.858696 |
| 995 | 2002-09-22 | 15.499445 | 33.890772 | 28.109229 | 10.657104 |
| 996 | 2002-09-23 | 16.671281 | 35.686708 | 26.959108 | 9.960204 |
| 997 | 2002-09-24 | 16.525583 | 36.758392 | 27.874970 | 8.786993 |
| 998 | 2002-09-25 | 17.492685 | 36.953019 | 27.248388 | 9.385779 |
| 999 | 2002-09-26 | 17.589244 | 37.610107 | 28.834608 | 9.139163 |
(11)-2. HDF5
HDF5は、Hierarchical Data Formatの略で、階層化されたデータ群を取り扱うフォーマットです。
・to_hdf()メソッド
#扱い方がよくわからないため実行せず
df.to_hdf('foo.h5','df') #HDF5ファイルへの書き込み
pd.read_hdf('foo.h5','df') #HDF%ファイルの読み込み(11)-3. Excel
・to_excel()メソッド
df.to_excel('foo.xlsx', sheet_name='Sheet1') #Excelファイルへの書き込み
pd.read_excel('foo.xlsx', 'Sheet1', index_col=None, na_values=['NA']) #Excelファイルの読み込みここで使用したメソッドは以下になります。
- DataFrame.to_csv()…DataFrameをCSVに書き込み
- read_csv()…csvをDataFrameとして読み込み
- DataFrame.to_hdf()…HDF5ファイルへの書き込み
- read_hdf5()…HDF5ファイルの読み込み
- DataFrame.to_excel()…Excelファイルへの書き込み
- read_excel()…Excelファイルの読み込み
4. まとめ
以上が10 minutes to pandasの概要となります。
データを扱うことに特化しており、色々な使い方ができそうですので、僕も色々と試していきたいと思います。また、githubに私が学習したjupyter notebookのファイルをあげていますので、こちらも参考にしていただければと思います。

