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 الأشياء أكثر سهولة.
Pandas 0.21+ الجواب
كانت هناك بعض التحديثات الهامة لإعادة تسمية العمود في الإصدار 0.21.
- أضافت طريقة
rename
axis
معلمةaxis
التي يمكن ضبطها علىcolumns
أو1
. يجعل هذا التحديث هذه الطريقة مطابقة لبقية API pandas. لا يزال يحتوي على معلماتindex
columns
ولكن لم تعد مضطرة لاستخدامها. -
set_axis
الأسلوبset_axis
معinplace
set_axis
إلىFalse
من إعادة تسمية كل الفهرس أو تصنيفات الأعمدة مع قائمة.
أمثلة ل Pandas 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'})
كما تقبل وظيفة إعادة التسمية الوظائف التي سيتم تطبيقها على كل اسم عمود.
df.rename(lambda x: x[1:], axis='columns')
أو
df.rename(lambda x: x[1:], axis=1)
باستخدام set_axis
مع قائمة و inplace=False
يمكنك توفير قائمة بطريقة set_axis
متساوية الطول لعدد الأعمدة (أو الفهرس). حاليًا ، سيتم تعيين الإعدادات الافتراضية في الوضع الحالي إلى 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()
خط واحد أو حلول خطوط الأنابيب
سأركز على شيئين:
البروتوكول الاختياري تنص بوضوح
لدي أسماء الأعمدة المعدلة المخزنة في قائمة ، لكنني لا أعرف كيفية استبدال أسماء الأعمدة.
لا أريد حل مشكلة كيفية استبدال
'$'
أو فصل الحرف الأول من كل رأس عمود. لقد قام OP بالفعل بهذه الخطوة. بدلاً من ذلك ، أريد التركيز على استبدال كائنcolumns
الموجودةcolumns
جديدة ، مع توفير قائمة بأسماء أعمدة الاستبدال.df.columns = new
wherenew
is the list of new columns names is as simple as gets. العيب في هذا النهج هو أنه يتطلب تحرير سمةcolumns
مخطط البيانات الموجودة حاليًا ولا يتم تضمينها في السطر. سأعرض بعض الطرق لتنفيذ ذلك عبر خط الأنابيب دون تحرير مخطط البيانات الحالي.
الإعداد 1
للتركيز على الحاجة إلى إعادة تسمية استبدال أسماء الأعمدة بقائمة موجودة مسبقًا ، سوف أقوم بإنشاء نموذج جديد 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
أسماء الأعمدة القديمة إلى أسماء أعمدة جديدة ، فيمكنك استخدام 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
واحد لجميع الأعمدة. خلاف ذلك ، سوف ينتهي بك الأمر مع object
dtype
لجميع الأعمدة وتحويلها مرة أخرى يتطلب المزيد من العمل في القاموس.
نوع 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
واحد ضد dtype
caveat من الحل 3 هنا.
نوع 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
استخدم lambda
في pd.DataFrame.rename
الذي يمر عبر كل عنصر new
في هذا الحل ، نجتاز lambda يأخذ 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
أعتقد أن هذه الطريقة مفيدة:
df.rename(columns={"old_column_name1":"new_column_name1", "old_column_name2":"new_column_name2"})
تسمح لك هذه الطريقة بتغيير أسماء الأعمدة على حدة.
إذا كان عليك التعامل مع الكثير من الأعمدة التي يطلق عليها نظام التزويد خارج سيطرتك ، فقد توصلت إلى النهج التالي الذي هو مزيج من النهج العام والاستبدال المحدد في دفعة واحدة.
أولاً ، أنشئ قاموسًا من أسماء أعمدة برنامج dataframe باستخدام تعبيرات regex من أجل التخلص من بعض ملحقات أسماء الأعمدة ثم أقوم بإضافة بدائل معينة إلى القاموس لتسمية أعمدة أساسية كما هو متوقع في وقت لاحق في قاعدة بيانات الاستلام.
ثم يتم تطبيق ذلك على مخطط البيانات دفعة واحدة.
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)
إذا كنت قد حصلت على dataframe ، df.columns مقالب كل شيء في قائمة يمكنك التلاعب بها ومن ثم إعادة تعيين في dataframe الخاص بك كأسماء الأعمدة ...
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 إلى ذاكرة gage ووقت التنفيذ. كانkadee وkaitlyn وeumiro يتمتعون بوظائف ذات أوقات تنفيذ أسرع - على الرغم من أن هذه الوظائف سريعة جدًا ، فنحن نقارن تقريب 1000 و 0،01 ثانية لجميع الإجابات. الأخلاقية: إجابتي فوق الأرجح ليست طريقة "أفضل".
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()
الأعمدة المراد تسميتها. لا يجب إعادة تسمية جميع الأعمدة:
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.rename(index=str, columns={"$a": "a", "$b": "b", "$c" : "c", "$d" : "d", "$e" : "e"})
في حال كنت لا تريد أسماء الصف df.columns = ['a', 'b',index=False]
كما هو موثق في http://pandas.pydata.org/pandas-docs/stable/text.html :
df.columns = df.columns.str.replace('$','')
ما عليك .columns
تعيينها إلى سمة .columns
:
>>> df = pd.DataFrame({'$a':[1,2], '$b': [10,20]})
>>> df.columns = ['a', 'b']
>>> df
a b
0 1 10
1 2 20
نظرًا لأنك تريد فقط إزالة علامة $ في جميع أسماء الأعمدة ، فيمكنك إجراء ما يلي:
df = df.rename(columns=lambda x: x.replace('$', ''))
أو
df.rename(columns=lambda x: x.replace('$', ''), inplace=True)
يمكن أن تأخذ طريقة 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)
يمكنك استخدام str.slice
لذلك:
df.columns = df.columns.str.slice(1)
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)