pandasでDataFrameの最初(一番左)に列を追加・挿入する方法

pandasでDataFrameの最初(一番左)に列を追加・挿入する方法。
環境:pandasのversionは0.25.3です。

f:id:soratokimitonoaidani:20200202135514p:plain

列名を指定して追加する方法だと末尾(最後、右端)に追加される

既存のDataFrameに1つの列を新規に追加する最も一般的な方法は、df['new_column'] = (追加したい値)だろう。しかしこの方法では、新しい列は一番右に追加されてしまう。

例を見てみよう。

import pandas as pd
pd.__version__
'0.25.3'
df = pd.DataFrame({
    'name'    : ['Alice', 'Bob', 'Charlie', 'David', 'Eve', 'Fred'],
    'English' : [12, 34, 56, 78, 90, 100],
    'Math'    : [88, 66, 55, 44, 22, 11]    
})

df
name English Math
0 Alice 12 88
1 Bob 34 66
2 Charlie 56 55
3 David 78 44
4 Eve 90 22
5 Fred 100 11
df['new_column'] = 'value'
df['new_column_2'] = ['a', 'b', 'c', 'd', 'e', 'f']
df
name English Math new_column new_column_2
0 Alice 12 88 value a
1 Bob 34 66 value b
2 Charlie 56 55 value c
3 David 78 44 value d
4 Eve 90 22 value e
5 Fred 100 11 value f

確かに右側に追加されている。

先頭(最初、左端)に追加するにはinsertを使う

pandas.DataFrame.insert()関数
公式ドキュメント:pandas.DataFrame.insert — pandas 1.0.0 documentation

メジャーアップデートされた1.0.0のドキュメントを参照していいのか微妙ですが、多分ここに変更はないでしょう。

insertはドキュメントに記載の通り「指定した好きな位置に列を挿入する」関数である。したがってこれで先頭を指定すれば良い。

loc, column, valueは指定必須。

locが「列を挿入する位置」なので、先頭に入れたければ0を指定する。0 <= loc <= len(columns)でなければならない。
columnは列名。
valueは単一の値ならばその値を全行に指定、SeriesやArrayならばそれぞれの値を指定、だろうな。

int, Series, or array-like

って公式ドキュメントには書いてあるけど、文字列(str)を指定して普通に列を追加できたんだけど……あれ?

上に書いたのと同じ文で再度dfを作った後に
df.insert(0, 'new_column', 'value')
df
new_column name English Math
0 value Alice 12 88
1 value Bob 34 66
2 value Charlie 56 55
3 value David 78 44
4 value Eve 90 22
5 value Fred 100 11
df.insert(0, 'new_column_2', ['a', 'b', 'c', 'd', 'e', 'f'])
df
new_column_2 new_column name English Math
0 a value Alice 12 88
1 b value Bob 34 66
2 c value Charlie 56 55
3 d value David 78 44
4 e value Eve 90 22
5 f value Fred 100 11
df.insert(0, 'new_column_error', ['a', 'b', 'c', 'd', 'e'])  # 6行ぶんを書くべきところ、要素数5の配列を入れた

エラー(内容はクリックすると展開されます)

---------------------------------------------------------------------------

ValueError                                Traceback (most recent call last)

<ipython-input-11-bca86ac7c013> in <module>
----> 1 df.insert(0, 'new_column_error', ['a', 'b', 'c', 'd', 'e'])  # 6行ぶんを書くべきところ、要素数5の配列を入れた


/usr/local/lib/python3.7/site-packages/pandas/core/frame.py in insert(self, loc, column, value, allow_duplicates)
    3588         """
    3589         self._ensure_valid_index(value)
-> 3590         value = self._sanitize_column(column, value, broadcast=False)
    3591         self._data.insert(loc, column, value, allow_duplicates=allow_duplicates)
    3592 


/usr/local/lib/python3.7/site-packages/pandas/core/frame.py in _sanitize_column(self, key, value, broadcast)
    3747 
    3748             # turn me into an ndarray
-> 3749             value = sanitize_index(value, self.index, copy=False)
    3750             if not isinstance(value, (np.ndarray, Index)):
    3751                 if isinstance(value, list) and len(value) > 0:


/usr/local/lib/python3.7/site-packages/pandas/core/internals/construction.py in sanitize_index(data, index, copy)
    610 
    611     if len(data) != len(index):
--> 612         raise ValueError("Length of values does not match length of index")
    613 
    614     if isinstance(data, ABCIndexClass) and not copy:


ValueError: Length of values does not match length of index

なお、すでにある列名を指定するとエラーValueError: cannot insert new_column, already existsが返ります。
それでは。