Одна линия или трубопроводные решения
Я сосредоточусь на двух вещах:
ОП четко заявляет
У меня есть отредактированные имена столбцов, которые хранятся в списке, но я не знаю, как заменить имена столбцов.
Я не хочу решать проблему замены '$'или удаления первого символа каждого заголовка столбца. ОП уже сделал этот шаг. Вместо этого я хочу сосредоточиться на замене существующего columnsобъекта новым, учитывая список имен замещающих столбцов.
df.columns = newгде newсписок имен новых столбцов так же прост, как и получается. Недостаток этого подхода заключается в том, что он требует редактирования columnsатрибута существующего информационного кадра, и он не выполняется встраиваемым образом. Я покажу несколько способов сделать это с помощью конвейерной обработки, не редактируя существующий фрейм данных.
Настройка 1
Чтобы сосредоточиться на необходимости переименования заменяемых имен столбцов в уже существующий список, я создам новый примерный кадр данных dfс исходными именами столбцов и несвязанными новыми именами столбцов.
df = pd.DataFrame({'Jack': [1, 2], 'Mahesh': [3, 4], 'Xin': [5, 6]})
new = ['x098', 'y765', 'z432']
df
Jack Mahesh Xin
0 1 3 5
1 2 4 6
Решение 1
pd.DataFrame.rename
Уже говорилось, что если бы у вас был словарь, сопоставляющий старые имена столбцов с новыми именами столбцов, вы могли бы использовать pd.DataFrame.rename.
d = {'Jack': 'x098', 'Mahesh': 'y765', 'Xin': 'z432'}
df.rename(columns=d)
x098 y765 z432
0 1 3 5
1 2 4 6
Тем не менее, вы можете легко создать этот словарь и включить его в вызов rename. Следующее использует тот факт, что при переборе dfмы перебираем каждое имя столбца.
# given just a list of new column names
df.rename(columns=dict(zip(df, new)))
x098 y765 z432
0 1 3 5
1 2 4 6
Это прекрасно работает, если ваши оригинальные имена столбцов являются уникальными. Но если они не, то это ломается.
Настройка 2
неуникальных столбцов
df = pd.DataFrame(
[[1, 3, 5], [2, 4, 6]],
columns=['Mahesh', 'Mahesh', 'Xin']
)
new = ['x098', 'y765', 'z432']
df
Mahesh Mahesh Xin
0 1 3 5
1 2 4 6
Решение 2
pd.concat с использованием keysаргумента
Во-первых, обратите внимание, что происходит, когда мы пытаемся использовать решение 1:
df.rename(columns=dict(zip(df, new)))
y765 y765 z432
0 1 3 5
1 2 4 6
Мы не отображали newсписок как имена столбцов. Мы закончили тем, что повторили y765. Вместо этого мы можем использовать keysаргумент pd.concatфункции во время итерации по столбцам df.
pd.concat([c for _, c in df.items()], axis=1, keys=new)
x098 y765 z432
0 1 3 5
1 2 4 6
Решение 3
Реконструкция. Это следует использовать, только если у вас есть один dtypeдля всех столбцов. В противном случае вы получите dtype objectвсе столбцы, и для их преобразования требуется больше словарной работы.
Один dtype
pd.DataFrame(df.values, df.index, new)
x098 y765 z432
0 1 3 5
1 2 4 6
смешанный dtype
pd.DataFrame(df.values, df.index, new).astype(dict(zip(new, df.dtypes)))
x098 y765 z432
0 1 3 5
1 2 4 6
Решение 4
Это трюк с transposeи set_index. pd.DataFrame.set_indexпозволяет нам установить индекс в строке, но не соответствует set_columns. Таким образом, мы можем транспонировать set_indexи перенести обратно. Тем не менее, тот же сингл dtypeпротив смешанногоdtype здесь применимо предостережение в из решения 3.
Один dtype
df.T.set_index(np.asarray(new)).T
x098 y765 z432
0 1 3 5
1 2 4 6
смешанный dtype
df.T.set_index(np.asarray(new)).T.astype(dict(zip(new, df.dtypes)))
x098 y765 z432
0 1 3 5
1 2 4 6
Решение 5
Используйте a lambdaв pd.DataFrame.renameэтом цикле через каждый элемент new
В этом решении мы передаем лямбду, которая принимает, xно затем игнорирует ее. Это также занимает, yно не ожидает этого. Вместо этого итератор задан в качестве значения по умолчанию, и затем я могу использовать его для циклического перехода по одному за раз, независимо от значения x.
df.rename(columns=lambda x, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6
И как отметили мне люди в чате sopython , если я добавлю *промежуточное xи y, я смогу защитить свою yпеременную. Хотя в этом контексте я не верю, что это нуждается в защите. Это все еще стоит упомянуть.
df.rename(columns=lambda x, *, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6