はじめに
Pandasは、Python環境において高速で強力がかつ使いやすいデータ分析・操作ツールです。pipコマンドでかんたんにインストールできます。
pip install pandas
コード内でPandasを使用する場合は、まずインポートを行います。
import pandas as pd
本記事では、頻繁に使用される12のデータ処理操作を紹介します。
# サンプルデータの作成
sample_data = pd.DataFrame({
'x': [1, -3, 0, 1, 3],
'y': [-1, 0, 1, 5, 1],
'z': [0, -2, 0, -9, 0]
})
sample_data
実践的テクニック
1. 負の数の出現回数をカウントする
行ごとの負の数をカウントするには、比較演算とastype変換、sum関数を組み合わせます。列ごとにカウントする場合はaxisを0に変更します。
# 各行の負の値の数を集計
negative_counts = (sample_data < 0).astype(int).sum(axis=1)
negative_counts
2. 正の数を0に置き換える
条件に基づく値の一括変更は、条件式をブールインデックスとして直接使用できます。
# 正の値を持つ要素をすべて0に設定
sample_data[sample_data > 0] = 0
sample_data
3. 列内の要素出現頻度を統計する
value_countsメソッドは、指定列の要素出現回数を返します。
# y列の各要素出現回数
sample_data['y'].value_counts()
binsパラメータを使用すると、値を指定した数の区间に分割して出現回数をカウントできます。
# 3つの区间に分割して出現回数をカウント
sample_data['y'].value_counts(bins=3)
normalize=Trueを設定すると、出現回数の全体に対する割合が返されます。
# 出現回数の割合を表示
sample_data['y'].value_counts(normalize=True)
4. 列名とインデックスを変更する
列名のリネーム
renameメソッドで列名を変更できます。inplace=Trueで元のDataFrameを更新します。
# 列名を変更
new_columns = {'x': 'X', 'y': 'Y'}
sample_data.rename(columns=new_columns, inplace=True)
sample_data
インデックスの設定
# 任意のインデックスを設定
sample_data.index = ['row1', 'row2', 'row3', 'row4', 'row5']
sample_data
インデックスのリセット
# インデックスをリセット
sample_data.reset_index(drop=True, inplace=True)
sample_data
5. 列の位置を変更する(insert+pop)
insertメソッドは指定位置に列を挿入し、popメソッドは列名を取得しつつその列を削除します。
# X列を3列目の最後に移動
sample_data.insert(2, 'X', sample_data.pop('X'))
sample_data
6. クエリによるデータ抽出
queryメソッドを使うと、文字列で条件指定できます。
# z列の値が0未満の行を抽出
sample_data.query("z < 0")
str.containsを組み合わせると、部分一致検索が可能です。
# name列を追加
sample_data.insert(0, 'name', ['田中', '田中', '鈴木', '山本', '田中'])
# 文字列を含むレコードを抽出
sample_data.query("name.str.contains('田|山|藤')", engine='python')
7. CSV保存時にインデックスを含めない
to_csvメソッドでindex=Noneを指定すると、インデックス列が保存されません。
sample_data.to_csv('output_data.csv', encoding='utf-8-sig', index=None)
8. 指定列でデータをソートする
sort_valuesメソッドで指定列に基づいて並べ替えられます。ascendingパラメータで昇順・降順を切り替え、na_positionでNaN値の配置位置を指定できます。
# name列でソート(NaNは先頭に配置)
sample_data.sort_values(by=['name'], na_position='first')
9. apply関数の活用
apply関数は、各行または列に対して関数を適用できます。
# X列とY列の各要素に1を加算
sample_data[['X', 'Y']].apply(lambda val: val + 1)
# applyメソッドの書式
DataFrame.apply(func, axis=0, raw=False, result_type=None, args=())
10. データのマージ(結合)
複数のDataFrameを結合する際は、concat関数を使用します。事前に結合対象をリストに格納します。
# 部分的にDataFrameを分割
part1 = sample_data[0:1]
part2 = sample_data[2:4]
part3 = sample_data[3:5]
# リストに格納して結合
combined_frames = [part1, part2, part3]
merged_data = pd.concat(combined_frames)
merged_data
11. DataFrameのコピー(ディープコピーとシャローコピー)
ディープコピー
copy(deep=True)で作成したコピーは、元のDataFrameとは独立したオブジェクトになります。
# ディープコピーの作成
original_copy = sample_data.copy(deep=True)
print(f"元データ:\n{sample_data}\nコピー:\n{original_copy}")
元のname列の最初の要素を変更しても、コピーには影響しません。
sample_data['name'][0] = '佐藤'
print(f"元データ:\n{sample_data}\nコピー:\n{original_copy}")
シャローコピー
copy(deep=False)またはcopy()はシャローコピーを作成します。データは共有されます。
# シャローコピーの作成(sample_data == shared_ref)
shared_ref = sample_data.copy(deep=False)
print(f"元データ:\n{sample_data}\n共有参照:\n{shared_ref}")
元のname列を変更すると、共有参照先も一緒に変更されます。
sample_data['name'][0] = '高橋'
print(f"元データ:\n{sample_data}\n共有参照:\n{shared_ref}")
12. 行・列の操作
行・列の削除
dropメソッドで行または列を削除できます。axis=0は行、axis=1は列を示します。
# z列を削除
sample_data.drop('z', axis=1, inplace=True)
sample_data
行・列の抽出
# 末尾2列を抽出
last_two_cols = sample_data.iloc[:, -2:]
print(f"末尾2列:\n{last_two_cols}")
# 特定列を抽出
named_cols = sample_data.loc[:, ['name', 'X']]
print(f"指定列:\n{named_cols}")
# インデックスを再設定
sample_data.index = ['idx1', 'idx2', 'idx3', 'idx4', 'idx5']
# 先頭2行を抽出
first_rows = sample_data.iloc[:2, :]
print(f"先頭2行:\n{first_rows}")
# 特定行を抽出
selected_rows = sample_data.loc[['idx1', 'idx3'], :]
print(f"指定行:\n{selected_rows}")
列間の値入れ替え
条件に基づいて2列間の値を交換できます。
# Y列で負の値を持つ行を特定
mask = sample_data['Y'].astype(int).map(lambda v: v < 0)
# 条件に一致する行でX列とY列の値を交換
sample_data.loc[mask, 'Y'], sample_data.loc[mask, 'X'] = sample_data.loc[mask, 'X'], sample_data.loc[mask, 'Y']
sample_data