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

随時更新

#リンク

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


#文字列処理#
###特殊文字の除去###
65%,78%...85%の%を取り除きたい

```py
# 例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に置き換えたい

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


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

```py

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


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

結果

```py

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


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

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

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



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

```python

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

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



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

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


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

```py
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を数える###

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

###N/Aを埋める###

```py
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)毎にどれくらい紛失データがあるのかをランキングで出力

```py
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))

```
結果

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

###finiteの詳細カウント###

```py
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除去###

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


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

```py

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

```



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

```py

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

```

#演算処理#

###列の掛け算###

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



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

```py

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





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

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

```py

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



#削除処理#

###無駄な特徴量を除去する###

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



###特定の行を削除###

```py
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)
```



###特定の列を削除###

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

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

```


###列の重複除去###

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



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

https://stackoverflow.com/questions/43951558/remove-rows-that-two-columns-have-the-same-values-by-pandas

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


#作成処理#

###dfの作成###

```py
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を生成する###

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


###dfのコピー###

```py

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

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

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

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



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

```py

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

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


###Numpy Array作成###

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

```py

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

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

```py

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



###DataFrameの追加###


```py
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に入れる###

```py
#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###

```py

array = df.values

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

```



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

```py

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

```

結果

```py

      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
```

#変更処理#


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


```py

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

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


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

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


###DataFrameに任意の行を追加する###

```py

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


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

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

###dtypeを利用したif分###

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

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

```

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


```py

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

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

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

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

https://stackoverflow.com/questions/16782323/python-pandas-keep-selected-column-as-dataframe-instead-of-series

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

###条件付きDataFrame加工###
Column cが10以上ならTargetを1、それ以下なら0にして追加する。

####条件が一つの場合####

```py
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)

```
結果

```py
# 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
```
####条件が複数ある場合####

```py

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)
```
結果

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


###条件付きDataFrame加工2###

```py
#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###

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

```py

0    1
1    4
Name: a, dtype: int64
```


###Dataframeのcolumnの長さとrowの長さ###

```py
print(len(train_df))
print(len(train_df.columns))
```


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

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


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

```py

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)
```

結果

```py
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'を一つシフトする。

```py

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
```

結果

```py

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


###位置で列を選ぶ###
ラベル無しのときとか。

```py

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



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

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

###DataFrameのindexをリセット###
dropを忘れずに。

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



###dfの反転###

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

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

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

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



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

```py
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()]
```

```py

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

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

###条件付きColumnの書き換え###

```py

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でマージする###

```py
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)
```

```py
   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のつく特徴量だけをサクっと取り出したいときに使える。

```py

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


###変数のイテレーション###

```py

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が入っていない行を取り出す###

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


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

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


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

```py

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のソート###

```py
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はメモリの消費が激しいので大きなデータセットのときは要注意。

```py
#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内の文字を分割して値を挿入する###

```py

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の値で埋める###

```py

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

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


###groupby###

```py
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を調べる###

```py
#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内を比べた時に、いずれかに無い値を出力する###

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

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



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

```py

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)
```


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

```py
# 列が膨大な場合
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)

```

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

```py
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

```

###値の重複カウント###

```py
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()

```
結果

```py

   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を数える###

```py
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の詳細な情報を知りたいとき###

```py
print(df['groups'].describe())
```

```py
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内の全ての値とその数をカウント###

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

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




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

```py

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


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

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

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

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


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

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

```py

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



###相関性ランキング###

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

```py
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)
```

結果

```py

  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
```

###２つの列の相関性###

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




# 出力処理 #


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


```py
# 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というパッケージを使えばデータフレームがテーブル形式でプリントされ、大変見やすくなる。

```py

from tabulate import tabulate
import pandas as pd

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

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

```py
# 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)をオフにする###

```py

np.set_printoptions(suppress=True)
```

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

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

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

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

```py

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

###相関(Correlation)が強い特徴量を落として無駄削減###
どちらかというとFeature Selection。

```py

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から抽出する###
```py

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

###一行 list for文まとめ###


```py

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の行の反転###


```py
array = np.flip(array)
```



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

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

```py

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に値を挿入###

```py

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のソート###

```py
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掛ける。

```py
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###

```py
array = np.array(list)
```


###Numpy array→list###
```py
lst = numpy_array.tolist()
```

###listのextend###

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


###要素を削除する###

```py
#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ファイルの読み込みと書き込み###

```py
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でインストール

```py
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ファイルを開く###

```py
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

```py
import warnings
warnings.filterwarnings("ignore")
```


###データの型変換まとめ###

List

```py

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

Numpy array

```py
numpy_array = numpy_array.astype(int)
```

Series

```py

series = series.astype(int)
```


DataFrame

```py

df = df.astype(int)
```

Python array

```py

array = array.astype(int)
```

普通のstring

```py

s = int(s)
```

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

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

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


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

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

```py

# 複数の特徴量のグループから生存率を出す。（出力値：家族生存率）
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'])

```


# 特徴量エンジニアリング

## ラグ
```py

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

## ローリング（窓）

```py
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()
```


# エンコーディング

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

```py
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))
```


## ターゲットエンコーディング　（スムーズ）
```py
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)

```