Исправление вашей ошибки
Я не уверен, как интерпретировать эту ошибку, потому что она действительно должна быть списком, верно?
Нет: colnames[0]
иcolnames[4]
- это скаляры, а не списки.Вы не можете объединить скаляр со списком.Для составления списков используйте квадратные скобки:
colnames = [colnames[0]] + [colnames[4]] + colnames[:-1]
Кроме того, я настоятельно рекомендую использовать df.columns = colnames
вместо df[[colnames]]
: __getitem__
(или его синтаксический сахар []
) запускает операцию копирования .
Общее решение
Но преобразование массивов в списки и последующее объединение списков вручную не только дорого, но и подвержено ошибкам.Ответ, связанный с имеет много решений на основе списка, но решение на основе NumPy целесообразно, поскольку объекты pd.Index
хранятся в виде массивов NumPy.
Ключом здесь является изменение массива NumPy.через нарезку, а не конкатенацию.Необходимо обработать только 2 случая: когда после текущей позиции существует нужная позиция, и наоборот.
import pandas as pd, numpy as np
from string import ascii_uppercase
df = pd.DataFrame(columns=list(ascii_uppercase))
def shifter(df, col_to_shift, pos_to_move):
arr = df.columns.values
idx = df.columns.get_loc(col_to_shift)
if idx == pos_to_move:
pass
elif idx > pos_to_move:
arr[pos_to_move+1: idx+1] = arr[pos_to_move: idx]
else:
arr[idx: pos_to_move] = arr[idx+1: pos_to_move+1]
arr[pos_to_move] = col_to_shift
df.columns = arr
return df
df = df.pipe(shifter, 'J', 1)
print(df.columns)
Index(['A', 'J', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'K', 'L', 'M', 'N',
'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'],
dtype='object')
Сравнительный анализ производительности
Использование нарезки NumPy более эффективно при большом количествестолбцы против метода на основе списка:
n = 10000
df = pd.DataFrame(columns=list(range(n)))
def shifter2(df, col_to_shift, pos_to_move):
cols = df.columns.tolist()
cols.insert(pos_to_move, cols.pop(df.columns.get_loc(col_to_shift)))
df.columns = cols
return df
%timeit df.pipe(shifter, 590, 5) # 381 µs
%timeit df.pipe(shifter2, 590, 5) # 1.92 ms