Переименование столбцов в пандах

У меня есть 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:

  1. 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 existing columns object with a new one given a list of replacement column names.

  2. 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's columns 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 dtypeobject 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']

Допустим, это ваш фрейм данных.

Вы можете переименовать столбцы двумя способами.

  1. Использование dataframe.columns = [# list]

    df.columns = [ 'а', 'б', 'с', 'd', 'е']

Ограничением этого метода является то, что если требуется изменить один столбец, необходимо передать полный список столбцов. Кроме того, этот метод не применим к индексным меткам. Например, если вы передали это:

df.columns = ['a','b','c','d']

Это выдаст ошибку. Несоответствие длины: ожидаемая ось имеет 5 элементов, новые значения имеют 4 элемента.

  1. Другим методом является метод 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 = 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)
Другие вопросы по тегам