Ответ 1
Просто назначьте его атрибуту .columns:
>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
a b
0 1 10
1 2 20
У меня есть DataFrame, использующий панды и метки столбцов, которые мне нужно отредактировать, чтобы заменить оригинальные метки столбцов.
Я хотел бы изменить имена столбцов в DataFrame A где исходные имена столбцов:
['$a', '$b', '$c', '$d', '$e']
в
['a', 'b', 'c', 'd', 'e'].
У меня есть отредактированные имена столбцов, которые хранятся в списке, но я не знаю, как заменить имена столбцов.
Просто назначьте его атрибуту .columns:
>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
a b
0 1 10
1 2 20
Используйте df.rename() и обращайтесь к столбцам, которые нужно переименовать. Не все столбцы должны быть переименованы:
df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})
# Or rename the existing DataFrame (rather than creating a copy)
df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}, inplace=True)
Пример минимального кода
df = pd.DataFrame('x', index=range(3), columns=list('abcde'))
df
a b c d e
0 x x x x x
1 x x x x x
2 x x x x x
Следующие методы работают и выдают одинаковый результат:
df2 = df.rename({'a': 'X', 'b': 'Y'}, axis=1) # new method
df2 = df.rename({'a': 'X', 'b': 'Y'}, axis='columns')
df2 = df.rename(columns={'a': 'X', 'b': 'Y'}) # old method
df2
X Y c d e
0 x x x x x
1 x x x x x
2 x x x x x
Не забудьте присвоить результат обратно, так как модификация не на месте. В качестве альтернативы укажите inplace=True:
df.rename({'a': 'X', 'b': 'Y'}, axis=1, inplace=True)
df
X Y c d e
0 x x x x x
1 x x x x x
2 x x x x x
Начиная с версии 0.25, вы также можете указать errors='raise' чтобы вызвать ошибки, если указан недопустимый столбец для переименования. Смотрите v0.25 rename() документы.
Используйте df.set_axis() с axis=1 и inplace=False (чтобы вернуть копию).
df2 = df.set_axis(['V', 'W', 'X', 'Y', 'Z'], axis=1, inplace=False)
df2
V W X Y Z
0 x x x x x
1 x x x x x
2 x x x x x
Это возвращает копию, но вы можете изменить DataFrame на месте, установив inplace=True (это поведение по умолчанию для версий <= 0,24, но оно может измениться в будущем).
Вы также можете назначить заголовки напрямую:
df.columns = ['V', 'W', 'X', 'Y', 'Z']
df
V W X Y Z
0 x x x x x
1 x x x x x
2 x x x x x
Метод rename может принимать функцию function, например:
In [11]: df.columns
Out[11]: Index([u'$a', u'$b', u'$c', u'$d', u'$e'], dtype=object)
In [12]: df.rename(columns=lambda x: x[1:], inplace=True)
In [13]: df.columns
Out[13]: Index([u'a', u'b', u'c', u'd', u'e'], dtype=object)
Как описано в http://pandas.pydata.org/pandas-docs/stable/text.html:
df.columns = df.columns.str.replace('$','')
Произошли некоторые существенные обновления переименования столбцов в версии 0.21.
rename добавил параметр axis который может быть установлен в columns или 1. Это обновление делает этот метод соответствующим остальному API панд. Он по-прежнему имеет параметры index и columns но вы больше не обязаны их использовать.set_axis со значением inplace установленным в False позволяет переименовать все метки индекса или столбца в список.Создайте образец DataFrame:
df = pd.DataFrame({'$a':[1,2], '$b': [3,4],
'$c':[5,6], '$d':[7,8],
'$e':[9,10]})
$a $b $c $d $e
0 1 3 5 7 9
1 2 4 6 8 10
rename с axis='columns' или axis=1df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis='columns')
или же
df.rename({'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'}, axis=1)
Оба приводят к следующему:
a b c d e
0 1 3 5 7 9
1 2 4 6 8 10
Еще можно использовать сигнатуру старого метода:
df.rename(columns={'$a':'a', '$b':'b', '$c':'c', '$d':'d', '$e':'e'})
Функция rename также принимает функции, которые будут применяться к каждому имени столбца.
df.rename(lambda x: x[1:], axis='columns')
или же
df.rename(lambda x: x[1:], axis=1)
set_axis со списком и inplace=False Вы можете предоставить список методу set_axis, длина которого равна числу столбцов (или индекса). В настоящее время, inplace по умолчанию True, но inplace будет по умолчанию False в будущих версиях.
df.set_axis(['a', 'b', 'c', 'd', 'e'], axis='columns', inplace=False)
или же
df.set_axis(['a', 'b', 'c', 'd', 'e'], axis=1, inplace=False)
df.columns = ['a', 'b', 'c', 'd', 'e']?Нет ничего плохого в том, чтобы напрямую присваивать столбцы. Это совершенно хорошее решение.
Преимущество использования set_axis состоит в том, что он может использоваться как часть цепочки методов и возвращает новую копию DataFrame. Без этого вам пришлось бы сохранить промежуточные шаги цепочки в другой переменной перед переназначением столбцов.
# new for pandas 0.21+
df.some_method1()
.some_method2()
.set_axis()
.some_method3()
# old way
df1 = df.some_method1()
.some_method2()
df1.columns = columns
df1.some_method3()
Поскольку вы хотите удалить знак $во всех именах столбцов, вы можете просто сделать:
df = df.rename(columns=lambda x: x.replace('$', ''))
ИЛИ
df.rename(columns=lambda x: x.replace('$', ''), inplace=True)
df.columns = ['a', 'b', 'c', 'd', 'e']
Он заменит существующие имена на имена, которые вы предоставляете, в указанном вами порядке.
old_names = ['$a', '$b', '$c', '$d', '$e']
new_names = ['a', 'b', 'c', 'd', 'e']
df.rename(columns=dict(zip(old_names, new_names)), inplace=True)
Таким образом вы можете вручную отредактировать new_names по своему усмотрению.
Отлично работает, когда вам нужно переименовать только несколько столбцов, чтобы исправить неправильные имена, акценты, удалить специальные символы и т.д.
Я думаю, что этот метод полезен:
df.rename(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"})
Этот метод позволяет изменять имена столбцов индивидуально.
Я сосредоточусь на двух вещах:
OP четко заявляет
У меня есть отредактированные имена столбцов, которые хранятся в списке, но я не знаю, как заменить имена столбцов.
Я не хочу решать проблему замены '$' или вырезать первый символ из каждого заголовка столбца. ОП уже сделал этот шаг. Вместо этого я хочу сосредоточиться на замене существующего объекта columns на новый, указав список имен заменяемых столбцов.
df.columns = new где new - список имен новых столбцов, так же просто, как и он. Недостатком этого подхода является то, что он требует редактирования существующего атрибута dataframe columns, и он не выполняется встроенным. Я покажу несколько способов выполнить это путем конвейерной обработки без редактирования существующего фрейма данных.
Настройка 1
Чтобы сфокусироваться на необходимости переименовать имена заменяемых столбцов в уже существующий список, я создам новый образец dataframe 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
Используйте 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
Я хотел бы немного объяснить, что происходит за кулисами.
Dataframes - это набор из серии.
Ряды поочередно являются продолжением a numpy.array
numpy.array имеют свойство .name
Это название серии. Редко, что pandas уважает этот атрибут, но он задерживается в местах и может быть использован для взлома поведения pandas.
Здесь много ответов говорит об атрибуте df.columns, являющемся list, когда на самом деле это Series. Это означает, что он имеет атрибут .name.
Вот что произойдет, если вы решите заполнить имя столбцов Series:
df.columns = ['column_one', 'column_two']
df.columns.names = ['name of the list of columns']
df.index.names = ['name of the index']
name of the list of columns column_one column_two
name of the index
0 4 1
1 5 2
2 6 3
Обратите внимание, что имя индекса всегда приходит на один столбец ниже.
Атрибут .name иногда задерживается. Если вы установите df.columns = ['one', 'two'], то df.one.name будет 'one'.
Если вы установите df.one.name = 'three', то df.columns все равно даст вам ['one', 'two'], а df.one.name предоставит вам 'three'
pd.DataFrame(df.one) вернет
three
0 1
1 2
2 3
Поскольку pandas повторно использует .name уже определенного Series.
Pandas имеет способы создания многоуровневых имен столбцов. Мало задействовано не так много, но я хотел осветить это в своем ответе, так как я не вижу, чтобы кто-то собирал это здесь.
|one |
|one |two |
0 | 4 | 1 |
1 | 5 | 2 |
2 | 6 | 3 |
Это легко достижимо, установив столбцы в списки, например:
df.columns = [['one', 'one'], ['one', 'two']]
df.rename(columns = {'Old Name':'New Name'})
df - это DataFrame, который у вас есть, а Старое имя - это имя столбца, которое вы хотите изменить, то Новое имя - это новое имя, которое вы изменили. Этот встроенный метод DataFrame упрощает работу.
Если у вас есть dataframe, df.columns выгружает все в список, который вы можете манипулировать, а затем переназначать в свой фреймворк как имена столбцов...
columns = df.columns
columns = [row.replace("$","") for row in columns]
df.rename(columns=dict(zip(columns, things)), inplace=True)
df.head() #to validate the output
Лучший способ? ИДК. Путь - да.
Лучше всего оценить все основные методы, предложенные в ответах на вопрос, ниже, используя cProfile для измерения памяти и времени выполнения. @kadee, @kaitlyn и @eumiro имели функции с самым быстрым временем выполнения, хотя эти функции настолько быстра, что мы сравниваем округление .000 и .001 секунд для всех ответов. Мораль: мой ответ выше, вероятно, не является "Лучшим" способом.
import pandas as pd
import cProfile, pstats, re
old_names = ['$a', '$b', '$c', '$d', '$e']
new_names = ['a', 'b', 'c', 'd', 'e']
col_dict = {'$a': 'a', '$b': 'b','$c':'c','$d':'d','$e':'e'}
df = pd.DataFrame({'$a':[1,2], '$b': [10,20],'$c':['bleep','blorp'],'$d':[1,2],'$e':['texa$','']})
df.head()
def eumiro(df,nn):
df.columns = nn
#This direct renaming approach is duplicated in methodology in several other answers:
return df
def lexual1(df):
return df.rename(columns=col_dict)
def lexual2(df,col_dict):
return df.rename(columns=col_dict, inplace=True)
def Panda_Master_Hayden(df):
return df.rename(columns=lambda x: x[1:], inplace=True)
def paulo1(df):
return df.rename(columns=lambda x: x.replace('$', ''))
def paulo2(df):
return df.rename(columns=lambda x: x.replace('$', ''), inplace=True)
def migloo(df,on,nn):
return df.rename(columns=dict(zip(on, nn)), inplace=True)
def kadee(df):
return df.columns.str.replace('$','')
def awo(df):
columns = df.columns
columns = [row.replace("$","") for row in columns]
return df.rename(columns=dict(zip(columns, '')), inplace=True)
def kaitlyn(df):
df.columns = [col.strip('$') for col in df.columns]
return df
print 'eumiro'
cProfile.run('eumiro(df,new_names)')
print 'lexual1'
cProfile.run('lexual1(df)')
print 'lexual2'
cProfile.run('lexual2(df,col_dict)')
print 'andy hayden'
cProfile.run('Panda_Master_Hayden(df)')
print 'paulo1'
cProfile.run('paulo1(df)')
print 'paulo2'
cProfile.run('paulo2(df)')
print 'migloo'
cProfile.run('migloo(df,old_names,new_names)')
print 'kadee'
cProfile.run('kadee(df)')
print 'awo'
cProfile.run('awo(df)')
print 'kaitlyn'
cProfile.run('kaitlyn(df)')
df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1], '$d': [1], '$e': [1]})
Если ваш новый список столбцов находится в том же порядке, что и существующие столбцы, назначение выполняется просто:
new_cols = ['a', 'b', 'c', 'd', 'e']
df.columns = new_cols
>>> df
a b c d e
0 1 1 1 1 1
Если у вас есть словарь с ключевыми именами старых столбцов с именами новых столбцов, вы можете сделать следующее:
d = {'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}
df.columns = df.columns.map(lambda col: d[col]) # Or `.map(d.get)` as pointed out by @PiRSquared.
>>> df
a b c d e
0 1 1 1 1 1
Если у вас нет сопоставления списка или словаря, вы можете лишить ведущий символ $ через понимание списка:
df.columns = [col[1:] if col[0] == '$' else col for col in df]
df = df.rename(columns=lambda n: n.replace('$', '')) - это функциональный способ решения этой проблемы.
df.rename(index=str,columns={'A':'a','B':'b'})
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html
Другой способ заменить исходные метки столбцов - удалить ненужные символы (здесь '$') из исходных ярлыков столбца.
Это можно было бы сделать, выполнив цикл for через df.columns и добавив разделенные столбцы в df.columns.
Вместо этого мы можем сделать это аккуратно в одном выражении, используя понимание списка, как показано ниже:
df.columns = [col.strip('$') for col in df.columns]
(strip метод в Python удаляет данный символ из начала и конца строки.)
Реальное простое использование
df.columns = ['Name1', 'Name2', 'Name3'...]
и он назначит имена столбцов по порядку, который вы поместите им
Вы можете использовать str.slice для этого:
df.columns = df.columns.str.slice(1)
Я знаю, что этот вопрос и ответ были пережеваны до смерти. Но я упомянул об этом для вдохновения для одной из проблем, которые у меня были. Я смог решить это, используя бит и куски из разных ответов, следовательно, предоставляя свой ответ, если кому-то это понадобится.
Мой метод является общим, в котором вы можете добавить дополнительные разделители посредством запятой, разделяющей переменную delimiters= и будущую ее защиту.
Рабочий код:
import pandas as pd
import re
df = pd.DataFrame({'$a':[1,2], '$b': [3,4],'$c':[5,6], '$d': [7,8], '$e': [9,10]})
delimiters = '$'
matchPattern = '|'.join(map(re.escape, delimiters))
df.columns = [re.split(matchPattern, i)[1] for i in df.columns ]
Вывод:
>>> df
$a $b $c $d $e
0 1 3 5 7 9
1 2 4 6 8 10
>>> df
a b c d e
0 1 3 5 7 9
1 2 4 6 8 10
Обратите внимание, что этот подход не работает для MultiIndex. Для MultiIndex вам нужно сделать что-то вроде следующего:
>>> df = pd.DataFrame({('$a','$x'):[1,2], ('$b','$y'): [3,4], ('e','f'):[5,6]})
>>> df
$a $b e
$x $y f
0 1 3 5
1 2 4 6
>>> rename = {('$a','$x'):('a','x'), ('$b','$y'):('b','y')}
>>> df.columns = pandas.MultiIndex.from_tuples([
rename.get(item, item) for item in df.columns.tolist()])
>>> df
a b e
x y f
0 1 3 5
1 2 4 6
Переименовать столбцы данных и заменить формат
import pandas as pd
data = {'year':[2015,2011,2007,2003,1999,1996,1992,1987,1983,1979,1975],
'team':['Australia','India','Australia','Australia','Australia','Sri Lanka','Pakistan','Australia','India','West Indies','West Indies'],
}
df = pd.DataFrame(data)
#Rename Columns
df.rename(columns={'year':'Years of Win','team':'Winning Team'}, inplace=True)
#Replace format
df = df.columns.str.replace(' ', '_')
Другой вариант - переименовать, используя регулярное выражение:
import pandas as pd
import re
df = pd.DataFrame({'$a':[1,2], '$b':[3,4], '$c':[5,6]})
df = df.rename(columns=lambda x: re.sub('\$','',x))
>>> df
a b c
0 1 3 5
1 2 4 6
Переименование столбцов при чтении кадра данных:
>>> df = pd.DataFrame({'$a': [1], '$b': [1], '$c': [1]}).rename(columns =
{'$a' : 'a','$b':'b','$c':'c'})
Out[1]:
a b c
0 1 1 1
Это, наверное, самое простое решение проблемы. Совершенно понятно, как это работает.
import pandas as pd
df.columns = [['$a', '$b', '$c', '$d', '$e']]
df.rename(columns = {'$a':'a','$b':'b','$c':'c','$d':'d','$e':'e'})
df.head()
Если вам приходится иметь дело с множеством столбцов, названных системой-поставщиком вне вашего контроля, я предложил следующий подход, который представляет собой комбинацию общего подхода и конкретных замен за один раз.
Сначала создайте словарь из имен столбцов данных, используя выражения регулярных выражений, чтобы отбросить определенные приложения имен столбцов, а затем добавьте конкретные замены в словарь для именования основных столбцов, как ожидается позже в принимающей базе данных.
Затем это применяется к кадру данных за один раз.
dict=dict(zip(df.columns,df.columns.str.replace('(:S$|:C1$|:L$|:D$|\.Serial:L$)','')))
dict['brand_timeseries:C1']='BTS'
dict['respid:L']='RespID'
dict['country:C1']='CountryID'
dict['pim1:D']='pim_actual'
df.rename(columns=dict, inplace=True)
Я вижу 3 простых способа
df.columns
вывод: ['$ a', '$ b', '$ c', '$ d', '$ e']
1.
df.columns = ['a', 'b', 'c', 'd', 'e']
2.
df.columns = df.columns.str.replace('$','')
3.
df.rename(columns={'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}, inplace=True)
Импортируйте библиотеки, которые помогут нам создать фрейм данных:
import pandas as pd
import numpy as np
Создать Dataframe:
df = pd.DataFrame(np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9]]), columns=['a', 'b', 'c'])
Переименовать Dataframe:
df.rename(columns={'a':'x', 'b':'y', 'c':'z'}, index=str)
df.columns теперь должен иметь разные значения
Вот изящная маленькая функция, которую я хотел бы использовать, чтобы сократить печатание:
def rename(data, oldnames, newname):
if type(oldnames) == str: #input can be a string or list of strings
oldnames = [oldnames] #when renaming multiple columns
newname = [newname] #make sure you pass the corresponding list of new names
i = 0
for name in oldnames:
oldvar = [c for c in data.columns if name in c]
if len(oldvar) == 0:
raise ValueError("Sorry, couldn't find that column in the dataset")
if len(oldvar) > 1: #doesn't have to be an exact match
print("Found multiple columns that matched " + str(name) + " :")
for c in oldvar:
print(str(oldvar.index(c)) + ": " + str(c))
ind = input('please enter the index of the column you would like to rename: ')
oldvar = oldvar[int(ind)]
if len(oldvar) == 1:
oldvar = oldvar[0]
data = data.rename(columns = {oldvar : newname[i]})
i += 1
return data
Вот пример того, как это работает:
In [2]: df = pd.DataFrame(np.random.randint(0,10,size=(10, 4)), columns=['col1','col2','omg','idk'])
#first list = existing variables
#second list = new names for those variables
In [3]: df = rename(df, ['col','omg'],['first','ohmy'])
Found multiple columns that matched col :
0: col1
1: col2
please enter the index of the column you would like to rename: 0
In [4]: df.columns
Out[5]: Index(['first', 'col2', 'ohmy', 'idk'], dtype='object')
Если вам не нужны имена строк df.columns = ['a', 'b',index=False]