翔泳社「現場で使える！pandasデータ前処理入門 機械学習・データサイエンスで役立つ前処理手法」のpandas ver2対応メモ

# 概要

翔泳社「[現場で使える！pandasデータ前処理入門 機械学習・データサイエンスで役立つ前処理手法](https://www.shoeisha.co.jp/book/detail/9784798160672)」（株式会社ロンバート著・2020年4月20日発売）を読んでpandasを勉強していますが、この本で扱っているpandasのバージョンが0.22.0と古いため、最新バージョンのpandasではサンプルコードが動かないところが多々ありました。
本記事では、執筆時点で最新のpandas2.0.3で本書と同等の実行結果を出力させるにはどのようにコードを書けばよいのかをまとめました。

※あくまで自分用のメモなので参考程度でお願いします。
**※3.2.4 HDF5（P223～231）の項目は扱っていないのでご了承ください。**

![現場で使える！pandasデータ前処理入門 機械学習・データサイエンスで役立つ前処理手法.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/667062/5ac8c752-399c-dae8-1d92-6fde092a3540.png)

↑この本です。扱っているpandasのバージョンが古い点以外は内容も充実しており気に入ってます。今からpandasを学ぶ人は最近出た本を選んだ方がいいかもしれないですが…

# pandas ver2対応メモ

▼リスト2.31（P79）
```
ser2 = pd.Series([5, 6], index=['い','う'])
# ser.append(ser2)
pd.concat([ser,ser2], axis=0)
```
Series.append は v1.4 で非推奨になり、v2で削除されました。
代わりにconcatを使用しましょう。
なお、axis=0は省略可能です。
append→concatは今後もかなり出てきます。毎回説明しているとキリがないので次以降は説明省略します。

▼リスト2.32（P80）
```
# ser.append(ser2, ignore_index=True)
pd.concat([ser,ser2], axis=0, ignore_index=True)
```

▼リスト2.64（P100）
```
val = [7,8,9,10,11]
idx = [0,1,2,'new1','new2']
series_add = pd.Series(val, index=idx, name='new3')
# df = df.append(series_add)
df = pd.concat([df,series_add.to_frame().T], axis=0)
df
```

▼リスト2.78（P110）
```
idx1 = pd.Index([1,7,2,3,5])
idx2 = pd.Index([3,4,1,5,6])

# print(idx1 & idx2)
# print(idx1 | idx2)
print(idx1.intersection(idx2))
print(idx1.union(idx2))
```

&の代わりにintersection、|の代わりにunionを使用します。&や|を使用してもエラーにはなりませんが、意図した実行結果になりません。

▼リスト2.83（P112）
```
# idx_date = pd.DatetimeIndex(
idx_date = pd.date_range(
    freq='D',
    start='2018-12-28',
    end='2019-01-05'
)

idx_date
```

pd.DatetimeIndexの代わりにpd.date_rangeを使用します。引数は同じで大丈夫です。

▼リスト2.85（P113）
```
# df_date['2019']
df_date.loc['2019']
```
上だとKeyErrorで怒られます。locを使えば大丈夫なようです。

▼リスト2.124（P138）
```
grouped = df.groupby('sex')
# grouped.mean()
grouped.mean(numeric_only=True)
```
numeric_only引数をTrueにすると、要素が数値型のカラムのみが対象になります。
v1まではnumeric_only=Trueがデフォルトなので省略可能でしたが、v2ではnumeric_only=Falseがデフォルトになったので明示的に指定しないとエラーになります。
numeric_only=Trueもappend→concat同様多く登場します。毎回説明しているとキリがないので次回以降は説明省略します。

▼リスト3.54（P184）
```
# pd.read_csv('../data/ex2.csv', usecols=['weight'], squeeze=True)
pd.read_csv('../data/ex2.csv', usecols=['weight']).squeeze()
```
squeeze引数はv1.5で非推奨になり、v2で削除されたようです。
代わりにpandas.DataFrame.squeezeを使用します。

▼リスト3.73（P197）
```
pd.read_csv('../data/ex5.csv',
            # error_bad_lines=False,
            # warn_bad_lines=True)
            on_bad_lines='warn')
```
error_bad_linesとwarn_bad_linesはv1.3で非推奨となり、v2で削除されたようです。
代わりにon_bad_lines引数を使用します。

▼リスト3.77（P199）
```
# pd.read_csv('../data/ex7.csv', mangle_dupe_cols=True)
pd.read_csv('../data/ex7.csv')
```

mangle_dupe_cols引数はv1.5時点で非推奨となり、v2で削除されたようです。
v2ではそのまま読み込めば大丈夫なようです。

▼リスト4.48（P266）
```
# pd.pivot_table(df, index='sex', aggfunc=np.mean)
pd.pivot_table(df, index='sex', aggfunc=np.mean, values=['art','eng','hist','math','scie'])
```
values引数を指定します。

▼リスト5.6（P289）
```
# df.append(df2)
pd.concat([df,df2])
```

▼リスト5.7（P290）
```
# df.append(df2, ignore_index=True)
pd.concat([df,df2], ignore_index=True)
```

▼リスト5.8（P290）
```
df3 = pd.DataFrame([[7,8,9]],columns=['a','b','c'])
# df.append(df3)
pd.concat([df,df3])
```

▼リスト5.25（P302）
```
# pd.concat([df1,dft], axis=1, join_axes=[df1.index])
pd.concat([df1,dft], axis=1).loc[df1.index,:]
```

▼リスト5.28（P304）
```
# df1.append(df2)
pd.concat([df1,df2],axis=0)
```

▼リスト5.29（P305）
```
# df1.append(df2, ignore_index=True)
pd.concat([df1,df2], axis=0, ignore_index=True)
```

▼リスト5.30（P305）
```
dft = df2.copy()
dft.columns = ['a','b','d']
# df1.append(dft.loc[0,:])
pd.concat([df1,dft.loc[0,:].to_frame().T], axis=0)
```

▼リスト5.31（P306）
```
ser1 = pd.Series(['s1','s2','s3'])
ser2 = pd.Series(['s4','s5','s6'])
# ser1.append(ser2)
pd.concat([ser1,ser2], axis=0)
```

▼リスト5.32（P307）
```
ser1.index = ['a','b','c']
ser1.name = 'ser1'
# df1.append(ser1)
pd.concat([df1,ser1.to_frame().T], axis=0)
```

▼リスト5.36（P313）
```
ser1 = pd.Series(['a3','b3','left_k3'],index=['a','b','key'])
# leftdf = leftdf.append(ser1, ignore_index=True)
leftdf = pd.concat([leftdf,ser1.to_frame().T], axis=0, ignore_index=True)
leftdf
```

```
ser2 = pd.Series(['c3','d3','right_k3'],index=['c','d','key'])
# rightdf = rightdf.append(ser2, ignore_index=True)
rightdf = pd.concat([rightdf,ser2.to_frame().T], axis=0, ignore_index=True)
rightdf
```

▼リスト7.33（P407）
```
# for idx, val in ser.iteritems():
for idx, val in ser.items():
    print(idx, val)
```

▼リスト7.34（P408）
```
# for idx, val in ser.iteritems():
for idx, val in ser.items():
    if val < 3:
        print(idx)
```

▼リスト7.44（P414）
```
# for col, val in df.iteritems():
for col, val in df.items():
    print(col)
    print(val, '\n')
```

▼リスト7.45（P415）
```
# for col, val in df.iteritems():
for col, val in df.items():
    mean = val.mean()
    print(col, 'の平均点は', mean)
```

▼リスト7.56（P423）
```
# grouped.mean()
grouped.mean(numeric_only=True)
```

▼リスト7.60（P425）
```
grouped = df.groupby(['sex','club'])
# grouped.mean()
grouped.mean(numeric_only=True)
```

▼リスト7.61（P426）
```
grouped = df.groupby(['sex','club'], as_index=False)
# grouped.mean()
grouped.mean(numeric_only=True)
```

▼リスト7.65（P428）
```
# df2.groupby(by='club').mean()
df2.groupby(by='club').mean(numeric_only=True)
```

▼リスト7.66（P428）
```
# df2.groupby(level=0).mean()
df2.groupby(level=0).mean(numeric_only=True)
```

▼リスト7.75（P433）
```
grouped = df.groupby('sex')
# grouped.mean()
grouped.mean(numeric_only=True)
```

```
# grouped.agg('mean')
grouped.agg('mean', numeric_only=True)
```

▼リスト7.76（P434）
```
# grouped.agg(np.mean)
grouped[['math','eng','scie']].agg(np.mean)
```

▼リスト7.80（P436）
```
# grouped.agg(max_min)
grouped[['math','eng','scie']].agg(max_min)
```

▼リスト7.81（P437）
```
# df.groupby(['sex','club']).agg(['mean','sum'])['math']
df.groupby(['sex','club'])[['math','eng','scie']].agg(['mean','sum'])['math']
```

▼リスト7.85（P439）
```
df2 = df.copy()
# df2['カテゴリ別平均'] = grouped.transform(lambda x: x.mean())
df2['カテゴリ別平均'] = grouped['sales'].transform(lambda x: x.mean())
df2
```

▼リスト7.86（P440）
```
# df2['万'] = grouped.transform(lambda x: x / 10000)
df2['万'] = grouped['sales'].transform(lambda x: x / 10000)
df2
```

▼リスト7.87（P441）
```
df2 = df.copy()
# cat_total = df2.groupby('category').sum()
cat_total = df2.groupby('category')[['sales']].sum()
cat_total.columns = ['cat_total']
cat_total
```

▼リスト7.91（P444）
```
# %timeit df.groupby('sex').apply(lambda x: x.mean())
# %timeit df.groupby('sex').mean()
%timeit df.groupby('sex')[['math','eng','scie']].apply(lambda x: x.mean())
%timeit df.groupby('sex').mean(numeric_only=True)
```

▼リスト7.97（P448）
```
# mean = round(df2.mean())
mean = round(df2.mean(numeric_only=True))
mean
```

▼リスト7.98（P448）
```
# df2.groupby('club').mean()
df2.groupby('club').mean(numeric_only=True)
```

▼リスト7.99（P449）
```
grouped = df2.groupby('club')
# grouped.apply(lambda x: x.fillna(x.mean()))
grouped.apply(lambda x: x.fillna(x.mean(numeric_only=True)))
```

▼リスト8.20（P463）
```
# df['class'] = df['class'].str.replace(pat=pattern, repl='')
df['class'] = df['class'].str.replace(pat=pattern, repl='', regex=True)
df
```

▼リスト8.75（P506）
```
# midx.labels
midx.codes
```

▼リスト8.94（P518）
```
# df.index.is_lexsorted()
```
```
# df.sort_index(level=0).index.is_lexsorted()
```

index.is_lexsortedは廃止されたようです。代替手段は不明です。

▼リスト8.101（P522）
```
df.loc[[('Sapporo','M','Marketing'),
        # ('Sapporo','F','Marketing'),
        ('Tokyo','F','Marketing'),]]
```
現在のバージョンでは、インデックスラベルに含まれていない場合はKeyErrorを返すようです。

▼リスト8.109（P526）
```
print(df2.index.levels[0])
# print(df2.index.labels[0])
print(df2.index.codes[0])
df2
```

▼リスト8.110（P527）
```
# df2.index = df2.index.set_labels(labels=[1,1,1,0,0,2,2],
df2.index = df2.index.set_codes(codes=[1,1,1,0,0,2,2],
                                 level=0)
df2
```

▼リスト8.116（P531）
```
# df['age'].mean(axis=0, level='address')
df['age'].groupby('address').mean()
```

▼リスト8.117（P531）
```
# df['age'].mean(axis=0, level=['address','sex'])
df['age'].groupby(['address','sex']).mean()
```

▼リスト8.118（P532）
```
# df.mean(level='sex')
```
DataFrame.mean()のlevel引数は削除されたっぽいです。同ページに記載されているgroupbyメソッドのやり方を使用しましょう。

▼リスト8.143（P547）
```
# ts.week, ts.dayofweek, ts.weekday_name
ts.week, ts.dayofweek, ts.day_name()
```

▼リスト8.150（P550）
```
# pd.DatetimeIndex(start='20190101', end='20190105', freq='D')
pd.date_range(start='20190101', end='20190105', freq='D')
```

▼リスト8.151（P551）
```
# pd.DatetimeIndex(start='20190101', periods=5, freq='W-SUN')
pd.date_range(start='20190101', periods=5, freq='W-SUN')
```

▼リスト8.164（P557）
```
# pd.PeriodIndex(start='2019-Apr', periods=5, freq='M')
pd.period_range(start='2019-Apr', periods=5, freq='M')
```

▼リスト8.168（P559）
```
# pd.DatetimeIndex(start='20190501 17:00', periods=5, freq='H')
pd.date_range(start='20190501 17:00', periods=5, freq='H')
```

```
from pandas.tseries.offsets import Hour
# pd.DatetimeIndex(start='20190501 17:00', periods=5, freq=Hour())
pd.date_range(start='20190501 17:00', periods=5, freq=Hour())
```

▼リスト8.170（P560）
```
# pd.DatetimeIndex(start='20190501 17:00', periods=5, freq=5 * Hour())
pd.date_range(start='20190501 17:00', periods=5, freq=5 * Hour())
```

▼リスト8.171（P561）
```
# pd.DatetimeIndex(start='20190501 17:00', periods=5, freq='5H')
pd.date_range(start='20190501 17:00', periods=5, freq='5H')
```

▼リスト8.172（P561）
```
# pd.DatetimeIndex(start='20190501 17:00', periods=5, freq=hours_minutes)
pd.date_range(start='20190501 17:00', periods=5, freq=hours_minutes)
```

▼リスト8.173（P562）
```
# pd.DatetimeIndex(start='20190501 17:00', periods=5, freq='3h20min')
pd.date_range(start='20190501 17:00', periods=5, freq='3h20min')
```

▼リスト8.174（P562）
```
# pd.DatetimeIndex(start='20110501', periods=2, freq='A-DEC')
pd.date_range(start='20110501', periods=2, freq='A-DEC')
```

```
from pandas.tseries.offsets import YearEnd
# pd.DatetimeIndex(start='20110501', periods=2, freq=YearEnd())
pd.date_range(start='20110501', periods=2, freq=YearEnd())
```

▼リスト8.175（P563）
```
# pd.DatetimeIndex(start='20110501', periods=2, freq='AS-JAN')
pd.date_range(start='20110501', periods=2, freq='AS-JAN')
```

```
from pandas.tseries.offsets import YearBegin
# pd.DatetimeIndex(start='20110501', periods=2, freq=YearBegin())
pd.date_range(start='20110501', periods=2, freq=YearBegin())
```

▼リスト8.179（P567）
```
# ser[datetime.date(2019,1,2)]
```

これはKeyErrorになります。代替手段は不明です。

▼リスト8.185（P570）
```
# df['2018-12-31 23']
df.loc['2018-12-31 23']
```

▼リスト8.190（P573）
```
# ser.tshift(-2)
```

Series.tshiftは廃止されたぽいです。リスト8.191の方法を使いましょう。

▼リスト9.22（P601）
```
# df.corr().style.background_gradient(cmap='coolwarm')
df.corr(numeric_only=True).style.background_gradient(cmap='coolwarm')
```

▼リスト9.29（P611）
```
# df.groupby('年代').sum()
df.groupby('年代').sum(numeric_only=True)
```

▼リスト9.101（P661）
```
time['Year'] = time.index.year
time['Month'] = time.index.month
time['Day'] = time.index.day
# time['Weekday'] = time.index.weekday_name
time['Weekday'] = time.index.day_name()
time['Hour'] = time.index.hour
time.head(3)
```

# 参考文献

[pandas documentation — pandas 2.0.3 documentation](https://pandas.pydata.org/docs/)
[【保存版】Pandas2.0のread_csv関数の全引数、パフォーマンス、活用テクニックを完全解説する！ - Qiita](https://qiita.com/fujine/items/dbe2f5e4101d6299ff12)