LoginSignup
13
15

More than 1 year has passed since last update.

MLエンジニアのためのコード辞典

Last updated at Posted at 2019-04-07

随時更新

リンク

文字列処理
NAとInf処理
演算処理
削除処理
作成処理
変更処理
EDA
PyplotとSeaborn
出力処理
特徴量生成とエンコーディング
numpy arrayとlist
ファイルの読み書き
その他

文字列処理

特殊文字の除去

65%,78%...85%の%を取り除きたい

# 例1:
# r'\%'のところはpythonの正規化
df['a'] = df['a'].str.replace(r'%', '')

# 例2:
# 2020年1月1日を 2020/1/1 に変えたいとき
df['date'] = df['date'].str.replace(r'[年,月]', '/')
df['date'] = df['date'].str.replace(r'[日]', '')

特殊文字の置き換え

appleかorangeかlemonの値はfruitsに置き換えたい

df['title'] = df['title'].str.replace(r'apple|orange|lemon', 'fruits')

日付から年・月・日を取り出す


date = '12/01/02'
result = date.split('/')
print(result)


# ちなみに特徴量も作れる。
df[['year','month','date']] = df['date'].str.split('/', expand=True)

結果


['12', '01', '02']

列内の要素に特定の文字があるか否かを確かめる

例えばforでループを回して列内を一つ一つチェックすることもできる。

#thousandsかmillionという文字が列の0番目の行に入っている場合
if '文字1' in df['volume'].iloc[0]:
   #何かする
elif '文字2'in df['volume'].iloc[0]:
   #何かする

特定の文字が入っている行だけを列内から抽出する


new_df = df[df['a'].str.contains("文字")]

参照:http://pandas.pydata.org/pandas-docs/stable/user_guide/text.html

もし特定の列に特定の文字が含まれていたら文

もし特定の列に特定の文字が含まれていたら、その文字を含んでいる行に何かをする。

if df['bas_toho1'].str.contains('徒歩').any():
   do something

違う文字列に対して違う値を割り振る

dct = {
    'Miss':1,
    'Ms':1,
    'Mr':2,
}

train['title'] = 0
test['title'] = 0

for key, value in dct.items():
train.loc[train[train['Name'].str.contains(key,regex=False)].index,'title'] = value
    test.loc[test[test['Name'].str.contains(key,regex=False)].index, 'title'] = value

NAとInf処理

N/Aを数える

print(df['levelplan'].isna().sum())

N/Aを埋める

df.fillna(0,inplace=True)
df['a'].fillna(df['a'].mode()[0],inplace=True)

#複数の時。inplaceだとfillnaしないので注意
df[['a', 'b']] = df[['a','b']].fillna(-1)

#NAを他の特徴量の値で埋める
# Ageの列でNaNとなっている行をfill_ageの列の値で埋める
train_test['Age'] = train_test['Age'].fillna(train_test['fill_age'])

NAの詳細カウント

特徴(Column)毎にどれくらい紛失データがあるのかをランキングで出力

array = np.array([[1,2,3],[4,np.nan,6],[7,np.nan,np.nan]])
df_train = pd.DataFrame(array, columns=['a','b','c'])

total = df_train.isnull().sum().sort_values(ascending=False)
percent = (df_train.isnull().sum()/df_train.isnull().count()).sort_values(ascending=False)
missing_data = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])

print(missing_data.head(3))

結果

#列 #紛失データ数 #紛失データの割合
      Total      Percent
  b      2       0.666667
  c      1       0.333333
  a      0       0.000000

finiteの詳細カウント

total = np.isfinite(train_X["label_5"]).sum().sort_values(ascending=False)
percent = (np.isfinite(train_X["label_5"]).sum()/np.isfinite(train_X["label_5"]).count()).sort_values(ascending=False)
finite_data = pd.concat([total, percent], axis=1, keys=['Total', 'Percent'])

print(finite_data)

inf除去

df = df.replace([np.inf, -np.inf], np.nan)

NaNが入っている列をリスト形式で出力する


print(df.columns[df.isna().any()].tolist())

NaNが入っている行だけを抽出する


train = train[train.isnull().any(axis=1)]

演算処理

列の掛け算

df['number'] = df['number']*100
df['number'] *=100

一部のインデックスの列を演算する


for i in range(segments):
    train_y.loc[i, 'a'] = df['a'].iloc[i*149999]

列の順番を変更

dfの列の順番がグチャグチャなので並び替えたい

列の順番 first,third,secondからfirst,second,thirdに直す


df = df[['first', 'second', 'third']]

削除処理

無駄な特徴量を除去する

features = [c for c in train_df.columns if c not in ['ID_code', 'target']]
df = df[features]

特定の行を削除

df = pd.DataFrame(np.array([1,2,3]))

# 最初のインデックスの行を削除
df.drop([1], inplace=True)

# 複数のインデックスの行を削除
df.drop([1,2], inplace=True)

# ラストの行を削除
df.drop(df_train.tail(1).index,inplace=True)

インデックスがラベル名の場合
#df.drop('label',axis=1,inplace=True)

# 条件付き
#df.drop(df[(df['col1'] < 60) & (df1['col1'] > 40)].index, inplace=True)

特定の列を削除

df.drop('a', axis=1, inplace=True)

#複数列の削除
df.drop(['a','b'], inplace=True)

列の重複除去

df.drop_duplicates('column_1',inplace=True)

2つのコラムで同じ値になっている行を削除する

table = table.query("col1_1 != col1_2 and col2_1 != col2_2")

作成処理

dfの作成

df = pd.DataFrame(columns=['a'])
df = pd.DataFrame([[1],[2],[3]],columns=['a'])
#df = pd.DataFrame()
#df = pd.DataFrame(data={'a':ac,'count':1},index=range(rows))
#data=を付けないとaがindexになってしまうので注意
#またdata内のインデックスとindex=のインデックスが合わないと値がNaNになってしまう#ので注意

同じ特徴量とサイズを持っている空のDataFrameを生成する

new_df = df.mask(df.notna())

dfのコピー


# ポインターコピー (新しい変更は元のdfにも適用される。ただし値の変更のみ。新しい行の追加などは反映さ# れない)
copy_df = df

# 値だけコピー (新しい変更は元のdfに適用されない)
new = old.copy()

# 特定の列だけ値コピー
# 書き方1
new = old[['a', 'c', 'd']].copy()

# 書き方2
new = old.drop('b', axis=1)

列を指定した空のDataFrameの作成


df = pd.DataFrame(columns=['col1','col2'])

# もし他のデータフレームの列をコピーしたい場合
new_df = pd.DataFrame(columns=df.columns.values)

Numpy Array作成

データサイズが分かっていない場合


array = np.empty(shape=(0))
array = np.append(array, 2)
print(array)  #array = [2]

データサイズが分かっている場合


array = np.zeros(shape=(3))
array[0] = 2
print(array) #array = [2,0,0]

DataFrameの追加

df1 = pd.DataFrame(columns=['a','b','c'])

# scalarで入れるとindexを指定しないといけないので、リストで入れる。
df1 = df1.append(pd.DataFrame({'a':[1],'b':[2],'c':[3]}),ignore_index=True)

#それかindexを指定する。ignore_indexがあるので一つずつ入れるとインデックスも一つずつ増え #ていく
df1 = df1.append(pd.DataFrame({'a':1,'b':2,'c':3},index=[0]),ignore_index=True)


#    a  b  c
# 0  1  2  3

df = df.append(df1)

サイズが不均等なNumpy arrayの塊を一つずつ同じDataFrameに入れる

#Data Frameの初期化
df = pd.DataFrame()

#サイズがそれぞれ合わない不均等なデータ
array = np.array([[1,9],[3,4,5],[3]])

for i in range(len(array)):
    #要素に対してData Frameを作り、既存のData Frameに加える
    new_df = pd.DataFrame({'a':array[i]})
    df = df.append(new_df)

print(df)

結果

   a
0  1
1  9
0  3
1  4
2  5
0  3

DataFrame → Numpy array


array = df.values

#dfのcolumn内のvalues
col_array = df.columns.values

0で埋めた新しい列を追加する


df['new'] = np.zeros(shape=(df.shape[0]))

結果


      a  b  c  new
0     0  1  2  0.0
1     3  4  5  0.0
2     5  5  5  0.0
3     4  5  4  0.0
4    52  1  1  0.0

変更処理

インデックスでフィルター


x = pd.DataFrame([1,1,1])

x = x.iloc[[1,2]]

二つのデータフレーム内で共通している行だけを取り出す

# AコラムとBコラムで共通しているdf1内の行を取り出す。
df1 = df1[(df1['A'].isin(df2['A'])) & (df1['B'].isin(df2['B']))]

DataFrameに任意の行を追加する


df = df.append({'col1':1,'col2':2}, ignore_index=True)

2つのコラムに渡って重複している行を取り出す

train_df = train_df[train_df.duplicated(subset=['co1','col2'],keep=False)]
# 単に重複している行を取り出したい場合
print(df[df.duplicated(keep=False)])

dtypeを利用したif分

for col in df.select_dtypes(['float32']).columns.values:
  # df[col] = something 

df = df.select_dtypes(include=["float64"])

列の値から数字だけを取り出して新たな列を作る


df['col2_num'] = df['col2'].str.extract('(\d)')

date time オブジェクトに変更する

df[:, "date"] = pd.to_datetime(df.loc[:, "str_date"])

dfから抽出した一つの列を(seriesではなく)dfに保つ方法

# train_y = train['target']だとtrain_yはseriesになってしまう
# []で囲むことでdataframeに保つことが出来る。
train_y = train[['target']]

条件付きDataFrame加工

Column cが10以上ならTargetを1、それ以下なら0にして追加する。

条件が一つの場合

df = pd.DataFrame(np.array([[1,2,3],[4,5,50]]), columns=['a','b','c'])

df['target'] = np.where(df['c'] > 10.0, 1, 0)

結果

# Before
   a  b   c
0  1  2   3
1  4  5  50

# After
   a  b   c  target
0  1  2   3       0
1  4  5  50       1

条件が複数ある場合


df = pd.DataFrame(np.array([[1,2,3],[4,5,50]]), columns=['a','b','c'])

#条件を設定
conditions = [(df['c'] > 10.0) & (df['b'] > 1.0),
               (df['c'] < 10.0) & (df['b'] > 1.0)]
#それぞれの条件に対応する値を設定
choices = [1, 0]

df['target'] = np.select(conditions, choices, default=0)

結果

   a  b   c  target
0  1  2   3       0
1  4  5  50       1

条件付きDataFrame加工2

#col1が1のところを3に変える
#ダメな例
#df[df['col1'] == 1]['col1'] = 3

#正しい例
df1.loc[df1[df1['col1'] == 1].index,'col1'] = 3

#test_df内のcol1の値のみをtrain_dfから抽出する。
train_df = train_df[train_df['col1'].isin(test_df['col1'].unique())]

locとiloc

df = pd.DataFrame([[1,2,3],[4,5,6]], columns=['a','b', 'c'])
print(df.loc[:, 'a'])
#print(df.iloc[:, 0])

結果


0    1
1    4
Name: a, dtype: int64

Dataframeのcolumnの長さとrowの長さ

print(len(train_df))
print(len(train_df.columns))

足りない桁数を0で埋める

seven = 7
seven = f'{seven:02}'  #0が2個で02
#seven = f'{7:02}'
print(seven)  #07

特定のインデックスに行を挿入する


df = pd.DataFrame(np.array([[1,2,3],[4,5,6],[7,8,9]]), columns=['a','b','c'])
#index2に入れたい
line = pd.DataFrame({'a': 3, 'b': 3, 'c':3}, index=[2])
df2 = pd.concat([df.iloc[:2], line, df.iloc[2:]], ignore_index=True)

結果

Before:
   a  b  c
0  1  2  3
1  4  5  6
2  7  8  9

After:
   a  b  c
0  1  2  3
1  4  5  6
2  3  3  3
3  7  8  9

行をシフトする

簡単。
例:column 'a'を一つシフトする。


df = pd.DataFrame(np.array([[1,2,3],[4,5,6],[7,8,9]]),columns=['a','b','c'])
df['a'] = df['a'].shift(1) #上にシフトしたい場合は-1

結果


     a  b  c
0  NaN  2  3
1  1.0  5  6
2  4.0  8  9

位置で列を選ぶ

ラベル無しのときとか。


df.iloc[:, 2]
#df[df.columns[2]]

本物のデータから実験用データを作る

#一番最初の行から100行分だけ取り出す。
df = df[:100]

DataFrameのindexをリセット

dropを忘れずに。

df.reset_index(drop=True, inplace=True)

dfの反転

一行目で反転し、二行目でindexをリセット。

df = df[::-1]
df.reset_index(drop=True, inplace=True)

Column内の特定の数字を置き換えたいとき

df.replace({'column_1': {-3:0, 3:2}},inplace=True)

重複している列を取り除いて一つの列にする

df1 = pd.DataFrame(np.array([[1,2,3]]),columns=['a','b','c'])
df2 = pd.DataFrame(np.array([[4,2,3]]),columns=['d','b','c'])

df1 = df1.merge(df2)

# Or

df = pd.concat([df1,df2],axis=1)
df = df.loc[:,~df.columns.duplicated()]

   a  b  c
0  1  2  3
   a  b  c
0  4  2  3

#結果
   a  b  c  d
0  1  2  3  4

条件付きColumnの書き換え


df.loc[df.col2 == 0, 'col1'] = 'Selling land'
#コラム'game'内の一つ一つの値にKという文字が含まれているか確かめ、その場合は'K'
#を'Good'に置き換える
df.loc[df.setsudo_hi.str.contains('K'), 'game'] = 'Good'

#複数の場合
searchfor = ['sm','SM']
df.loc[df['device_name'].str.contains('|'.join(searchfor), na=False), 'device_name'] = 'Samsung'

#or文
df.loc[(df.col1 != 'Valuable') & (df.col2 != 'Okay') , 'col3'] = 'Nothing'
#listの中に入っている文字と一致したら
df.loc[df.col1.isin(lst), 'co1'] = 'Valuable'

同じIDでマージする

x = np.array([[1,9],[2,5],[3,1]])
y = np.array([[1,6],[1,2],[2,3],[3,9],[3,10],[3,11]])

x = pd.DataFrame(x,columns=['id','d'])
y = pd.DataFrame(y,columns=['id','c'])

df = pd.merge(x, y, how='left', on='id')

print(x,'\n')
print(y,'\n')

print(df)
   id  d
0   1  9
1   2  5
2   3  1

   id   c
0   1   6
1   1   2
2   2   3
3   3   9
4   3  10
5   3  11

   id  d   c
0   1  9   6
1   1  9   2
2   2  5   3
3   3  1   9
4   3  1  10
5   3  1  11

列をフィルターにかけ、必要な列だけを取り出す

コラムがC_1,C_2,C_3,A_1,A_2,A_3などとあるときに、Cのつく特徴量だけをサクっと取り出したいときに使える。


A_feats = [i for i in train_df.colums.values if 'A' in i]

変数のイテレーション


a_1 = [1,2]
a_2 = [3,4]
temp = [5, 6]

for i in range(1,3):
    print(eval('a_'+str(i)))

    # Assinmentを行いたい場合 Ex: a_i = temp
    exec('a_' + str(i) + '= temp') 

特定の列内にNaNが入っていない行を取り出す

df = df[df['col1'].notnull()]

データフレームをシャッフル

df = df.sample(frac=1).reset_index(drop=True)

df内の列を一つのseriesにまとめる


df = pd.DataFrame([[1,2,3],[4,5,6]],columns=['a','b','c'])

#   a  b  c
# 0  1  2  3
# 1  4  5  6

s = pd.Series()

for i in df.columns.values:
    s = s.append(df[i],ignore_index=True)

# 0    1
# 1    4
# 2    2
# 3    5
# 4    3
# 5    6
# dtype: int64

DataFrameのソート

df.sort_values(by='col1',ascending=False,inplace=True)

#もし一つの列だけをソートし、他の列に影響を与えたくない場合はnp.sortを利用
x = np.sort(df['col1'].values)[::-1]
df['col1'] = pd.Series(x)

2つのDataFrameを連結する

ただしconcatはメモリの消費が激しいので大きなデータセットのときは要注意。

#Rowを連結したい場合。例えばdf1=[col1,col2](10 rows),
#df2=[col1,col2] (20 rows)を連結してdf=[col1,col2] (30 rows)とするとき。
df = pd.concat([df1,df2], ignore_index=True)

#Columnを連結したい場合。例えばdf1=[col1,col2](10 rows),
#df2=[col3] (10 rows)を連結してdf=[col1,col2,col3] (10 rows)とするとき。
df = pd.concat([df1,df2], axis=1)

EDA

DataFrame内の文字を分割して値を挿入する


x = np.array([['a.b','c.d'],['e.f','gh']])
df = pd.DataFrame(x,columns=['A','B'])

#df:
#      A    B
# 0  a.b  c.d
# 1  e.f   gh

new = df['B'].str.split('.') 

# new:
# 0    [c, d]
# 1      [gh]

# /で分けて特徴量を作る。
df[['year','month','date']] = df['date'].str.split('/', expand=True)


# 分割後、0番目のリストの値を挿入
df['first'] = df['construct_name'].str.split('_').str[0]

# df['B']:
# 0     c
# 1    gh

# 整数で分割後、0番目のリストの値の最後のを挿入
train['Cabin_Char'] = train['Cabin'].str.split('\d').str[0].str[-1]

ある列Xがnanのところだけある列Yの値で埋める


lst = df[df['x'].isna()].index

for i in lst:
    df.loc[i,'x'] = df['y'].iloc[i]

groupby

df = train_df.groupby('col1',as_index=False).mean()

df = pd.DataFrame(data={'col1':df['col1'],'col2':df['col2']}, \
index=range(df.shape[0]))

Unique Valuesを調べる

#Unique valuesの数
print('Number of unique values in col1',df['col1'].nunique())

#Unique values
print('Unique values in col1',df['col1'].unique())

# df2のcol1にあってdf1のcol1に無い値を調べる
print(df2[~df2['col1'].isin(df1['col1'])]['col1'].unique())

2つのarray内を比べた時に、いずれかに無い値を出力する

2つのデータフレームのコラムの違い等を確かめたいときに使える。またnumpy arrayとpython arrayどちらでも使える。

# array1にあってarray2にない要素を返す。
np.setdiff1d(array1, array2)
# array2にあってarray1にない要素を返す。
np.setdiff1d(array2, array1)

ある値を他のデータフレームを参照しながら更新


train_df['temp'] = train_df['col1']

for val,new_val inzip(df['col1'].values,df['new_col1'].values):
    train_df.loc[train_df['col1'] == val, 'temp'] = new_val

train_df['jukyo'] = train_df['temp']
train_df.drop('temp',axis=1,inplace=True)

一つの列に全ての列の値をまとめる

# 列が膨大な場合
df = pd.melt(df, id_vars=[], value_vars=df.columns.values)
df.dropna(inplace=True)
df.drop('variable',axis=1,inplace=True)
df.rename(columns={'variable':'col1'},inplace=True)


#https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.stack.html
# .stack()でも良し

# 少ないなら
df = pd.DataFrame({'col1':['A', 'B', 'C', 'D'],'col2':['E', 'F', 'G', 'H']})
df = df['col1'].append(df['col2']).reset_index(drop=True)

データフレーム間の細かい値の移動

train_df = pd.DataFrame({'col1':['A', 'B', 'C', 'D','E'],'col2':['E', 'F', 'G', 'H',np.nan]})
test_df = pd.DataFrame({'col1':['I', 'J', 'K', 'L','M'],'col2':['N', 'O', 'P', 'Q',np.nan]})

#train_df:
  col1 col2
0    A    E
1    B    F
2    C    G
3    D    H
4    E  NaN

train_df.loc[[0,1],'col1'] = test_df.loc[[0,1],'col1']

#train_df:
  col1 col2
0    I    E
1    J    F
2    C    G
3    D    H
4    E  NaN

値の重複カウント

df = pd.DataFrame(np.array([[1,1,1],[1,2,3],[1,4,5]]), columns=['a','b','c'])

df = df.apply(lambda x: x.duplicated()).sum()

結果


   a  b  c
0  1  1  1
1  1  2  3
2  1  4  5

a    2
b    0
c    0
dtype: int64

a-column内の1自体のカウントは+1して3ということに注意。.duplicated()が[False, True, True]のため。

とある列でgroupbyして、他の列のunique valuesを数える

df = pd.DataFrame([[124,200,1],[124,2000,2],[3000,3000,3],[125,3000,4],[125,3000,5],[123,200,6]],columns=['col1','col2','col3'])

# col1で行をまとめて、col2のユニークな値の数を数える
print(df.groupby('co11')['col2'].nunique())

# col1
# 123     1
# 124     2
# 125     1
# 3000    1

Columnの詳細な情報を知りたいとき

print(df['groups'].describe())
count    4137.000000
mean        9.385303
std         5.458562
min         0.000000
25%         4.000000
50%         9.000000
75%        13.000000
max        19.000000
Name: groups, dtype: float64

column内の全ての値とその数をカウント

print(df['col1'].value_counts())

# col1の値をソートして表示したい場合
print(df['col1'].value_counts().sort_index())

Nullになっている行のインデックスが知りたい


print(np.where(df['col1'].isnull())[0])
#例:[1,4]

特徴量の名前と数が知りたいとき

print(df.columns.values)
print(len(df.columns))

2つのデータフレームの違いを知る

df = pd.concat([df1,df2]).drop_duplicates(keep=False)

level0のインデックスの観点から一つの列の値の重複を確認する

インデックスが複数で層になっているときに、一番最初の層の観点から重複を探すにはどうすれば良いか。


df = df[df['col1'].groupby(level=0).apply(lambda x: x.duplicated())]

相関性ランキング

それぞれの特徴量の相関性を強い順にランキング化する。

df = pd.DataFrame(np.array([[5,2,3],[1,3,2],[5,8,5]]), columns=['a','b','c'])

correlations = df.corr().abs().unstack().sort_values(kind="quicksort", ascending=False).reset_index()
correlations = correlations[correlations['level_0'] != correlations['level_1']]

print(correlations.head(10))

# targetとの相関
result = df.drop("target", axis=1).apply(lambda x:x.corr(df['target'])).sort_values(ascending=False)

結果


  level_0 level_1         0
3       c       b  0.882498
4       b       c  0.882498
5       c       a  0.755929
6       a       c  0.755929
7       b       a  0.359211
8       a       b  0.359211

2つの列の相関性

df['A'].corr(df['B'])

出力処理

特徴量からカテゴリー変数名と数値変数名を一発で取得

# df内のカテゴリ変数名を取得
categories = df.select_dtypes(include='object').columns.values

# df内の数値変数名を取得
numerics = ['int16', 'int32', 'int64', 'float16', 'float32', 'float64']
numerics = df.select_dtypes(include=numerics).columns.values


# 念のため他の型の変数が無いかをチェック
others = [col for col in df.columns.values if col not in np.concatenate((categories, numerics), axis=0)]

print(others)

データフレームの列間隔のズレを直して綺麗に出力したいとき

値に日本語が入ったりしているとデータフレーム内の列の間隔がズレることがある。これはEDAのときなどにされるとデータフレームの値が見にくい。このtabulateというパッケージを使えばデータフレームがテーブル形式でプリントされ、大変見やすくなる。


from tabulate import tabulate
import pandas as pd

print(tabulate(df, headers='keys', tablefmt='psql'))

numpy array or DataFrameを省略せずに全て出力する

# Numpy array
import sys
np.set_printoptions(threshold=sys.maxsize)

# DataFrame
# 縦と横幅
pd.set_option("display.max_rows", None, "display.max_columns", None)

with pd.option_context('display.max_rows', None, 'display.max_columns', None):
    print(df)

#横幅の設定 (columnに入っている値が長すぎると途切れてしまうので)
pd.set_option('max_colwidth', 200)

指数表記(Scientific notation)をオフにする


np.set_printoptions(suppress=True)

特徴量生成とエンコーディング

他の特徴量をグループ化して統計量を取る

# pclassをグループとして各々グループから年齢の中央値を取りmid_age_per_classとする。
train_test['age_per_class'] = train_test.groupby('Pclass')['Age'].transform('median')

ラベルエンコーダー (Label Encoder)


label_encoder = LabelEncoder()
df.loc[:,'col1'] = label_encoder.fit_transform(df.loc[:,'col1'])

相関(Correlation)が強い特徴量を落として無駄削減

どちらかというとFeature Selection。


X = np.array([[1, 1, 1],
              [2, 2, 0],
              [3, 3, 1],
              [4, 4, 0],
              [5, 5, 1],
              [6, 6, 0],
              [7, 7, 1],
              [8, 7, 0],
              [9, 7, 1]])

df = pd.DataFrame(X)

# Create correlation matrix
corr_matrix = df.corr().abs()

# Select upper triangle of correlation matrix
upper = corr_matrix.where(np.triu(np.ones(corr_matrix.shape), k=1).astype(np.bool))

# Find index of feature columns with correlation greater than 0.95
to_drop = [column for column in upper.columns if any(upper[column] > 0.95)]

# Drop features 
df.drop(to_drop, axis=1, inplace=True)

結果

    0   2
0   1   1
1   2   0
2   3   1
3   4   0
4   5   1
5   6   0
6   7   1
7   8   0
8   9   1

ここから
https://chrisalbon.com/machine_learning/feature_selection/drop_highly_correlated_features/

numpy arrayとlist

特定の条件を満たす数字をnumpy arrayから抽出する


x = np.array([0,1,2,3,4])
x = x[(x>0) & (x<4)]    #結果:[1 2 3]

一行 list for文まとめ


list = [i for i in ratio.columns.values if ("expected_" in i) and not("unexpected_" in i)]

lst = [i for i in range(10)]

# if
test_fold = [0 for i in range(x_train.shape[0]) if ...]

# if and else
test_fold = [0 if ... else 1 for i in range(x_train.shape[0])]

Numpy arrayの行の反転

array = np.flip(array)

特定の条件を満たす数字を2次元のnumpy arrayから抽出する

x[1]で数字5以下の満たすx[1]と、それに対応するx[0]を取り出すという仮定で書いています。


x = np.array([[0,1,2,3],[3,4,5,6]])

boolArr = x[1] < 5

y = np.zeros(shape=(2,2))

y[0], y[1] = np.extract(boolArr, x[0]), np.extract(boolArr,x[1])

#結果[[0. 1.]
#     [3. 4.]]

2D listに値を挿入


x = np.array([[1,2,3,4,5,1,2],[5,1,2,3,2,2,3]])

low = list([[],[]])

low[0].append(x[0][0])
low[1].append(x[1][0])

print(low)
#結果 low = [[1], [5]]

Numpy arrayのソート

x_1 = np.array([0,18,90,7,8,9])

x_1 = np.sort(x_1)
#結果 [ 0  7  8  9 18 90]

x_1 = np.sort(x_1)[::-1]
#結果 [90 18  9  8  7  0]

条件付きNumpy Array加工

例題:要素が5以下ならそのままにし、要素が5以上なら10掛ける。

array = np.arange(10)
#array=[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
array = np.where(array < 5, array, 10*array)
#構文 array = np.where(条件, Trueの場合, Falseの場合)
#array([ 0,  1,  2,  3,  4, 50, 60, 70, 80, 90])

list → Numpy array

array = np.array(list)

Numpy array→list

lst = numpy_array.tolist()

listのextend

aList = [123, 'xyz', 'zara', 'abc', 123];
bList = [2009, 'manni'];
aList.extend(bList)
#aList: [123, 'xyz', 'zara', 'abc', 123, 2009, 'manni']

要素を削除する

#list
del t[0]
#or
t.pop()

# numpy array
#np.delete(x,index,axis)
x = np.delete(x, 1, 0)
# 特定のインデックスを削除したい場合
x = np.delete(x, [1,2,5], 0)
# 特定のインデックス以上を削除したい場合
x = np.delete(x, np.s_[3:], axis=1)

ファイルの読み書き

csvファイルの読み込みと書き込み

df = pd.read_csv('.csv')
df.to_csv('.csv',index=False)
# 日本語の文字化け対策
df.to_csv('.csv',encoding='shift_jis',index=False)

feather file書き込みと読み込み

pip install feather-formatでインストール

import feather

# 単にcsvファイルをfeatherファイルに変換したい場合
df = pd.read_csv('./df.csv')
feather.write_dataframe(df, './df.feather')

# 特徴量をそれぞれfeatherファイルに保存したい場合
df = pd.DataFrame(np.array([1]),columns=['a'])

feather.write_dataframe(df, './dataset/test')
# df.to_feather('')でも可。feather fileはfloat16をサポートしていないので注意
df = feather.read_dataframe('./dataset/test')

# df内の列を一つずつfeather形式で保存
# index=をちゃんと設定しないとエラーが起こる。またObject dtypeも他のdtypeに直す# 必要あり。
for col in train_df.columns.values:
    pd.DataFrame(data={str(col):train_df[col]},index=range(train_df.shape[0])).to_feather(str(col) + '_train.ftr')
    pd.DataFrame(data={str(col):test_df[col]},index=range(test_df.shape[0])).to_feather(str(col) + '_test.ftr')

pickleファイルを開く

import pickle
with open('df1.pkl', 'rb') as df1, open('df2.pkl', 'rb') as df2:
    df1, df2 = pickle.load(df1), pickle.load(df2)

その他

Suppress warnings

import warnings
warnings.filterwarnings("ignore")

データの型変換まとめ

List


list = [int(string) for string in lst]

Numpy array

numpy_array = numpy_array.astype(int)

Series


series = series.astype(int)

DataFrame


df = df.astype(int)

Python array


array = array.astype(int)

普通のstring


s = int(s)

カレントディレクトリの設定

データ整形と関係ないけど。。

import os
# print(os.getcwd())
os.chdir("C:\\Users\\dravr\\Documents\\kaggle\\IEEE\\dataset")

index.map() 複数の入力値から呼応した一つの出力値を特徴量に加える

series.map()やindex.map()を使えば、与えられた入力値から簡単に出力値を得ることが出来る。以下は、その入力値が複数の場合に有用である。


# 複数の特徴量のグループから生存率を出す。(出力値:家族生存率)
reference = df.groupby(['Last_name','SibSp','Embarked','Pclass'])['Survived'].mean()

# .index.map()を使うためにmapの複数の入力値をインデックスに加える
train = train.set_index(['Last_name','SibSp','Embarked','Pclass'],drop=True)
test = test.set_index(['Last_name','SibSp','Embarked','Pclass'],drop=True)

# 複数の入力値に呼応した一つの出力値、家族生存率を特徴量に加える。
# (series.map()の場合、dataframe.map()として使えない(入力値は一つだけ)のでindex.mapを使っている。)
train['Family_sur_rate'] = train.index.map(reference)
test['Family_sur_rate'] = test.index.map(reference)

# 入力値として使ったインデックスを特徴量に戻す
train = train.reset_index(level=['Last_name','SibSp','Embarked','Pclass'])
test = test.reset_index(level=['Last_name','SibSp','Embarked','Pclass'])

特徴量エンジニアリング

ラグ


for shift in [0, 1, 2]:
    data[f"shift_t{shift}"] = data.groupby(["id"])["demand"].transform(
        lambda x: x.shift(shift)
    )

ローリング(窓)

for size in [7, 14,21, 30, 60, 90, 180]:
    data[f"rolling_std_t{size}"] = data.groupby(["id"])["demand"].transform(
        lambda x: x.shift(1).rolling(size).mean()
    )

# .skew() .kurt() .std() .max() .min()

エンコーディング

カウントエンコーディング

count_features = ['Age','SibSp','Cabin','Ticket']

for feature in count_features:
    train['count_' + feature] = train[feature].map(pd.concat([train[feature], 
             test[feature]], ignore_index=True).value_counts(dropna=False))
    test['count_' + feature] = test[feature].map(pd.concat([train[feature], 
             test[feature]], ignore_index=True).value_counts(dropna=False))

ターゲットエンコーディング (スムーズ)

import numpy as np
import pandas as pd


def add_noise(series, noise_level):
    return series * (1 + noise_level * np.random.randn(len(series)))

def target_encode(trn_series=None, 
                  tst_series=None, 
                  target=None, 
                  min_samples_leaf=1, 
                  smoothing=1,
                  noise_level=0):
    """
    Smoothing is computed like in the following paper by Daniele Micci-Barreca
    https://kaggle2.blob.core.windows.net/forum-message-attachments/225952/7441/high%20cardinality%20categoricals.pdf
    trn_series : training categorical feature as a pd.Series
    tst_series : test categorical feature as a pd.Series
    target : target data as a pd.Series
    min_samples_leaf (int) : minimum samples to take category average into account
    smoothing (int) : smoothing effect to balance categorical average vs prior  
    """ 
    assert len(trn_series) == len(target)
    assert trn_series.name == tst_series.name
    temp = pd.concat([trn_series, target], axis=1)
    # Compute target mean 
    averages = temp.groupby(by=trn_series.name)[target.name].agg(["mean", "count"])
    # Compute smoothing
    smoothing = 1 / (1 + np.exp(-(averages["count"] - min_samples_leaf) / smoothing))
    # Apply average function to all target data
    prior = target.mean()
    # The bigger the count the less full_avg is taken into account
    averages[target.name] = prior * (1 - smoothing) + averages["mean"] * smoothing
    averages.drop(["mean", "count"], axis=1, inplace=True)
    # Apply averages to trn and tst series
    ft_trn_series = pd.merge(
        trn_series.to_frame(trn_series.name),
        averages.reset_index().rename(columns={'index': target.name, target.name: 'average'}),
        on=trn_series.name,
        how='left')['average'].rename(trn_series.name + '_mean').fillna(prior)
    # pd.merge does not keep the index so restore it
    ft_trn_series.index = trn_series.index 
    ft_tst_series = pd.merge(
        tst_series.to_frame(tst_series.name),
        averages.reset_index().rename(columns={'index': target.name, target.name: 'average'}),
        on=tst_series.name,
        how='left')['average'].rename(trn_series.name + '_mean').fillna(prior)
    # pd.merge does not keep the index so restore it
    ft_tst_series.index = tst_series.index
    return add_noise(ft_trn_series, noise_level), add_noise(ft_tst_series, noise_level)


train_df = pd.DataFrame(np.array([[3,2,1],[6,2,1],[7,1,0]]),columns=['feature1','category1','target'])
test_df = pd.DataFrame(np.array([[3,2,1],[6,2,1],[7,1,0]]),columns=['feature1','category1','target'])


train_df['target_encoded'], test_df['target_encoded'] = target_encode(train_df["category1"], 
                         test_df["category1"], 
                         target=train_df.target, 
                         min_samples_leaf=1,
                         smoothing=1,
                         noise_level=0.01)

print(train_df)

13
15
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
13
15