python - كيفي - مكتبات لغة بايثون




إضافة عمود جديد إلى DataFrame الموجودة في الباندا بيثون (14)

أرغب في إضافة عمود جديد ، "e" ، إلى إطار البيانات الموجود ولا تقم بتغيير أي شيء في إطار البيانات. (المسلسل دائما حصلت على نفس الطول كما dataframe.)

أفترض أن قيم الفهرس في e تطابق تلك الموجودة في df1 .

أسهل طريقة لبدء عمود جديد باسم e ، وتعيينه القيم من السلسلة e :

df['e'] = e.values

تعيين (Pandas 0.16.0+)

اعتبارًا من Pandas 0.16.0 ، يمكنك أيضًا استخدام التعيين ، الذي يقوم بتعيين أعمدة جديدة إلى DataFrame وإرجاع كائن جديد (نسخة) مع كافة الأعمدة الأصلية بالإضافة إلى الأعمدة الجديدة.

df1 = df1.assign(e=e.values)

وفقًا لهذا المثال (الذي يتضمن أيضًا شفرة المصدر لوظيفة assign ) ، يمكنك أيضًا تضمين أكثر من عمود واحد:

df = pd.DataFrame({'a': [1, 2], 'b': [3, 4]})
>>> df.assign(mean_a=df.a.mean(), mean_b=df.b.mean())
   a  b  mean_a  mean_b
0  1  3     1.5     3.5
1  2  4     1.5     3.5

في السياق مع المثال الخاص بك:

np.random.seed(0)
df1 = pd.DataFrame(np.random.randn(10, 4), columns=['a', 'b', 'c', 'd'])
mask = df1.applymap(lambda x: x <-0.7)
df1 = df1[-mask.any(axis=1)]
sLength = len(df1['a'])
e = pd.Series(np.random.randn(sLength))

>>> df1
          a         b         c         d
0  1.764052  0.400157  0.978738  2.240893
2 -0.103219  0.410599  0.144044  1.454274
3  0.761038  0.121675  0.443863  0.333674
7  1.532779  1.469359  0.154947  0.378163
9  1.230291  1.202380 -0.387327 -0.302303

>>> e
0   -1.048553
1   -1.420018
2   -1.706270
3    1.950775
4   -0.509652
dtype: float64

df1 = df1.assign(e=e.values)

>>> df1
          a         b         c         d         e
0  1.764052  0.400157  0.978738  2.240893 -1.048553
2 -0.103219  0.410599  0.144044  1.454274 -1.420018
3  0.761038  0.121675  0.443863  0.333674 -1.706270
7  1.532779  1.469359  0.154947  0.378163  1.950775
9  1.230291  1.202380 -0.387327 -0.302303 -0.509652

يمكن العثور here وصف هذه الميزة الجديدة عند تقديمها لأول مرة.

لدي DataFrame المفهرسة التالية مع الأعمدة المسماة والصفوف أرقام غير مستمرة:

          a         b         c         d
2  0.671399  0.101208 -0.181532  0.241273
3  0.446172 -0.243316  0.051767  1.577318
5  0.614758  0.075793 -0.451460 -0.012493

أود إضافة عمود جديد ، 'e' ، إلى إطار البيانات الموجود ولا أريد تغيير أي شيء في إطار البيانات (أي أن العمود الجديد له نفس طول DataFrame دائمًا).

0   -0.335485
1   -1.166658
2   -0.385571
dtype: float64

حاولت إصدارات مختلفة من join ، append ، merge ، لكنني لم أحصل على النتيجة التي أردت ، فقط الأخطاء على الأكثر. كيف يمكنني إضافة عمود e إلى المثال أعلاه؟


تعيين العمود السوبر البسيط

يتم تنفيذ dataframe الباندا كما dict أمر من الأعمدة.

وهذا يعني أنه لا يمكن استخدام __getitem__ [] فقط للحصول على عمود معين ، ولكن يمكن استخدام __setitem__ [] = لتعيين عمود جديد.

على سبيل المثال ، يمكن أن يحتوي عمود البيانات هذا على عمود مضاف إليه ببساطة عن طريق استخدام ملحق []

    size      name color
0    big      rose   red
1  small    violet  blue
2  small     tulip   red
3  small  harebell  blue

df['protected'] = ['no', 'no', 'no', 'yes']

    size      name color protected
0    big      rose   red        no
1  small    violet  blue        no
2  small     tulip   red        no
3  small  harebell  blue       yes

لاحظ أن هذا يعمل حتى لو تم إيقاف فهرس dataframe.

df.index = [3,2,1,0]
df['protected'] = ['no', 'no', 'no', 'yes']
    size      name color protected
3    big      rose   red        no
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue       yes

[] = هو الطريق للذهاب ، ولكن احترس!

ومع ذلك ، إذا كان لديك pd.Series وحاول تعيينه إلى dataframe حيث يتم إيقاف تشغيل الفهارس ، فسوف تواجه مشكلة. انظر المثال:

df['protected'] = pd.Series(['no', 'no', 'no', 'yes'])
    size      name color protected
3    big      rose   red       yes
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue        no

هذا لأن pd.Series بشكل افتراضي يحتوي على فهرس تعداد من 0 إلى n. والباندا [] = الطريقة تحاول أن تكون "ذكية"

ما يحدث في الواقع.

عندما تستخدم الباندا [] = الطريقة ، تقوم بهدوء بالانضمام الخارجي أو الدمج الخارجي باستخدام فهرس مخطط اليد اليسرى وفهرس سلسلة اليد اليمنى. df['column'] = series

ملاحظة جانبية

هذا يتسبب بسرعة في التنافر المعرفي ، لأن الطريقة []= تحاول أن تفعل الكثير من الأشياء المختلفة اعتمادا على المدخلات ، والنتيجة لا يمكن التنبؤ بها إلا إذا كنت تعرف فقط كيف يعمل الباندا. لذلك أود تقديم المشورة ضد []= في قواعد الكود ، ولكن عند استكشاف البيانات في دفتر ملاحظات ، فلا بأس.

تدور حول المشكلة

إذا كان لديك pd.Series وتريد تعيينه من أعلى إلى أسفل ، أو إذا كنت ترميز رمز منتج وكنت غير متأكد من ترتيب الفهرس ، فإنه يستحق ذلك لحماية لهذا النوع من المشاكل.

يمكنك أن pd.Series إلى np.ndarray أو list ، وهذا سوف تفعل الخدعة.

df['protected'] = pd.Series(['no', 'no', 'no', 'yes']).values

أو

df['protected'] = list(pd.Series(['no', 'no', 'no', 'yes']))

لكن هذا ليس واضحًا تمامًا.

قد يأتي بعض المبرمج ويقول "مرحبًا ، يبدو هذا مكررًا ، سأحسّن ذلك بعيداً".

طريقة صريحة

تعيين فهرس pd.Series أن يكون فهرس df صريح.

df['protected'] = pd.Series(['no', 'no', 'no', 'yes'], index=df.index)

أو أكثر واقعية ، ربما لديك pd.Series متوفرة بالفعل.

protected_series = pd.Series(['no', 'no', 'no', 'yes'])
protected_series.index = df.index

3     no
2     no
1     no
0    yes

يمكن الآن تعيينها

df['protected'] = protected_series

    size      name color protected
3    big      rose   red        no
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue       yes

طريقة بديلة مع df.reset_index()

بما أن تنافر المؤشر هو المشكلة ، إذا شعرت أن مؤشر dataframe لا ينبغي أن يملي الأشياء ، يمكنك ببساطة إسقاط الفهرس ، وهذا يجب أن يكون أسرع ، ولكنه ليس نظيفًا جدًا ، لأن وظيفتك الآن على الأرجح تقوم بشيئين.

df.reset_index(drop=True)
protected_series.reset_index(drop=True)
df['protected'] = protected_series

    size      name color protected
0    big      rose   red        no
1  small    violet  blue        no
2  small     tulip   red        no
3  small  harebell  blue       yes

ملاحظة على df.assign

في حين أن df.assign يجعلها أكثر وضوحًا مما تقوم به ، إلا أنه في الواقع لديه نفس المشاكل المذكورة أعلاه []=

df.assign(protected=pd.Series(['no', 'no', 'no', 'yes']))
    size      name color protected
3    big      rose   red       yes
2  small    violet  blue        no
1  small     tulip   red        no
0  small  harebell  blue        no

فقط احترس من df.assign أن العمود الخاص بك لا يسمى self . سوف يسبب أخطاء. هذا يجعل df.assign رائحة كريهة ، لأن هناك هذا النوع من القطع الأثرية في هذه الوظيفة.

df.assign(self=pd.Series(['no', 'no', 'no', 'yes'])
TypeError: assign() got multiple values for keyword argument 'self'

قد تقول ، "حسنا ، أنا فقط لن تستخدم self بعد ذلك". ولكن من يدري كيف تتغير هذه الوظيفة في المستقبل لدعم الحجج الجديدة. ربما يكون اسم العمود الخاص بك وسيطة في تحديث جديد للباندا ، مما يتسبب في مشاكل في الترقية.


إذا حصلت على SettingWithCopyWarning ، فإن الحل السهل هو نسخ DataFrame الذي تحاول إضافة عمود إليه.

df = df.copy()
df['col_name'] = values

إذا كان العمود الذي تحاول إضافته هو متغير سلسلة ، فحينئذٍ فقط:

df["new_columns_name"]=series_variable_name #this will do it for you

يعمل هذا جيدًا حتى إذا كنت تستبدل عمودًا موجودًا.قم فقط بكتابة new_columns_name نفس العمود الذي تريد استبداله. وسيقوم فقط بالكتابة فوق بيانات الأعمدة الموجودة بسلسلة البيانات الجديدة.


إذا كنت ترغب في تعيين العمود الجديد بالكامل على قيمة أساسية أولية (مثل بلا) ، فيمكنك القيام بذلك: df1['e'] = None

هذا الواقع سيقوم بتعيين نوع "الكائن" إلى الخلية. في وقت لاحق ، يمكنك مطلقًا وضع أنواع بيانات معقدة ، مثل القائمة ، في خلايا فردية.


استخدم فهارس df1 الأصلية لإنشاء السلسلة:

df1['e'] = Series(np.random.randn(sLength), index=df1.index)

تحرير 2015
أفاد البعض بالحصول على SettingWithCopyWarning مع هذا الرمز.
ومع ذلك ، لا يزال يعمل رمز الكمال مع إصدار الباندا الحالية 0.16.1.

>>> sLength = len(df1['a'])
>>> df1
          a         b         c         d
6 -0.269221 -0.026476  0.997517  1.294385
8  0.917438  0.847941  0.034235 -0.448948

>>> df1['e'] = p.Series(np.random.randn(sLength), index=df1.index)
>>> df1
          a         b         c         d         e
6 -0.269221 -0.026476  0.997517  1.294385  1.757167
8  0.917438  0.847941  0.034235 -0.448948  2.228131

>>> p.version.short_version
'0.16.1'

يهدف SettingWithCopyWarning للإبلاغ عن مهمة ربما غير صالحة على نسخة من Dataframe. لا يعني ذلك بالضرورة أنك قمت بذلك بشكل خاطئ (يمكن أن يؤدي إلى نتائج إيجابية خاطئة) ولكن من 0.13.0 ، نعلمك بوجود أساليب أكثر ملاءمة للغرض نفسه. ثم ، إذا تلقيت التحذير ، فما عليك سوى اتباع نصيحة: جرِّب استخدام .loc [row_index، col_indexer] = value بدلاً من ذلك

>>> df1.loc[:,'f'] = p.Series(np.random.randn(sLength), index=df1.index)
>>> df1
          a         b         c         d         e         f
6 -0.269221 -0.026476  0.997517  1.294385  1.757167 -0.050927
8  0.917438  0.847941  0.034235 -0.448948  2.228131  0.006109
>>> 

في الواقع ، هذه هي الطريقة الأكثر فعالية حاليًا كما هو موضح في مستندات الباندا

تحرير عام 2017

كما هو موضح في التعليقات وAlexander ، فإن أفضل طريقة لإضافة قيم سلسلة كعمود جديد في DataFrame يمكن أن تستخدم حاليًا:

df1 = df1.assign(e=p.Series(np.random.randn(sLength)).values)

حصلت على SettingWithCopyWarning اللعين ، وأنها لم تكن ثابتة باستخدام بناء الجملة iloc. تم إنشاء My DataFrame بواسطة read_sql من مصدر ODBC. باستخدام اقتراح من قبل lowtech أعلاه ، عملت التالية بالنسبة لي:

df.insert(len(df.columns), 'e', pd.Series(np.random.randn(sLength),  index=df.index))

هذا عمل جيد لإدراج العمود في النهاية. لا أعرف ما إذا كان هذا هو الأكثر فعالية ، لكنني لا أحب رسائل التحذير. أعتقد أن هناك حلاً أفضل ، لكنني لا أستطيع العثور عليه ، وأعتقد أنه يعتمد على جانب معين من المؤشر.
ملاحظة . أن هذا يعمل مرة واحدة فقط وسوف يعطي رسالة خطأ في حالة محاولة الكتابة والعمود الموجود.
ملاحظة كما هو موضح أعلاه ومن 0.16.0 تعيين هو الحل الأفضل. راجع الوثائق http://pandas.pydata.org/pandas-docs/stable/generated/pandas.DataFrame.assign.html#pandas.DataFrame.assign تعمل جيدًا لنوع تدفق البيانات حيث لا تقوم بالكتابة فوق قيمك الوسيطة.


سيكون القيام بذلك مباشرة عبر NumPy هو الأكثر فعالية:

df1['e'] = np.random.randn(sLength)

ملاحظة كان اقتراحي الأصلي (قديم جداً) استخدام map (وهو أبطأ بكثير):

df1['e'] = df1['a'].map(lambda x: np.random.random())

قبل تعيين عمود جديد ، إذا كان لديك بيانات مفهرسة ، فستحتاج إلى فرز الفهرس. على الأقل في حالتي اضطررت إلى:

data.set_index(['index_column'], inplace=True)
"if index is unsorted, assignment of a new column will fail"        
data.sort_index(inplace = True)
data.loc['index_value1', 'column_y'] = np.random.randn(data.loc['index_value1', 'column_x'].shape[0])

كنت أبحث عن وسيلة عامة لإضافة عمود numpy.nan s إلى dataframe دون الحصول على SettingWithCopyWarning الغبية.

من التالي:

  • الإجابات هنا
  • هذا السؤال حول تمرير متغير كوسيطة الكلمة الرئيسية
  • هذه الطريقة لتوليد مجموعة numpy من NaNs في الخط

خطرت لي هذه:

col = 'column_name'
df = df.assign(**{col:numpy.full(len(df), numpy.nan)})

ما يلي هو ما فعلته ... ولكنني جديدة جدا لالباندا و python حقا بشكل عام ، لذلك لا وعود.

df = pd.DataFrame([[1, 2], [3, 4], [5,6]], columns=list('AB'))

newCol = [3,5,7]
newName = 'C'

values = np.insert(df.values,df.shape[1],newCol,axis=1)
header = df.columns.values.tolist()
header.append(newName)

df = pd.DataFrame(values,columns=header)

من أجل الاكتمال - حل آخر باستخدام طريقة DataFrame.eval() :

البيانات:

In [44]: e
Out[44]:
0    1.225506
1   -1.033944
2   -0.498953
3   -0.373332
4    0.615030
5   -0.622436
dtype: float64

In [45]: df1
Out[45]:
          a         b         c         d
0 -0.634222 -0.103264  0.745069  0.801288
4  0.782387 -0.090279  0.757662 -0.602408
5 -0.117456  2.124496  1.057301  0.765466
7  0.767532  0.104304 -0.586850  1.051297
8 -0.103272  0.958334  1.163092  1.182315
9 -0.616254  0.296678 -0.112027  0.679112

حل:

In [46]: df1.eval("e = @e.values", inplace=True)

In [47]: df1
Out[47]:
          a         b         c         d         e
0 -0.634222 -0.103264  0.745069  0.801288  1.225506
4  0.782387 -0.090279  0.757662 -0.602408 -1.033944
5 -0.117456  2.124496  1.057301  0.765466 -0.498953
7  0.767532  0.104304 -0.586850  1.051297 -0.373332
8 -0.103272  0.958334  1.163092  1.182315  0.615030
9 -0.616254  0.296678 -0.112027  0.679112 -0.622436

يبدو أنه في إصدارات Pandas الأخيرة ، فإن الطريقة التي يجب assign هي استخدام assign :

df1 = df1.assign(e=np.random.randn(sLength))

انها لا تنتج SettingWithCopyWarning.


مضمونة:

df.loc[:, 'NewCol'] = 'New_Val'

مثال:

df = pd.DataFrame(data=np.random.randn(20, 4), columns=['A', 'B', 'C', 'D'])

df

           A         B         C         D
0  -0.761269  0.477348  1.170614  0.752714
1   1.217250 -0.930860 -0.769324 -0.408642
2  -0.619679 -1.227659 -0.259135  1.700294
3  -0.147354  0.778707  0.479145  2.284143
4  -0.529529  0.000571  0.913779  1.395894
5   2.592400  0.637253  1.441096 -0.631468
6   0.757178  0.240012 -0.553820  1.177202
7  -0.986128 -1.313843  0.788589 -0.707836
8   0.606985 -2.232903 -1.358107 -2.855494
9  -0.692013  0.671866  1.179466 -1.180351
10 -1.093707 -0.530600  0.182926 -1.296494
11 -0.143273 -0.503199 -1.328728  0.610552
12 -0.923110 -1.365890 -1.366202 -1.185999
13 -2.026832  0.273593 -0.440426 -0.627423
14 -0.054503 -0.788866 -0.228088 -0.404783
15  0.955298 -1.430019  1.434071 -0.088215
16 -0.227946  0.047462  0.373573 -0.111675
17  1.627912  0.043611  1.743403 -0.012714
18  0.693458  0.144327  0.329500 -0.655045
19  0.104425  0.037412  0.450598 -0.923387


df.drop([3, 5, 8, 10, 18], inplace=True)

df

           A         B         C         D
0  -0.761269  0.477348  1.170614  0.752714
1   1.217250 -0.930860 -0.769324 -0.408642
2  -0.619679 -1.227659 -0.259135  1.700294
4  -0.529529  0.000571  0.913779  1.395894
6   0.757178  0.240012 -0.553820  1.177202
7  -0.986128 -1.313843  0.788589 -0.707836
9  -0.692013  0.671866  1.179466 -1.180351
11 -0.143273 -0.503199 -1.328728  0.610552
12 -0.923110 -1.365890 -1.366202 -1.185999
13 -2.026832  0.273593 -0.440426 -0.627423
14 -0.054503 -0.788866 -0.228088 -0.404783
15  0.955298 -1.430019  1.434071 -0.088215
16 -0.227946  0.047462  0.373573 -0.111675
17  1.627912  0.043611  1.743403 -0.012714
19  0.104425  0.037412  0.450598 -0.923387

df.loc[:, 'NewCol'] = 0

df
           A         B         C         D  NewCol
0  -0.761269  0.477348  1.170614  0.752714       0
1   1.217250 -0.930860 -0.769324 -0.408642       0
2  -0.619679 -1.227659 -0.259135  1.700294       0
4  -0.529529  0.000571  0.913779  1.395894       0
6   0.757178  0.240012 -0.553820  1.177202       0
7  -0.986128 -1.313843  0.788589 -0.707836       0
9  -0.692013  0.671866  1.179466 -1.180351       0
11 -0.143273 -0.503199 -1.328728  0.610552       0
12 -0.923110 -1.365890 -1.366202 -1.185999       0
13 -2.026832  0.273593 -0.440426 -0.627423       0
14 -0.054503 -0.788866 -0.228088 -0.404783       0
15  0.955298 -1.430019  1.434071 -0.088215       0
16 -0.227946  0.047462  0.373573 -0.111675       0
17  1.627912  0.043611  1.743403 -0.012714       0
19  0.104425  0.037412  0.450598 -0.923387       0






chained-assignment