プログラミング

【Python】pandasでのデータ操作コマンド一覧まとめ

python eyecatch

pythonでデータを色々操作する時、モデリングする時、必ずと行っていいほどjupiterとpandasを使うと思います。

とは言っても、全てのコマンドを覚えているわけではないので、よく使うものはパワポにまとめて都度参照して使っていました。

この記事では、データの入出力・条件抽出など、各種操作別によく使うものを纏めておきました。

随時更新するかもしれません。

最初に読み込むコード: 事前準備

表示領域を広げる

%%HTML
<style>
    div#notebook-container    { width: 95%; }
    div#menubar-container     { width: 65%; }
    div#maintoolbar-container { width: 99%; }
</style> 

ノートの表示領域が広がります。

各種packageを読み込む

from plotly.offline import init_notebook_mode,iplot
import plotly.graph_objs as go
import plotly.plotly as py
from plotly import tools
from datetime import date
import pandas as pd
import numpy as np
import random
import warnings
warnings.filterwarnings("ignore")
init_notebook_mode(connected=True)
pd.set_option("display.max_rows", 5000) # 最大表示行数を5,000に指定
from IPython.core.display import display #display(dataframe)で複数df表示可能 

pandasとnumpyは必須かと思いますが、その他は必要に応じて読み込んだりしています。

ColumnとRowの表示件数設定

# Print all rows and columns
pd.set_option('display.max_columns', None)
pd.set_option('display.max_rows', None)

ただし、データ容量が大きくなる場合は使わないほうが良さげです。

matplotlibの設定

# matplotlib setting
import matplotlib.pyplot as plt
%matplotlib inline
from matplotlib import rcParams
plt.rcParams['font.family'] = 'IPAGothic'
plt.rcParams["figure.figsize"] = [20, 8] # グラフのサイズを指定
plt.rcParams['font.size'] = 20 # フォントサイズを設定 default : 12
plt.rcParams['xtick.labelsize'] = 18 # 横軸のフォントサイズ
plt.rcParams['ytick.labelsize'] = 18 # 縦軸のフォントサイズ
plt.rcParams['axes.labelsize'] = 18 # 軸ラベルのフォントサイズ
plt.rcParams['figure.titlesize'] = 30 # タイトルのフォントサイズ
plt.rcParams['axes.titlesize'] = 30 # タイトルのフォントサイズ
import seaborn as sns # seabornの読み込み 
import matplotlib.pyplot as plt
%matplotlib inline

これで、グラフをノート内に描画することが出来ます。デフォルトでは、別windowが立ち上がってしまい、不便かと思います。

その他グラフの設定は、状況に併せて個別に設定してください。

デフォルト値を直接操作する場合

毎回設定するのではなく、常にグラフ値を設定しておきたい場合は、”Users/username/.matplotlib/matplotlibrc“に設定することも出来ます。

DataFrameの詳細情報を取得する関数

DataFrameの詳細情報を取得する関数を事前に定義しておきます。

# Data Analysis Function
def get_dataframe_info(df_input):
    int_rows = df_input.shape[0]
    int_cols = df_input.shape
    flt_rows = float(int_rows)

    df_output = pd.DataFrame(columns=["Column", "Type", "Not Null", 'Null', '% Not Null', '% Null'])
    df_output.loc[0] = ['Table Row Count', '', int_rows, '', '', '']
    df_output.loc = ['Table Column Count', '', int_cols, '', '', '']
    int_table_row = 1

    for i in range(int_cols):
        str_column_name = df_input.columns.values[i]
        str_column_type = df_input.dtypes.values[i]
        int_not_null = df_input[str_column_name].count()
        int_null = sum( pd.isnull(df_input[str_column_name]))
        flt_percent_not_null = round(int_not_null / flt_rows * 100, 1)
        flt_percent_null = 100 - flt_percent_not_null
        int_table_row += 1
        df_output.loc[int_table_row] = [str_column_name, str_column_type, int_not_null, int_null, flt_percent_not_null, flt_percent_null]

    return df_output

そして、get_dataframe_info(df)で表示します。

シンプルなDataFrameの情報を取得するには、

# DataFrame Information
df_train.info() 

こんな感じです。

データの過疎具合・密度を確認する関数

# check data sparsity
def check_sparsity(df):
    non_zeros = (df.ne(0).sum(axis=1)).sum()
    total = df.shape*df.shape[0]
    zeros = total - non_zeros
    sparsity = round(zeros / total * 100,2)
    density = round(non_zeros / total * 100,2)
    print(" Total:",total,"\n Zeros:", zeros, "\n Sparsity [%]: ", sparsity, "\n Density [%]: ", density)

データに含まれるnullの件数などを把握するのに便利です。

カテゴリ変数系の関数

これらも事前に定義しておくと楽。

# カテゴリ変数を取得する関数
def _get_categorical_features(dataframe):
    feats = [col for col in list(dataframe.columns) if dataframe[col].dtype == 'object']
    return feats

# カテゴリ変数をファクトライズ (整数に置換)する関数
def _factorize_categoricals(dataframe, cats):
    for col in cats:
        dataframe[col], _ = pd.factorize(dataframe[col])
    return dataframe

# カテゴリ変数のダミー変数 (二値変数化)を作成する関数
def _get_dummies(dataframe, cats):
    for col in cats:
        dataframe = pd.concat([dataframe, pd.get_dummies(dataframe[col], prefix=col)], axis=1)
    dataframe = dataframe.drop(cats, axis=1)
    return dataframe

日付操作関連の関数

あるひとつのdatetimeが含まれるカラムがあって、そのダミー変数を作成したい場合に便利。

# Create year, month, day, weekday, hour, min, sec columns of particular column
def datetime_dummies(dataframe, date_col):
    import datetime
    dataframe[date_col+'_year'] = dataframe[date_col].dt.year
    dataframe[date_col+'_month'] = dataframe[date_col].dt.month
    dataframe[date_col+'_day'] = dataframe[date_col].dt.day
    dataframe[date_col+'_weekday'] = dataframe[date_col].dt.weekday
    dataframe[date_col+'_hour'] = dataframe[date_col].dt.hour
    dataframe[date_col+'_minute'] = dataframe[date_col].dt.minute
    dataframe[date_col+'_second'] = dataframe[date_col].dt.second

データ入力: Input

csv

めちゃくちゃ使う、はず。

pd.read_csv(
  ’test.csv’,
  encoding = ‘utf8’,
  dtype={‘Column Name’ : ‘object’, ‘Column Name’ : ’int64’},
  parse_date={‘Column Name’, ’Column Name’},
  usecols = ['a', 'c']
  ) 

tsv, excel, DataBase, xml, json, geojson, topojson

準備中。

データ操作: Row

条件抽出

df = df[df['Column'] = 'Value']

これもめちゃくちゃ使っている。特定のカラムが特定の値と一致するもの df[‘Column’] = ‘Value’を取得すると、trueとfalseのSeriesデータが取得出来る。それをさらにdfに当て込んで、trueのもののみ取得して、df変数に上書きしているという仕組み。

この例は一番シンプルな例。

サンプリング, ソート, 重複レコード, レコード集計, レコード連結

準備中。

レコード結合

# dataframe merge
pd.merge(left, right, on=‘key', how='left') #結合Keyが複数の場合はon=‘’にリストを渡す

詳細はいずれ更新予定。

データ操作: Column

カラム名変更

# Rename columns
df.rename(columns={'A': 'a', 'C': 'c'}, inplace=True)

# Change all at once
df_new = df.rename(columns=lambda s: s.upper(), index=lambda s: s.lower())

なんだかんだよく使う。

連続値をカテゴリ化して別のカラムを作成

# Ageが10未満なら1(child)、10以上なら0(adult)として、連続値をカテゴリ化
df['Age_Group'] = np.where(df['Age'] < 10, 1, 0)

モデリングするためのインプットデータとしてだったり、データを分類してvisualizationする時など、使う場面は結構ある印象。

フィルター, フィールド作成, 置換, 特定列の各値に関数適用, データ分割, データ区分, フラグ設定, 再構成(ダミーデータ作成), 行列入れ替え, フィーーるど順序

更新予定。

モデリング: Modeling

次元削減

# 次元削減 Scikit-learnのSelectKBestを使用する
from sklearn.feature_selection import SelectKBest, f_regression

y = df_train['target']
X = df_train.drop(['ID', 'target'], axis=1)

# 100の特徴量を選択
selector = SelectKBest(score_func=f_regression, k=100)
selector.fit(X, y)
mask = selector.get_support()    # 各特徴量を選択したか否かのmaskを取得

# 選択した特徴量の列のみ取得
X_selected = selector.transform(X)

# 選択した特徴量の列と目的変数で新規dfを作成
df_train_selected = pd.DataFrame(y)
df_train_selected = pd.concat(
    [df_train_selected, pd.DataFrame(X_selected, columns=X.columns[mask])],
    axis=1)

lightgbm

# lightgbmでの予測
import lightgbm as lgb
from sklearn.model_selection import train_test_split
from sklearn.metrics import mean_squared_error

# 説明変数
X = df_train.drop('target', axis=1)

# 目的変数
y = df_train['target']

# 訓練データとテストデータに分割する
X_train, X_val, y_train, y_val = train_test_split(X, y, test_size=0.2, random_state=0)

# データセットを生成する
lgb_train = lgb.Dataset(X_train, y_train)
lgb_eval = lgb.Dataset(X_val, y_val, reference=lgb_train)
# LightGBM のハイパーパラメータ
lgbm_params = {
    'task': 'train',
    'boosting_type':'gbdt',
    'objective': 'regression', # 回帰問題 multiclass
    'metric': 'mape', # RMSE (平均二乗誤差平方根) の最小化を目指す, rmse, mapeなど multi_logloss
    'learning_rate': 0.1,
    'num_leaves': 48,
    'num_iteration': 10000,
    'verbose': 0 ,
    'colsample_bytree':.8,
    'subsample':.9,
    'max_depth':7,
    'reg_alpha':.1,
    'reg_lambda':.1,
     'min_split_gain':.01,
    'min_child_weight':1
}
# 上記のパラメータでモデルを学習する
model = lgb.train(lgbm_params, lgb_train, valid_sets=lgb_eval, early_stopping_rounds=150, verbose_eval=1000)

lightgbmでの説明変数の重要度をvisualize

# plot importance of exlanatory valiables
lgb.plot_importance(model, figsize=(12, 50));

分類器の結果確認

# Crosstab
pred_Y = model.predict(X)
pred_Y = np.where(pred_Y > 0.5, 1, 0)
pd.crosstab(Y, pred_Y)

単純重回帰モデルでの予測

# Modeling - Start 

# 単純重回帰モデルでの予測
from sklearn import linear_model

# モデル構築変数
clf = linear_model.LinearRegression()

# 説明変数
X = df_for_model_for_input.drop('目的変数', axis=1).as_matrix()

# 目的変数
Y = df_for_model_for_input['目的変数'].as_matrix()

# 予測モデルを作成
clf.fit(X, Y)
print('Count: ' + str(len(df_for_model)))

# Regression Coefficients
model_regression_coefficients =  pd.DataFrame(
    {"Name":df_for_model_for_input.drop('目的変数', axis=1).columns, "Coefficients":clf.coef_}).sort_values(by='Coefficients')    

# Intercept
model_intercept = clf.intercept_
print("Intercept: " + str(model_intercept))

# R^2
model_r2 = clf.score(X, Y)
print("R^2: " + str(model_r2))

# Residual
pred_y = clf.predict(X)
model_mae = np.average(abs(Y - pred_y))
model_mape = np.average(abs((Y - pred_y)/Y))
print("MAE: " + str(model_mae))
print("MAPE: " + str(model_mape))

print('----------------------------------------------------------------')
# Modeling - End

その他随時アップデート予定。

データビジュアライゼーション: Data Visualization

シンプルなヒストグラム

# Histogram
sns.distplot(df['Column'].dropna(), kde=False, rug=False, bins=30)

目的変数のヒストグラム

# 目的変数のヒストグラム
plt.figure(figsize=(20,8)) #グラフ全体の縦横設定
plt.title(‘Distribution of target’, fontsize=18) #タイトルとタイトルのフォントサイズ設定
plt.tick_params(labelsize=18) #tick_paramの文字サイズ設定
sns.distplot(df_train['target'], bins=100, kde=False)

ヒートマップ

# 目的変数・説明変数の相関係数をHeatmapで可視化
df_corr = df_train.drop('Column', axis=1).corr()
sns.heatmap(df_corr, square=True, vmax=1, vmin=-1, center=0)
# param
#数値を表示: annot
#カラーバー表示・非表示: cbar
#正方形で表示: square
#最大値、最小値、中央値を指定: vmax, vmin, center
#色(カラーマップ)を指定: cmap

散布図: scatter plot

# 予測結果の確認 散布図
plt.scatter(y_test, y_pred)
plt.plot([10,18], [10,18], c='navy') # 直線の描画
plt.show()

# 予測元の分布
sns.distplot(y_test)
sns.distplot(y_pred)

重回帰などで予測結果をグラフで確認する時によく使う。

データ出力: Display

テーブル表示

よく使うのとしては、headとtail

# データの先頭n件を表示
df.head()

# データを後ろからn件表示
df.tail(20)

引数として数値を渡せばその件数表示してくれれる。

クロス集計

更新予定。

データエクスポート: Export

csv

df.to_csv('output.csv', index=False)

オプションとして、index=Falseで、1列目に不要な番号が表示されなくなります。

tsv, excel, DataBase, xml, json

更新予定。

またそのうち追記していきます。