Ответ 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=1
df.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]