もう、Excel的な集計はPythonでやってしまいたい。慣れるとそのほうが早いし便利ですね。
その時に、いつも調べてしまうような、よく使うテクニックをまとめてみました。
1.[基本処理] ファイル読み込み・出力
CSV読み込み
path='./path/to/csv'
df = pd.read_csv(path)
dataset = pd.read_csv(path,encoding='shift-jis') ## ExcelCSVの場合
dataset = pd.read_csv(path, index_col=2) # indexを指定して
TSV読み込み
dataset = pd.read_table(path)
ファイル出力
df.to_csv(path)
2.[Excel的な基本編集]データ抽出・フィルタ(行・列)&フィルタ後のデータ更新
Excelでいう基本操作の行や列の追加、フィルタや関数による条件に応じた値代入など
カラム(列)抽出
df[ ['col1','col2','col3'] ] # 列名で抽出
カラム追加・削除
df['new_column'] = 0 # 初期値を0で埋めて追加
df.drop("new_column", axis=1) # 列(axis=1)を指定して削除
行フィルタ・抽出・削除
df[df['product']=='P1'] # 条件で抽出
df.drop(5) # 行5を削除
df.drop([5,6]) # 行5,6を削除
列の値代入・更新
# =A1*2 的な
s = pd.Series([1, 2, 3], index=['a', 'b', 'c'])
s.apply(lambda x: x * 2)
# a 2
# b 4
# c 6
# dtype: int64
# =IF(A1>0,1,0)的な
Y = df['flg'].apply( lambda x: 1 if x>0 else 0)
一気に更新 ( =A1+5 )
df['point'] += 5
条件を指定して更新 ( Excel関数の代替 ( =IF(A1>=5,'P1','P2' ) )
df.loc[ df['file_name'].str.contains('ABCD' ) ,'product'] = 'P1' # 任意の文字列を含む場合
df.loc[ df['point'] >= 5 ,'product'] = 'P1' #任意の条件に一致する場合
複数の要素を指定して更新
df.loc['Bob':'Dave', 'age'] = 25 # Bob ~ Daveまで一気に更新
df.loc['Bob':'Dave', 'age'] = [20, 30, 40] #こんな風にもできる
df.iloc[1:3, 'age'] = 25 # 1 ~ 3まで一気に更新
df.loc[:'Dave', 'age'] = 25 # Daveまで一気に更新
df.loc[:5, 'age'] = 25 # 5まで一気に更新
df.iloc[::2, 0] # 奇数行
df.iloc[1::2, 0] # 偶数行
合計・平均,カウント( =sum(A:A) , =average(A:A) )
# mean は数値型のみ集約
df.mean()
# C2 2
# C3 5
# dtype: float64
# sum は 文字列も集約
df.sum()
# C1 ABC
# C2 6
# C3 15
# dtype: object
# sumif , subtotal的に ( =sumif() ,=subtotal(9, A:A) )
df[df['price']>=500].sum()
# count , counif
df.count()
df[df['price']>=500].count()
参考:http://sinhrks.hatenablog.com/entry/2014/11/27/232150
# 不偏標準偏差
df.std()
# C1 1.290994
# C2 1.290994
# C3 0.577350
# dtype: float64
# 標本標準偏差
df.std(ddof=False)
セルの値代入
df.at['Bob', 'age'] = 25 #index名で指定する場合
df.loc['Bob', 'age'] = 25 # locでも可能だが、1つの値更新は、atの方が早い
df.iat[1,0] = 25 # 行番号、列番号で指定(*いずれも0始まり)
df.iloc[1,0] = 25 # ilocでも可能だが、1つの値更新は、iatの方が早い
参考:pandasで任意の位置の値を取得・変更するat, iat, loc, iloc
https://note.nkmk.me/python-pandas-at-iat-loc-iloc/
3.[Excel VBA的な]ループ処理でなんでも自在に
1行ずつ処理
import pandas as pd
df = pd.DataFrame([[1, 10], [2, 20], [3, 30], [4, 40]], columns=['col1', 'col2'])
for index, row in df.iterrows():
print(row['col1'], row['col2’])
値を更新する
for index, row in df.iterrows():
row.point += 5
for index, row in df.iterrows():
df.at[index, 'point'] += 5
まとめて取得
for age, point in zip(df['age'], df['point']):
print(age)
print(point)
print('======\n')
1列ずつ処理
import pandas as pd
df = pd.DataFrame([[1, 10], [2, 20], [3, 30], [4, 40]], columns=['col1', 'col2'])
for index, col in df.iteritems():
print(sum(col))
4.PivotTable的な集計
df = pd.DataFrame({'group': ['g1', 'g2', 'g1', 'g2'],
'A': [1, 2, 3, 4], 'B': [5, 6, 7, 8]},
columns=['group', 'A', 'B'])
df
# group A B
# 0 g1 1 5
# 1 g2 2 6
# 2 g1 3 7
# 3 g2 4 8
grouped = df.groupby('group')
for name, group in grouped:
print(name)
print(group)
print('')
# g1
# group A B
# 0 g1 1 5
# 2 g1 3 7
#
# g2
# group A B
# 1 g2 2 6
# 3 g2 4 8
pivot_table()を使うともっと簡単。
pvTbl = pd.pivot_table(df,values=['A','B'],index='group',aggfunc='sum')
# values : 集計対象のカラムを指定、list or str
# index : 集計キー(list or str)
# aggfunc : mean , sum など集計方法を指定
pvTbl.reset_index(inplace=True) # 元の状態だと 集計キーをdataFrameのindexとして使用できないため、indexを解除)
さっとグループごとの平均を計算
grouped = df.groupby('group')
grouped.apply(np.mean)
# A B
# group
# g1 2 6
# g2 3 7
5.データ連結 (Hlookup, Vlookup的な)
行(縦)方向に連結
pd.concat([df1, df2 (,・・・)])
df1.append(df2)
df1.append([df2, df4])
1行だけ追加も同じように
s1 = pd.Series(['X0', 'X1', 'X2', 'X3'],
index=['A', 'B', 'C', 'D'], name=10) # nameはラベル名
df1.append(s1)
*列名が異なる場合は、一方がNaNで埋められる
横方向の連結
pd.concat([df1, df4], axis=1)
pd.concat([df1, df4], axis=1, join='inner') # inner join的な(共通indexのみ)
pd.concat([df1, df4], axis=1, join_axes=[df1.index]) # left join的な
横方向の連結(Vlookup的な 厳密にはjoin的な)
left = pd.DataFrame({'key': ['K0', 'K1', 'K2', 'K3'],
'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3']})
right = pd.DataFrame({'key': ['K1', 'K3', 'K5', 'K7'],
'C': ['C1', 'C3', 'C5', 'C7'],
'D': ['D1', 'D3', 'D5', 'D7']},
index=[1, 3, 5, 7])
pd.merge(left, right, on='key', how='left’) # how: inner / left / right / outer
pd.merge(left, right, on=['key1', 'key2']) # 複数のキーによる結合も
参考:http://sinhrks.hatenablog.com/entry/2015/01/28/073327
その他:pivot_tableで集計してjoinする方法は以下を参照
https://teratail.com/questions/129198
6.統計処理
基本統計量
df.describe()
パーセンタイル(デシル)
def decile(pddata,targetCol,Sep=10,makeCol='decile'):
pd['decile'] = pd.qcut(pddata[targetCol], Sep, labels=np.arange(Sep, 0, -1))
return pd
相関行列
df.corr()