ylabel - subplot title python




重命名熊貓中的列 (16)

我有一個使用熊貓和列標籤的DataFrame,我需要編輯以替換原始列標籤。

我想更改DataFrame A中的列名,其中原始列名是:

['$a', '$b', '$c', '$d', '$e'] 

['a', 'b', 'c', 'd', 'e'].

我將編輯過的列名存儲在列表中,但我不知道如何替換列名。


DataFrame - df.rename()將工作。

df.rename(columns = {'Old Name':'New Name'})

df是您擁有的DataFrame, 舊名稱是要更改的列名稱,則新名稱是您更改為的新名稱。 這種DataFrame內置方法使事情變得更容易。


一條線或管線解決方案

我將專注於兩件事情:

  1. OP明確指出

    我將編輯過的列名存儲在列表中,但我不知道如何替換列名。

    我不想解決如何替換'$'或從每個列標題剝離第一個字符的問題。 OP已經完成了這一步。 相反,我想專注於使用替換列名稱列表替換現有columns對象。

  2. df.columns = new其中new是新列名稱的列表,非常簡單。 這種方法的缺點是它需要編輯現有的數據框的columns屬性,而不是內聯完成的。 我將通過流水線顯示幾種方式來執行此操作,而無需編輯現有數據框。

設置1
為了專注於重新命名使用預先存在的列表替換列名的需要,我將創建一個新的示例數據框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 。 相反,我們可以在遍歷df的列時使用pd.concat函數的keys參數。

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
這是一個帶有transposeset_index的噱頭戲法。 pd.DataFrame.set_index允許我們設置一個內聯索引,但沒有對應的set_columns 。 所以我們可以轉置,然後set_index ,並轉置回來。 但是,解決方案3中的單個dtype與混合dtype警告相同。

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
pd.DataFrame.rename中使用循環遍歷new每個元素的lambda
在這個解決方案中,我們傳遞一個需要x但是忽略它的lambda。 它也需要一個y但不期望它。 相反,迭代器是作為默認值給出的,然後我可以使用它循環一次,而不考慮x的值。

df.rename(columns=lambda x, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

正如sopython聊天中的人們指出的那樣,如果我在xy之間添加* ,我可以保護我的y變量。 雖然在這種情況下,我不相信它需要保護。 它仍然值得一提。

df.rename(columns=lambda x, *, y=iter(new): next(y))

   x098  y765  z432
0     1     3     5
1     2     4     6

熊貓0.21+答案

在版本0.21中對列重命名進行了一些重大更新。

  • rename方法添加了可以設置為columns1axis參數。 此更新使此方法與熊貓API的其餘部分相匹配。 它仍然有indexcolumns參數,但你不再被迫使用它們。
  • set_axis設置為Falseset_axis方法使您可以使用列表重命名所有索引或列標籤。

熊貓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

使用axis='columns'axis=1 rename

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與list和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.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()函數並引用要重命名的列。 並非所有列都必須重命名:

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.columns上運行for循環並將刪除的列添加到df.columns來完成。

相反,我們可以通過使用如下所示的列表理解,在單個語句中整齊地做到這一點:

df.columns = [col.strip('$') for col in df.columns]

(Python中的strip方法從字符串的開頭和結尾剝離給定的字符。)


嘗試這個。 這個對我有用

df.rename(index=str, columns={"$a": "a", "$b": "b", "$c" : "c", "$d" : "d", "$e" : "e"})


如果您不得不處理由您的控制系統提供的系統命名的大量列,我提出了以下一種方法,即將一般方法和特定的替換組合在一起。

我首先使用正則表達式從數據框列名稱中創建一個字典,以便丟棄列名的某些附錄,然後在字典中添加特定的替換,以便在接收數據庫中稍後預期命名核心列。

然後將其一次應用於數據框。

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)

如果您有數據框,則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

最好的辦法? IDK。 一種方式 - 是的。

評估問題答案中提出的所有主要技術的更好方法是使用cProfile來測量內存和執行時間。 @kadee,@kaitlyn和@eumiro具有最快執行時間的功能 - 雖然這些功能非常快,但我們正在比較所有答案的.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(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"})

該方法允許您單獨更改列名稱。


既然你只想刪除所有列名中的$符號,你可以這樣做:

df = df.rename(columns=lambda x: x.replace('$', ''))

要么

df.rename(columns=lambda x: x.replace('$', ''), inplace=True)

請注意,這些方法不適用於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

這裡有一個我喜歡用來減少打字的漂亮小功能:

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'])

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 = 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.columns = ['a', 'b', 'c', 'd', 'e']

它會按照您提供的順序,用您提供的名稱替換現有名稱。

你也可以像這樣通過索引來分配它們:

df.columns.values[2] = 'c'    #renames the 2nd column to 'c' (in position #3)






rename