Да, ==
плохо для сравнения строк (любые объекты действительно, если вы не знаете, что они канонические). ==
просто сравнивает ссылки на объекты. .equals()
тесты для равенства. Для строк часто они будут такими же, но, как вы обнаружили, это не гарантируется всегда.
Просто назначьте его атрибуту .columns
:
>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
a b
0 1 10
1 2 20
df.columns = ['a', 'b', 'c', 'd', 'e']
Он заменит существующие имена именами, которые вы предоставляете, в указанном вами порядке.
Вы также можете назначить их по индексу следующим образом:
df.columns.values[2] = 'c' #renames the 2nd column to 'c' (in position #3)
df.columns.values
, это неправильно. [Д0] stackoverflow.com/questions/43291781/…
– liliscent
17 May 2018 в 08:53
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]
lambda col: d[col]
вы можете пройти d.get
... так что это будет выглядеть как df.columns.map(d.get)
– piRSquared
13 September 2017 в 08:48
Если у вас есть 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 для измерения памяти и amp; время исполнения. @kadee, @kaitlyn, & amp; У @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)')
Метод rename
может принимать функцию, например:
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)
df.rename(columns=lambda x: x.lstrip(), inplace=True)
– root-11
21 October 2013 в 23:05
t.columns = t.columns.str.replace(r'[^\x00-\x7F]+','')
– The Red Pea
5 November 2015 в 07:30
df.rename(columns=lambda x: x.replace(' ', '_'), inplace=True)
- это драгоценный камень, поэтому мы можем записать df.Column_1_Name
вместо записи df.loc[:, 'Column 1 Name']
.
– josh
16 December 2016 в 16:40
Я знаю, что этот вопрос и ответ были пережеваны до смерти. Но я упомянул об этом для вдохновения для одной из проблем, которые у меня были. Я смог решить это, используя бит и куски из разных ответов, следовательно, предоставляя свой ответ, если кому-то это понадобится.
Мой метод является общим, в котором вы можете добавить дополнительные разделители посредством запятой, разделяющей переменную 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
Вы можете использовать str.slice
для этого:
df.columns = df.columns.str.slice(1)
Если вы не хотите, чтобы имена строк df.columns = ['a', 'b',index=False]
pd.rename(index=str,columns={'A':'a','B':'b'})
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html
Я хотел бы немного объяснить, что происходит за кулисами.
Dataframes - это набор сериалов.
Ряды в свою очередь являются расширением numpy.array
numpy.array
s имеют свойство .name
Это имя серии. Редко, что панды уважают этот атрибут, но он задерживается в местах и может быть использован для взлома некоторых поведений панд.
В этом много ответов говорится о атрибут 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, который у вас есть, а Old Name - это имя столбца, которое вы хотите изменить, затем New Имя - это новое имя, которое вы изменили. Этот встроенный метод DataFrame упрощает работу.
blockquote>
В версии 0.21 были внесены существенные обновления для переименования столбцов.
rename
добавил параметр axis
, который может быть установлен на columns
или 1
. Это обновление делает этот метод совпадением с остальной частью API pandas. У него все еще есть параметры 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()
Pandas 0.21+ answer
- почему-то я пропустил эту часть в «что нового»? часть...
– MaxU
22 November 2017 в 14:27
Как описано в http://pandas.pydata.org/pandas-docs/stable/text.html :
df.columns = df.columns.str.replace('$','')
Если вам приходится иметь дело с множеством столбцов, названных системой предоставления из-под вашего контроля, я пришел к следующему подходу, который представляет собой комбинацию общего подхода и конкретных замещений за один раз.
Сначала я создаю словарь из имен столбцов dataframe с использованием выражений регулярных выражений, чтобы отбросить определенные приложения имен столбцов, а затем я добавлю определенные замены в словарь для обозначения основных столбцов, как ожидается, позже в принимающей базе данных.
Затем это применяется к кадру данных за один раз.
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)
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.columns = ['a', 'b', 'c', 'd', 'e']
проще.
– Christopher Pearson
22 June 2015 в 22:05
df.columns.values
для получения старых имен.
– bkowshik
20 July 2015 в 07:18
myList = list(df) myList[10:20]
и т. Д., Поэтому это прекрасно.
– Tim Gottgetreu
12 July 2017 в 23:12
Обратите внимание, что этот подход не работает для 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
Поскольку вы хотите удалить знак $ во всех именах столбцов, вы можете просто сделать:
df = df.rename(columns=lambda x: x.replace('$', ''))
ИЛИ
df.rename(columns=lambda x: x.replace('$', ''), inplace=True)
Еще один способ заменить исходные метки столбцов - удалить ненужные символы (здесь '$') из исходных ярлыков столбца.
Это могло быть сделано путем запуска цикла for по df. столбцы и добавление разделенных столбцов в df.columns.
Вместо этого мы можем сделать это аккуратно в одном выражении, используя понимание списка, как показано ниже:
df.columns = [col.strip('$') for col in df.columns]
(strip
метод в Python передает данный символ из начала и конца строки.)
Я сосредоточусь на двух вещах:
'$'
или отбрасывать первый символ каждого заголовка столбца. ОП уже сделал этот шаг. Вместо этого я хочу сосредоточиться на замене существующего объекта columns
на новый, заданный список заменяющих имен столбцов. df.columns = new
где new
- список имен новых столбцов, так же просто, как и он получает. Недостатком этого подхода является то, что он требует редактирования существующего атрибута columns
существующего dataframe, и он не выполняется inline. Я покажу несколько способов выполнить это с помощью конвейерной обработки без редактирования существующего фрейма данных. Настройка 1 Чтобы сосредоточиться на необходимости переименовать имена заменяемых столбцов на уже существующие list, я создам новый образец 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
Mixed 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
Переименовать столбцы данных и заменить формат
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
Вот небольшая небольшая функция, которую я хотел бы использовать, чтобы нарезать:
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 = ['Name1', 'Name2', 'Name3'...]
, и он назначит имена столбцов по порядку, который вы поместите им
Используйте функцию 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)
code
& lt; class 'pandas.core.frame.DataFrame' & gt; Int64Index: 1000 записей, от 0 до 999. Столбцы данных: BodyMarkdown 1000 non-null code
работает, но когда я делаю dataframe.head (), старые имена столбцов снова появляются.
– darKoram
10 September 2012 в 23:39
SettingWithCopyWarning:
, когда я использую второй фрагмент кода в этом ответе.
– Monica Heddneck
18 August 2016 в 19:47
df = df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'})
изменяет отображаемое имя, но not i> элементы в базовой структуре данных. Поэтому, если вы попробуете df['newName1']
, вы получите сообщение об ошибке. inplace=True
необходим, чтобы избежать этого.
– irritable_phd_syndrom
14 July 2017 в 13:24
new_columns = df.columns.values;
new_columns[0] = 'XX';
df.columns = new_columns
– cd98 20 November 2013 в 16:18df.rename(columns = {'$b':'B'}, inplace = True)
– nachocab 11 September 2015 в 22:30