初めての人がわかった気になれるpandasの使い方
僕自身普段はGo言語をよく書いていてPython自体あんまりやらないので、pandasもほぼ使ったことなかったです。最近、pandasを使わざる負えない状況になり、ちょっと触りました。
pandasはものすごく便利で高機能だなと感じました。ただ、高機能すぎて、めっちゃ詳しく紹介してくれてる記事はいっぱいあるんですが、僕の知りたいのそこじゃない状態になってしまったので、最低限これだけわかったらpandasの基本を理解したといえるんじゃないかなという切り口でまとめました。
対象の読者
- pandas初めて
- pandasのデータ構造がわからない
- pythonはなんとなく書ける
pandasのデータ構造は2種類ある
pandasのデータ構造には、DataFrame
というテーブル(列と行)を表現するのデータ構造とSeries
という1列or1行だけを表現するデータ構造の2種類があります。
DataFrame
行と列が存在するいわゆるテーブルのようなデータ構造です。pandasといえばほとんどこのデータ構造を扱います。(公式ドキュメント)
name | height | birthdate | |
---|---|---|---|
a | tanaka | 160 | 1990-01-01 |
b | yamada | 170 | 1980-02-02 |
c | kato | 180 | 1970-03-03 |
各列には列名が付与されています。
一番左の列はインデックスといい、行番号のような存在です。インデックスにも列名を付与することもできますし、インデックスを複数列指定することもできます。インデックスは、数値、文字列、日時など様々なデータを利用することが可能です。
Series
DataFrameとは違い、1列のみ、もしくは1行のみを表現するデータ構造です。(公式ドキュメント)
weight | |
---|---|
a | 53 |
b | 67 |
c | 83 |
1列だけですが、インデックスはあります。DataFrameと同じように複数列のインデックスを持つこともできますし、インデックスとしてまた数値、文字列、日時など様々なデータを利用することが可能です。また、列名はついていたり、ついてなかったりします。
DataFrameとSeriesの関係性と注意点
DataFrameは複数のSeriesの集まりによって構成されています。
僕の場合、Series型の存在を知らないときに、とあるライブラリでSeries型のデータが返ってきたので困惑しました。
1つだけのSeries型のデータでもDataFrameに変換することができます。ビギナーはSeries型のハンドリングを覚えるがめんどくさいと思うので、Series型のデータは迷わずDataFrame型に変換するとよいのではないかと思います。そうすれば、扱うのはDataFrame型だけに統一できるのでビギナーにとっては扱いやすくなるのかなと思います。
変換する方法は簡単で、series型のデータを.to_frame()
するだけです。(公式ドキュメント)
Series型のデータは速攻でDataFrame型のデータに変換しますので、この記事ではDataFrame型に対する操作についてのみ紹介していきます。
DataFrameの使い方
新しいDataFrameを作る
df = pd.DataFrame(
[
['tanaka',160,datetime(1990, 1, 1)],
['yamada',170,datetime(1980, 2, 2)],
['kato',180,datetime(1970, 3, 3)]
],
index=['a','b','c'],
columns=['name','height','birthdate']
)
DataFrameの作り方は様々な方法があるので、こちらはDataFrameの作り方の1例です。この例では行ごとにデータを定義してますが、列ごとにデータを定義することもできますし、csvデータを読み込んでもいいですし、indexやcolumnsを指定しなくてもよいです。(公式ドキュメント)
indexは指定しない場合、0,1,2...と自動的に連番になります。
DataFrameの中身をデバッグする
print(df)
printするだけです。データ量が多い時は、先頭の数行と末尾の数行を出しくれて、index、columns、レコード数などを以下のように表示してくれます。
Open High Low Close Adj Close Volume
Date
1966-07-05 0.000000 0.273663 0.267490 0.269547 0.124835 388800
1966-07-06 0.000000 0.283951 0.267490 0.283951 0.131506 692550
1966-07-07 0.000000 0.291152 0.271605 0.273663 0.126741 1858950
1966-07-08 0.000000 0.276749 0.267490 0.276749 0.128171 1239300
1966-07-11 0.000000 0.283951 0.272634 0.275720 0.127694 656100
... ... ... ... ... ... ...
2021-07-29 243.320007 245.199997 242.979996 244.020004 244.020004 2572300
2021-07-30 243.850006 245.410004 242.210007 242.710007 242.710007 2336800
2021-08-02 244.240005 244.679993 239.690002 240.100006 240.100006 2693900
2021-08-03 239.559998 239.949997 235.250000 236.949997 236.949997 3299300
2021-08-04 236.449997 236.600006 233.050003 234.830002 234.830002 2240000
[13866 rows x 6 columns]
DataFrameかSeriesか確認する
print(type(df))
DataFrameだった場合 -> <class 'pandas.core.frame.DataFrame'>
Seriesだった場合 -> <class 'pandas.core.series.Series'>
と出力されます。
SeriesをDataFrameに変換する
.to_frame()
してあげるだけです。(公式ドキュメント)
ser = pd.Series(
[53, 67, 83],
index=['a','b','c'],
name="weight"
)
df = ser.to_frame()
DataFrameからindexの一覧を取り出す
df.index
DataFrameからcolumnの一覧を取り出す
df.columns
DataFrameから行を取り出す
行を取り出すとSeriesオブジェクトを取得します。
df.loc['index名']
DataFrameから条件を指定して複数行を取り出す
df.loc[df['height'] > 165]
DataFrameから値を取り出す
df.loc['index名', 'column名']
DataFrameを行ごとにループする
for index, row in df.iterrows():
print(index) # indexの値を出力する
print(row['column名']) # column名で値を取得できる
DataFrameのデータを更新する
indexとcolumnを指定してデータを更新できます。
df.loc['index名', 'colume名'] = "sato"
条件を指定して更新したい場合は下のようにできます。
df.loc[df['height'] > 165, 'name'] = "sato"
DataFrameに行を追加する
index名を指定して、値を配列として代入すると行を追加できます。配列の要素数が列数と一致する必要があります。
df.loc['index名'] = ['sato',185,datetime(1960, 3, 3)]
indexを指定してないdataFrameだった場合、indexは0,1,2...と連番になっているのでlen(df)
でDataFrameの行数を取得するのがよいでしょう。
df.loc[len(df)] = ['sato',185,datetime(1960, 3, 3)]
DataFrameに列を追加する
column名を指定して、値を配列を代入すると列を追加できます。配列の要素数が行数と一致する必要があります。
df['column名'] = [55,65,75]
DataFrameの行を削除する
df.drop('index名')
DataFrameの列を削除する
drop()
の引数にaxix=1
を追加すると行を削除できます。
df.drop('column名', axis=1)
csvファイルをDataFrameとして読み込む
df = pd.read_csv('ファイルパス')
カラム名はcsvにヘッダーカラムがあれば、勝手に読み込んでくれます。他にも細かいオプションでカラム名を指定したり、何行かスキップして読み込んだりできます。(公式ドキュメント)
csvファイルとして出力する
df.to_csv('ファイルパス')
たいていの場合はこれで良いと思います。オプションで細かい設定もできます。(公式ドキュメント)
終わりに
pandasのデータ構造とDataFrameに対する一通りの処理をまとめました。これだけ知っていれば、それなりpandasを使ってデータを見たりいじったりできるかと思います。僕はここにあること以外のことは何も知りませんでしたが、pandas使ってデータをいじることはできました!
pandasはすごく高機能なので、同じ処理を様々な方法を用いて実現することができますし、いろんなオプションを駆使することでかゆいところまで手が届くように作られています。ここで紹介したのは、様々なやり方のうちの一例でしかありません。
細かなことは公式ドキュメントにありますので、都度必要なときに参考にするのがよさそうです。また、Googleで検索すれば、細かなことを紹介してくれている記事は日本語でも英語でもたくさんあるので困ることはなさそうです。
Discussion