Переименование столбцов в пандах
У меня есть DataFrame, использующий панды и метки столбцов, которые мне нужно отредактировать, чтобы заменить оригинальные метки столбцов.
Я хотел бы изменить имена столбцов в DataFrame A
где исходные имена столбцов:
['$a', '$b', '$c', '$d', '$e']
в
['a', 'b', 'c', 'd', 'e'].
У меня есть отредактированные имена столбцов, которые хранятся в списке, но я не знаю, как заменить имена столбцов.
45 ответов
Просто назначьте его .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)
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)
Как описано в http://pandas.pydata.org/pandas-docs/stable/text.html:
df.columns = df.columns.str.replace('$','')
Панды 0.21+ Ответ
Произошли некоторые существенные обновления переименования столбцов в версии 0.21.
rename
метод добавилaxis
параметр, который может быть установлен вcolumns
или же1
, Это обновление делает этот метод соответствующим остальному API панд. Это все еще имеетindex
а такжеcolumns
параметры, но вы больше не обязаны их использовать.set_axis
метод сinplace
установлен вFalse
позволяет переименовать все метки индекса или столбца в список.
Примеры для панд 0.21+
Создайте образец 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.rename(columns={'$a': 'a', '$b': 'b', '$c': 'c', '$d': 'd', '$e': 'e'}, 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
как хотите. Прекрасно работает, когда вам нужно переименовать только несколько столбцов, чтобы исправить неправильное написание, акценты, удалить специальные символы и т. Д.
One line or Pipeline solutions
I'll focus on two things:
OP clearly states
I have the edited column names stored it in a list, but I don't know how to replace the column names.
I do not want to solve the problem of how to replace
'$'
or strip the first character off of each column header. OP has already done this step. Instead I want to focus on replacing the existingcolumns
object with a new one given a list of replacement column names.df.columns = new
гдеnew
is the list of new columns names is as simple as it gets. The drawback of this approach is that it requires editing the existing dataframe'scolumns
attribute and it isn't done inline. I'll show a few ways to perform this via pipelining without editing the existing dataframe.
Setup 1
To focus on the need to rename of replace column names with a pre-existing list, I'll create a new sample dataframe df
with initial column names and unrelated new column names.
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
It has been said already that if you had a dictionary mapping the old column names to new column names, you could use 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
However, you can easily create that dictionary and include it in the call to rename
, The following takes advantage of the fact that when iterating over df
, we iterate over each column name.
# 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
This works great if your original column names are unique. But if they are not, then this breaks down.
Setup 2
non-unique columns
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
аргумент
First, notice what happens when we attempt to use solution 1:
df.rename(columns=dict(zip(df, new)))
y765 y765 z432
0 1 3 5
1 2 4 6
We didn't map the new
list as the column names. We ended up repeating y765
, Instead, we can use the keys
аргумент pd.concat
function while iterating through the columns of 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
Reconstruct. This should only be used if you have a single dtype
for all columns. Otherwise, you'll end up with dtype
object
for all columns and converting them back requires more dictionary work.
не замужем 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
Solution 4
This is a gimmicky trick with transpose
а также set_index
, pd.DataFrame.set_index
allows us to set an index inline but there is no corresponding set_columns
, So we can transpose, then set_index
, and transpose back. However, the same single dtype
versus mixed dtype
caveat from solution 3 applies here.
не замужем 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
Solution 5
Использовать lambda
в pd.DataFrame.rename
that cycles through each element of new
In this solution, we pass a lambda that takes x
but then ignores it. It also takes a y
but doesn't expect it. Instead, an iterator is given as a default value and I can then use that to cycle through one at a time without regard to what the value of x
является.
df.rename(columns=lambda x, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6
And as pointed out to me by the folks in sopython chat, if I add a *
между x
а также y
, I can protect my y
переменная. Though, in this context I don't believe it needs protecting. It is still worth mentioning.
df.rename(columns=lambda x, *, y=iter(new): next(y))
x098 y765 z432
0 1 3 5
1 2 4 6
Имена столбцов и имена серий
Я хотел бы немного объяснить, что происходит за кулисами.
Датафреймы представляют собой набор Series.
Серия, в свою очередь, является продолжением numpy.array
numpy.array
у собственности .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
Потому что панды повторно использует .name
из уже определенного Series
,
Многоуровневые имена столбцов
У Панд есть способы создания многослойных имен столбцов. В этом не так много магии, но я хотел бы рассказать об этом и в своем ответе, так как не вижу здесь никого, кто бы мог это понять.
|one |
|one |two |
0 | 4 | 1 |
1 | 5 | 2 |
2 | 6 | 3 |
Этого легко достичь, установив столбцы в списки, например так:
df.columns = [['one', 'one'], ['one', 'two']]
Многие функции pandas имеют параметр inplace. При установке значения True преобразование применяется непосредственно к фрейму данных, для которого вы его вызываете. Например:
df = pd.DataFrame({'$a':[1,2], '$b': [3,4]})
df.rename(columns={'$a': 'a'}, inplace=True)
df.columns
>>> Index(['a', '$b'], dtype='object')
В качестве альтернативы, есть случаи, когда вы хотите сохранить исходный фрейм данных. Я часто видел, как люди попадают в этот случай, если создание фрейма данных - дорогостоящая задача. Например, если для создания фрейма данных потребовался запрос к базе данных снежинок. В этом случае просто убедитесь, что для параметра inplace установлено значение False.
df = pd.DataFrame({'$a':[1,2], '$b': [3,4]})
df2 = df.rename(columns={'$a': 'a'}, inplace=False)
df.columns
>>> Index(['$a', '$b'], dtype='object')
df2.columns
>>> Index(['a', '$b'], dtype='object')
Если эти типы преобразований - то, что вы делаете часто, вы также можете изучить ряд различных инструментов графического интерфейса pandas. Я создатель одного под названием Mito. Это электронная таблица, которая автоматически преобразует ваши изменения в код Python.
Я думаю, что этот метод полезен:
df.rename(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"})
Этот метод позволяет изменять имена столбцов индивидуально.
Давайте разберемся с переименованием на небольшом примере...
1. переименование столбцов с использованием сопоставления:
df = pd.DataFrame({"A": [1, 2, 3], "B": [4, 5, 6]}) #creating a df with column name A and B
df.rename({"A": "new_a", "B": "new_b"},axis='columns',inplace =True) #renaming column A with 'new_a' and B with 'new_b'
output:
new_a new_b
0 1 4
1 2 5
2 3 6
2.Переименование index/Row_Name с использованием сопоставления:
df.rename({0: "x", 1: "y", 2: "z"},axis='index',inplace =True) #Row name are getting replaced by 'x','y','z'.
output:
new_a new_b
x 1 4
y 2 5
z 3 6
Предположим, что имя вашего набора данных - df, а df -.
df = ['$a', '$b', '$c', '$d', '$e']`
Итак, чтобы переименовать их, мы просто сделаем это.
df.columns = ['a','b','c','d','e']
Допустим, это ваш фрейм данных.
Вы можете переименовать столбцы двумя способами.
Использование dataframe.columns = [# list]
df.columns = [ 'а', 'б', 'с', 'd', 'е']
Ограничением этого метода является то, что если требуется изменить один столбец, необходимо передать полный список столбцов. Кроме того, этот метод не применим к индексным меткам. Например, если вы передали это:
df.columns = ['a','b','c','d']
Это выдаст ошибку. Несоответствие длины: ожидаемая ось имеет 5 элементов, новые значения имеют 4 элемента.
Другим методом является метод Pandas rename(), который используется для переименования любого индекса, столбца или строки.
df = df.rename(columns={'$a':'a'})
Точно так же вы можете изменить любые строки или столбцы.
Если у вас уже есть список для новых имен столбцов, вы можете попробовать следующее:
new_names = ['a', 'b', 'c', 'd', 'e']
new_names_map = {df.columns[i]:new_cols[i] for i in range(len(new_cols))}
df.rename(new_names_map, axis=1, inplace=True)
Если у вас есть датафрейм, 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 были функции с самым быстрым временем выполнения - хотя эти функции настолько быстры, что мы сравниваем округление в 0,000 и 0,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.rename(index=str,columns={'A':'a','B':'b'})
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html
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]
Другой способ, которым мы могли бы заменить исходные метки столбцов, - это удалить ненужные символы (здесь "$") с оригинальных меток столбцов.
Это можно было сделать, запустив цикл for над df.columns и добавив раздетые столбцы в df.columns.
Вместо этого мы можем сделать это аккуратно в одном выражении, используя понимание списка, как показано ниже:
df.columns = [col.strip('$') for col in df.columns]
(strip
Метод в Python удаляет данный символ из начала и конца строки.)
DataFrame - df.rename() будет работать.
df.rename(columns = {'Old Name':'New Name'})
df - это имеющийся у вас DataFrame, а Old Name - это имя столбца, который вы хотите изменить, затем New Name - это новое имя, на которое вы изменяете. Этот встроенный метод DataFrame значительно упрощает работу.
Очень просто использовать
df.columns = ['Name1', 'Name2', 'Name3'...]
и он назначит имена столбцов в порядке их размещения
This way it will work
import pandas as pd
# Define a dictionary
rankings = {'test': ['a'],
'odi': ['E'],
't20': ['P']}
# Convert the dictionary into DataFrame
rankings_pd = pd.DataFrame(rankings)
# Before renaming the columns
print(rankings_pd)
rankings_pd.rename(columns = {'test':'TEST'}, inplace = True)
Вы могли бы использовать str.slice
для этого:
df.columns = df.columns.str.slice(1)
df = df.rename(columns=lambda n: n.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
Я знаю этот вопрос, и ответ был разжеван до смерти. Но я обратился к нему за вдохновением для решения одной из моих проблем. Я был в состоянии решить это, используя кусочки от разных ответов, поэтому предоставил свой ответ на тот случай, если кому-то это понадобится.
Мой метод является общим, в котором вы можете добавить дополнительные разделители через запятую 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
Если вам приходится иметь дело с множеством столбцов, названных системой-поставщиком вне вашего контроля, я предложил следующий подход, который представляет собой комбинацию общего подхода и конкретных замен за один раз.
Сначала я создаю словарь из имен столбцов данных, используя выражения регулярных выражений, чтобы отбросить определенные приложения имен столбцов, а затем добавляю конкретные замены в словарь для именования основных столбцов, как и ожидалось позже в принимающей базе данных.
Затем это применяется к кадру данных за один раз.
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)