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 ]
Output:
>>> 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
30
列名称与系列名称
我想解释一下幕后发生的事情 .
数据帧是一组系列 .
系列又是 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
# 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={'oldName1': 'newName1', 'oldName2': 'newName2'})
# Or rename the existing DataFrame (rather than creating a copy)
df.rename(columns={'oldName1': 'newName1', 'oldName2': 'newName2'}, inplace=True)
13
另一个选项是使用正则表达式重命名:
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
4
这是一个漂亮的小功能,我喜欢用它来减少打字:
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')
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]
28 回答
如果你不想要行名
df.columns = ['a', 'b',index=False]
我认为这种方法很有用:
此方法允许您单独更改列名称 .
我知道这个问题和答案已被咀嚼致死 . 但我提到它是我遇到的一个问题的灵感来源 . 我能够使用来自不同答案的点点滴滴解决它,从而在任何人需要时提供我的回复 .
我的方法是通用的,您可以通过逗号分隔
delimiters=
变量和将来证明它来添加其他分隔符 .Working Code:
Output:
列名称与系列名称
我想解释一下幕后发生的事情 .
数据帧是一组系列 .
系列又是
numpy.array
的延伸numpy.array
s有一个属性.name
这是该系列的名称 . 很少有熊猫尊重这个属性,但它在某些地方徘徊,可以用来破解一些熊猫行为 .
命名列的列表
这里有很多答案说
df.columns
属性是list
,实际上它是Series
. 这意味着它具有.name
属性 .如果您决定填写
Series
列的名称,会发生这种情况:请注意,索引的名称总是低一列 .
徘徊的文物
.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)
将返回因为pandas重用已定义的
Series
的.name
.多级列名
Pandas有办法做多层列名 . 没有太多的魔法涉及,但我想在我的答案中涵盖这个,因为我没有看到有人在这里接受这个 .
通过将列设置为列表可以轻松实现这一点,如下所示:
我们可以替换原始列标签的另一种方法是从原始列标签中剥离不需要的字符(此处为“$”) .
这可以通过在df.columns上运行for循环并将剥离的列附加到df.columns来完成 .
相反,我们可以通过使用下面的列表理解在一个语句中巧妙地做到这一点:
(
strip
Python中的方法从字符串的开头和结尾剥离给定的字符 . )只需将其分配给
.columns
属性:如http://pandas.pydata.org/pandas-docs/stable/text.html中所述:
由于您只想删除所有列名中的$符号,您可以这样做:
要么
如果你不得不处理由提供系统命名的大量列的控制,我想出了以下方法,即一次性方法和特定替换的组合 .
我首先使用正则表达式从数据框列名创建一个字典,以便抛弃某些字典列名的附录,然后我在字典中添加特定的替换,以便在接收数据库中稍后按预期命名核心列 .
然后将其一次性应用于数据帧 .
熊猫0.21答案
版本0.21中的列重命名有一些重要更新 .
rename method添加了
axis
参数,该参数可以设置为columns
或1
. 此更新使此方法与其余的pandas API匹配 . 它仍然具有index
和columns
参数,但您不再被迫使用它们 .set_axis method且
inplace
设置为False
使您可以使用列表重命名所有索引或列标签 .熊猫的例子0.21
构造示例DataFrame:
使用axis ='columns'或axis = 1重命名
要么
两者都导致以下结果:
仍然可以使用旧方法签名:
rename
函数还接受将应用于每个列名称的函数 .要么
将set_axis与list和inplace = False一起使用
您可以为
set_axis
方法提供一个列表,该列表的长度与列数(或索引)相等 . 目前,inplace
默认为True
,但inplace
将在以后的版本中默认为False
.要么
为什么不使用df.columns = ['a','b','c','d','e']?
像这样直接分配列没有任何问题 . 这是一个非常好的解决方案 .
使用
set_axis
的优点是它可以用作方法链的一部分,并返回DataFrame的新副本 . 没有它,您必须在重新分配列之前将链的中间步骤存储到另一个变量 .如果你有数据帧,df.columns将所有内容转储到你可以操作的列表中,然后作为列的名称重新分配到你的数据帧中......
最好的办法? IDK . 一种方式 - 是的 .
评估所有主要技术的更好方法在下面的问题的答案中使用cProfile来记录内存和执行时间 . @kadee,@ kaitlyn和@eumiro具有执行时间最快的功能 - 尽管这些功能如此之快,我们正在比较所有答案的.000和.001秒的舍入 . 道德:我上面的回答很可能不是'最好'的方式 .
它将按您提供的顺序用您提供的名称替换现有名称 .
请注意,这些方法不适用于MultiIndex . 对于MultiIndex,您需要执行以下操作:
这样您就可以根据需要手动编辑
new_names
. 当您只需要重命名几列以纠正错误拼写,重音,删除特殊字符等时,效果很好 .您可以使用str.slice:
一条线或管道解决方案
我会专注于两件事:
我不想解决如何替换
'$'
或从每个列 Headers 中删除第一个字符的问题 . OP已经完成了这一步 . 相反,我想专注于使用给定替换列名列表的新对象替换现有的columns
对象 .df.columns = new
其中new
是新列名称的列表,就像它获得的一样简单 . 这种方法的缺点是它需要编辑现有数据框的columns
属性,并且它没有显示通过流水线操作执行此操作而无需编辑现有数据框的几种方法 .Setup 1
为了专注于需要使用预先存在的列表重命名替换列名,我将创建一个新的示例数据框
df
,其中包含初始列名和不相关的新列名 .Solution 1
pd.DataFrame.rename
已经说过 if 你有一个将旧列名称映射到新列名的字典,你可以使用
pd.DataFrame.rename
.但是,您可以轻松地创建该字典并将其包含在对
rename
的调用中 . 以下利用了以下事实:当迭代df
时,我们迭代每个列名 .如果原始列名称是唯一的,则此方法很有用 . 但如果他们不是,那么这就会崩溃 .
Setup 2
非唯一列
Solution 2
pd.concat使用
keys
参数首先,注意当我们尝试使用解决方案1时会发生什么:
我们没有将
new
列表映射为列名 . 我们最终重复y765
. 相反,我们可以在迭代df
的列时使用pd.concat
函数的keys
参数 .Solution 3
重建 . 仅当您对所有列都有一个
dtype
时才应使用此选项 . 否则,对于所有列,您最终会得到dtype
object
并将其转换回来需要更多字典工作 .单
dtype
混合
dtype
Solution 4
这是一个带有
transpose
和set_index
的花哨技巧 . pd.DataFrame.set_index允许我们设置内联索引,但没有相应的set_columns
. 所以我们可以转置,然后set_index
,并转置回来 . 但是,解决方案3中的相同单一dtype
与混合dtype
警告适用于此处 .单
dtype
混合
dtype
Solution 5
在_179107中使用
lambda
循环遍历new
的每个元素在这个解决方案中,我们传递一个lambda,它接受
x
然后忽略它 . 它也需要y
但不要指望它 . 相反,迭代器作为默认值给出,然后我可以使用它来循环一次,而不考虑x
的值 .正如sopython聊天中的人们指出的那样,如果我在
x
和y
之间添加*
,我可以保护我的y
变量 . 虽然,在这种情况下,我不认为它需要保护 . 值得一提的是 .DataFrame - df.rename()将起作用 .
The rename dataframe columns and replace format
试试这个 . 这个对我有用
https://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.rename.html
使用df.rename()函数并引用要重命名的列 . 并非所有列都必须重命名:
另一个选项是使用正则表达式重命名:
这是一个漂亮的小功能,我喜欢用它来减少打字:
以下是它的工作原理示例:
是一种解决这个问题的功能性方法
真正的简单只是使用
它将按照您放置它们的顺序分配列名称
rename方法可以采用一个函数,例如:
如果新列的列与现有列的顺序相同,则分配很简单:
如果您将旧列名称上的字典键入新列名称,则可以执行以下操作:
如果您没有列表或字典映射,则可以通过列表解析删除前导
$
符号: