pandas基本操作まとめ
0. 本記事の概要
Kaggleのコース
https://www.kaggle.com/learn/pandas
をベースとして,pandasの基本操作を纏めました.
元コースとくらべて,若干順番が前後していたり,省略あるいは追記している部分があります.
1. データの作成,データの読み込み
pandasのデータ→DataFrame,またはSeriesで管理する.
DataFrame:一般のテーブルデータを取り扱う型.
Series:リストを取り扱う型.すなわち,単一の列データのみ保持する.
import pandas as pd
test_data1 = pd.DataFrame({'type': ['A', 'B', 'C', 'A', 'C',], 'columnA': [1, 2, 3, 4, 5], 'columnB': [6, 7, 8, 9, 10]})
test_data2 = pd.Series([1, 2, 3, 4, 5])
"""test_data1
type columnA columnB
0 A 1 6
1 B 2 7
2 C 3 8
3 A 4 9
4 C 5 10
"""
print(test_data1.shape) # (5, 3)
print(len(test_data1)) # 5
データには数値以外にも,文字列を保持させることができる.
kaggleなどで使う上では,既存のcsvデータを読み込むことが多い.
これはread_csv(データパス)で行う.
csv_data = pd.read_csv("table_data.csv")
csv_data = pd.read_csv("table_data.csv", index_col=0) # インデックス列がcsvに含まれている場合,指定できる
# 注:インデックスは数字とは限らない(が,多くの場合は数字と思われる).
2. データの選択
DataFrameの列データにアクセスする方法が主に2つある.
1.属性として指定する方法
2.辞書型のラベルとして指定する方法
test_data1.columnA
test_data1['columnA']
"""どちらも以下のデータを返却する
0 1
1 2
2 3
3 4
4 5
"""
また,各行にアクセスするには,通常のリストと同様にインデックスを指定する.
test_data1['columnA'][0] # 1が返却される
一方で,pandasには独自のアクセス方法が2つほど用意されている.
1つ目はilocで,行と列を数値で指定する方法.
2つ目はlocで,行と列をラベルで指定する方法.
# 以下の2つはどちらも同じ場所を指している
test_data1.iloc[0, 1] # 1が返却される
test_data1.loc[0, 'columnA'] # 1が返却される
注意すべきはlocの書き方.locでは「ラベルを指定する」という動作の関係上,スライスの定義が通常と異なる.すなわち,loc[0:3]と書いた場合,0行目のデータから3行目のデータまで,計4行が返却される.一方,通常のpythonのスライスでは末尾のインデックスを含まないため,[0:3]と書いた場合は0から2までのデータが返却される(ilocはこちらの方式).この違いに注意する.
test_data1.loc[0:3] # インデックス0から3までが返却される!!
test_data1.iloc[0:3] # インデックス0から2までが返却される
3. 条件による抽出・データ同士の演算
pandasのデータはpython(やnumpy)のリストと同じような演算が可能.
例えば,
test_data1.type == 'A'
"""
0 True
1 False
2 False
3 True
4 False
"""
と書くと,各行がこの条件を満たすかどうかのブーリアンが返却される.これを利用すると,例えば,
test_data1[test_data1.type == 'A']
"""
type columnA columnB columnC columnD
0 A 1 6 0 7
3 A 4 9 0 13
"""
とすることで,typeがAであるデータのみを抽出できる.
複数の条件を組み合わせるには"&(and)"や"|(or)"を使う.
また,各列同士を足し合わせるなども可能.
test_data1.columnA + test_data1.columnB
"""
0 7
1 9
2 11
3 13
4 15
"""
4. 列データの追加
既存のDataFrameに新たな列を追加する場合,以下のように書く.
test_data1['columnC'] = 0
"""
type columnA columnB columnC
0 A 1 6 0
1 B 2 7 0
2 C 3 8 0
3 A 4 9 0
4 C 5 10 0
"""
これでcolumnCが追加され,その全ての値が0で初期化される.
イテレータで初期化することも可能.
3.の演算と組み合わせることで,既存のデータから新たなデータ列を作ることができる.
(例えば,質量と体積というデータから,質量÷体積=密度 を新たに作る,など)
test_data1['columnD'] = test_data1.columnA + test_data1.columnB
"""
type columnA columnB columnC columnD
0 A 1 6 0 7
1 B 2 7 0 9
2 C 3 8 0 11
3 A 4 9 0 13
4 C 5 10 0 15
"""
5. データ統計
あるデータについて平均や標準偏差を求めたい.
その場合,describe()を使う.
test_data1.columnA.describe()
"""
count 5.000000
mean 3.000000
std 1.581139
min 1.000000
25% 2.000000
50% 3.000000
75% 4.000000
max 5.000000
Name: columnA, dtype: float64
"""
データ数,平均,標準偏差,最小値,各パーセンタイル値,最大値が表示された.
describe()は対象とするデータの種類によって異なるサマリーを出力する.
test_data1.type.describe() # 文字列の場合
"""
count 5
unique 3
top C
freq 2
Name: type, dtype: object
"""
特定の統計値を指定して出力させることもできる.
test_data1.columnA.mean() # 平均値が出力される
test_data1.type.unique() # ユニークな要素がリストとして出力される
test_data1.type.value_counts() # ユニークな要素と,その頻度が出力される
6. 関数によるデータ処理
3.では列同士の演算を行った.pandasでは更に,自作の関数を各データに適用することができる.
これには3通りの方法がある.
・map()を使う方法:ある列のデータ(Series)に対して操作を行う.
columnA_max = test_data1.columnA.max()
columnA_min = test_data1.columnA.min()
mapped = test_data1.columnA.map(lambda x: (x - columnA_min) / (columnA_max - columnA_min))
"""
0 0.00
1 0.25
2 0.50
3 0.75
4 1.00
"""
この場合,mapに渡す関数は単一の引数を受け取り,操作を施したSeriesを返却する.
・apply()を使う方法:各行(列)のデータに対して操作を行う.
def convert_columnD(row):
row.columnD = row.columnD * row.columnA
return row
applied = test_data1.apply(convert_columnD, axis='columns')
"""
type columnA columnB columnC columnD
0 A 1 6 0 7
1 B 2 7 0 18
2 C 3 8 0 33
3 A 4 9 0 52
4 C 5 10 0 75
"""
この場合,applyに渡す関数は各行(列)のデータを丸ごと受け取り,操作を施したDataFrameを返却する.そのため,上の例のように,複数の列(行)データを使った演算が可能.
・applymap()を使う方法:elementwise(各要素ごと)に操作を行う(See https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.applymap.html).
7. グループ化
例えば,test_data1のデータをtype毎に分析したいとする.
3.のように条件式で指定してもよいが,typeの種類が増えるにつれて煩雑になってしまう.
こういった場合,groupby()という関数でグループ化を行うと便利.
test_data1.groupby('type').columnA.mean() # 各typeのデータ内で平均を求める
"""
type
A 2.5
B 2.0
C 4.0
"""
groupbyにはグループ化対象のラベルを渡す.これは,リストの形で複数渡すことも可能で,この場合,データはMulti-indexed(階層化されたインデックスを持つデータ)となる.
8. ソート
データをソートするには,sort_valuesを使う.
sorted_data = test_data1.sort_values(by='columnA', ascending=False) # データAの降順に並び替え
"""
type columnA columnB columnC columnD
4 C 5 10 0 15
3 A 4 9 0 13
2 C 3 8 0 11
1 B 2 7 0 9
0 A 1 6 0 7
"""
インデックスで並べ直したい場合はsort_index()を使う.
データのざっくりした傾向を掴むために,各グループをそのデータ数順に表示したい場合がある.
7.と組み合わせて,以下のようにする.
group_sizes_sorted = test_data1.groupby('type').size().sort_values(ascending=False)
"""
type
A 2
C 2
B 1
"""
9. リネーム
ある列(あるいは行)をリネームするには,rename()を使う.
引数には,リネームする対象を渡す.
renamed = test_data1.rename(columns={'type': 'class'}) # 列のリネーム
"""
class columnA columnB columnC columnD
0 A 1 6 0 7
1 B 2 7 0 9
2 C 3 8 0 11
3 A 4 9 0 13
4 C 5 10 0 15
"""
行(インデックス)のリネームもできる.
index_renamed = test_data1.rename(index={0: 'first', 1: 'second'}) # 行のリネーム
"""
type columnA columnB columnC columnD
first A 1 6 0 7
second B 2 7 0 9
2 C 3 8 0 11
3 A 4 9 0 13
4 C 5 10 0 15
"""
ただし,行インデックスそのものをリネームするより,ある列をインデックス列として指定することの方が多いかも.これはset_index()で行う.
type_indexed = test_data1.set_index('type')
"""
columnA columnB columnC columnD
type
A 1 6 0 7
B 2 7 0 9
C 3 8 0 11
A 4 9 0 13
C 5 10 0 15
"""
実は,pandasのDataFrameでは,行と列「そのもの」にname属性が定義されている.
これを設定するには,rename_axis()を使う.
axis_renamed = test_data1.rename_axis('product', axis='rows').rename_axis('field', axis='columns')
"""
field type columnA columnB columnC columnD
product
0 A 1 6 0 7
1 B 2 7 0 9
2 C 3 8 0 11
3 A 4 9 0 13
4 C 5 10 0 15
"""
10. データの結合
別々のテーブルデータを読み込んで,それらを1つのデータに結合したい場合がある.
pandasにはこれを実現する関数がいくつか存在する.
・concat():2つのDataFrameが同じ種類の列を持っている場合など
この場合は純粋に2つのデータをくっつける操作になる.
test_data_one = pd.DataFrame({'type': ['A', 'B', 'C'], 'columnA': [1, 2, 3], 'columnB': [11, 12, 13]})
test_data_another = pd.DataFrame({'type': ['C', 'C', 'B'], 'columnA': [2, 4, 8], 'columnB': [3, 9, 27]})
concated = pd.concat([test_data_one, test_data_another])
"""
type columnA columnB
0 A 1 11
1 B 2 12
2 C 3 13
0 C 2 3
1 C 4 9
2 B 8 27
"""
インデックスを0からふり直すには,ignore_indexオプションをTrueにする.
(参考:https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.concat.html)
concated = pd.concat([test_data_one, test_data_another], ignore_index=True)
"""
type columnA columnB
0 A 1 11
1 B 2 12
2 C 3 13
3 C 2 3
4 C 4 9
5 B 8 27
"""
また,列方向に結合する(=データ数は同じで,各データに追加の列データを加える)ことも可能.
・join():ある共通のインデックスに従って結合したい場合など
(説明が難しいが,)例えば,同じ日に別々の地域で観測した天候を纏めたい場合を想定する.
データを日付毎に纏めたいが,地域ごとで区別できるようにしたい.
weather_region_A = pd.DataFrame({'date': ['01', '02', '03'], 'weather': ['cloudy', 'sunny', 'sunny']})
weather_region_B = pd.DataFrame({'date': ['01', '02', '03'], 'weather': ['sunny', 'rainy', 'rainy']})
この場合,まず,
・set_index()によって,日付をインデックス列に指定する.
data_left = weather_region_A.set_index('date')
data_right = weather_region_B.set_index('date')
・join()によって,データを日付のインデックス毎に結合する.
なお,join()はDataFrameの関数なので,data_left.join()という風に書く.
また,suffix(接尾辞)を指定することができる.
data_joined = data_left.join(data_right, lsuffix='_A', rsuffix='_B')
"""
weather_A weather_B
date
01 cloudy sunny
02 sunny rainy
03 sunny rainy
"""
11. データ型の確認・変換
データ型はdtypes属性で確認可能.
test_data1.dtypes
# test_data1.columnD.dtypes # 各列に対しても動作する
"""
type object
columnA int64
columnB int64
columnC int64
columnD int64
"""
ただし,文字列から成るデータはobject型と見なされる.
データの変換はastype(変換後のデータ型)で行う.
converted_columnD = test_data1.columnD.astype('float64')
"""
0 7.0
1 9.0
2 11.0
3 13.0
4 15.0
Name: columnD, dtype: float64
"""
12. 欠損値の検索・データの置き換え
テーブルデータに欠損値(データが存在しない,NaNで表される)がある場合を考える.
"""test_data_missing
type columnA columnB
0 A 1.0 6.0
1 B 2.0 7.0
2 C NaN 8.0
3 A NaN 9.0
4 C 5.0 NaN
"""
特定の列にNaNを含むデータの抽出は以下のように行う.
test_data_missing[pd.isnull(test_data_missing.columnA)]
"""
type columnA columnB
2 C NaN 8.0
3 A NaN 9.0
"""
pd.isnull(検索する列のラベル)は各行の該当列がNaNかどうかのブーリアンを返却する.
これによって抽出を行っている.
NaNをあるデータで置き換える(埋める)場合,fillna(置き換え後のデータ)を使う.
filled_columnA = test_data_missing.columnA.fillna('Unknown')
"""
0 1.0
1 2.0
2 Unknown
3 Unknown
4 5.0
"""
また,fillnaと同じような動作で,特定のデータを別のデータに置き換えたい場合,replace(置き換え対象,置き換え後データ)を使う.
replaced_type = test_data_missing.type.replace('A', 'AAA')
"""
0 AAA
1 B
2 C
3 AAA
4 C
"""
Author And Source
この問題について(pandas基本操作まとめ), 我々は、より多くの情報をここで見つけました https://qiita.com/shun310/items/e06b7bc97768152042a7著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .