اذهب إلى المحتوى
  • 0

تطبيق دالة على عمودين فقط من dataframe في pandas

Mohamed Elnemr

السؤال

أود عمل دالة بحيث يتم تطبيقها فقط على عمودين معينين من ال dataframes، حاولت عمل الكود التالي:

df['col3'] = df[['col1','col2']].apply(f)  

لكنه يظهر الخطأ التالي:

 TypeError: ('<lambda>() takes exactly 2 arguments (1 given)'

كيف يمكنني فعل هذا؟

رابط هذا التعليق
شارك على الشبكات الإجتماعية

Recommended Posts

  • 0

يمكنك استخدام الدالة apply لتطبيق أي دالة تريدها على الأعمدة التي تريد حيث نقوم بوضع axis=1 لاختيار الأعمدة بينما نضع axis=0 اذا اردنا اختيار صفوف بعينها، أنظر المثال التالي:

In [1]: df
Out[1]: 
          0         1
0  1.000000  0.000000
1 -0.494375  0.570994
2  1.000000  0.000000
3  1.876360 -0.229738
4  1.000000  0.000000

In [2]: def f(x):    
   		  return x[0] + x[1]  
     

In [3]: df.apply(f, axis=1) 
Out[3]: 
0    1.000000
1    0.076619
2    1.000000
3    1.646622
4    1.000000

أو يمكنك استخدام الكود التالي بتحديد أسماء الأعمدة التى تريدها:

df['col3'] = df.apply(lambda x: f(x.col1, x.col2), axis=1)

الكود التالي يوضح كيف تستخدم هذة الطريقة بعد تعريف دالة معينة:

import pandas as pd

df = pd.DataFrame({'ID':['1', '2', '3'], 'col1': [0, 1, 2], 'col2':[3, 4, 5]})
mylist = ['a', 'b', 'c', 'd', 'e', 'f']

def get_sublist(sta,end):
    return mylist[sta:end+1]

df['col3'] = df.apply(lambda x: get_sublist(x.col1, x.col2), axis=1)

ويكون الناتج كالتالي:

  ID     col1   col2    col_3
0  1      0      3    [a, b, c, d]
1  2      1      4   [b, c, d, e]
2  3      2      5   [c, d, e, f]

ويمكنك تحديد اسماء الأعمدة التي تريد لتطبيق الدالة عليهم مهما كان عددهم.

رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

كما أشار أحمد يمكنك استخدام Apply لكن أنصح دوماً بالاعتماد على طرق أخرى لأن هذه الطرق بطيئة، لذا يمكن أن نقوم بالأمر من خلال الدالة vectorize  التي ستعطيك فرق كبير للغاية بالسرعة كالتالي:

import pandas as pd
# تعرف داتا فريم لنختبر عليه
df = pd.DataFrame({'ID':['1', '2', '3'], 'col1': [0, 1, 2], 'col2':[3, 4, 5]})
df
"""
 	ID 	col1 	col2
0 	1 	0 	3
1 	2 	1 	4
2 	3 	2 	5
"""
# نعرف تابع لنختبر عليه
def f(x,y):    
  return x+y
import numpy as np
# نقوم بتطبيق التابع على عمودي البيانات
df.loc[:,'result'] = np.vectorize(f) (df['col1'], df['col2'])
df
"""
	ID 	col1 	  col2 	 	result
0 	1 	0 			3 	 	3
1 	2 	1 			4 	 	5
2 	3 	2 			5 	 	7
"""

كذلك كان بإمكانك استخدام الدالة apply:

df['col_3'] = df.apply(lambda x: f(x.col1, x.col2), axis=1)
df
"""
    ID 	col1 	col2 	col_3
0 	1 	0 			3 	  3
1 	2 	1 			4     5
2 	3 	2 			5     7
"""

وكتحسين لسرعة التنفيذ باستخدام apply يمكنك استخدام الأداة swifter:

import swifter
df['col_3'] = df.swifter.apply(lambda x: f(x.col1, x.col2), axis=1)

للمقارنة:

# توليد داتافريم بحجم كبير
df1 = df.sample(100000, replace=True).reset_index(drop=True)
# تطبيق نفس العملية واستخلاص زمن التنفيذ
%timeit df1.apply(lambda x: f(x.col1, x.col2), axis=1)
# 1 loop, best of 5: 1.84 s per loop
%timeit df1.swifter.apply(lambda x: f(x.col1, x.col2), axis=1)
# 100 loops, best of 5: 2.24 ms per loop
%timeit np.vectorize(f) (df['col1'], df['col2'])
# 10000 loops, best of 5: 62.7 µs per loop

لاحظ أن apply استغرقت ثانيتين تقريباً وع التحسين swifter  استغرقت 2 ونصف ميلي ثانية، لكن باستخدام vectorize استغرقت 62 ميكرو ثانية وهو فرق هائل. وهنا نتحدث عن عمليات بسيطة جداً هناك عمليات قد يتطلب تنفيذها وقت يتجاوز النصف ساعة والساعة حتى تنتهي لو استخدمنا Apply. لذا إذا كنت تفكر بالتعامل مع بيانات ضخمة ابتعد عنها.

تم التعديل في بواسطة Ali Haidar Ahmad
رابط هذا التعليق
شارك على الشبكات الإجتماعية

  • 0

يمكنك أيضاً استخدام ال loop لتنفيذ المطلوب وهذه الطريقة هي أسرع من استخدام apply مع axis 1 كما في المثال التالي

import pandas as pd

df = pd.DataFrame({'ID':['1','2','3'], 'col_1': [0,2,3], 'col_2':[1,4,5]})
mylist = ['a','b','c','d','e','f']

def get_sublist(sta,end):
    return mylist[sta:end+1]

df['col_3'] = list(map(get_sublist,df['col_1'],df['col_2']))

ملاحظة 

في الإصدار Python 2 لا تحتاج لاستخدام ال list للتحويل

رابط هذا التعليق
شارك على الشبكات الإجتماعية

انضم إلى النقاش

يمكنك أن تنشر الآن وتسجل لاحقًا. إذا كان لديك حساب، فسجل الدخول الآن لتنشر باسم حسابك.

زائر
أجب على هذا السؤال...

×   لقد أضفت محتوى بخط أو تنسيق مختلف.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   جرى استعادة المحتوى السابق..   امسح المحرر

×   You cannot paste images directly. Upload or insert images from URL.

  • إعلانات

  • تابعنا على



×
×
  • أضف...