পান্ডস: প্রাক-বিদ্যমান কলাম থেকে গণনা করা মানগুলি সহ একটি ডেটাফ্রেমে দুটি নতুন কলাম তৈরি করুন


100

আমি পান্ডাস লাইব্রেরির সাথে কাজ করছি এবং আমি dfএন কলামগুলির সাথে একটি ডেফ্রেমে দুটি নতুন কলাম যুক্ত করতে চাই (n> 0)।
এই নতুন কলামগুলির ফলাফল ফাংশনের প্রয়োগ থেকে ডেটাফ্রেমের কলামগুলির মধ্যে একটিতে আসে।

প্রয়োগ করার ফাংশনটি হ'ল:

def calculate(x):
    ...operate...
    return z, y

শুধুমাত্র একটি মান প্রদান করে ফাংশনটির জন্য একটি নতুন কলাম তৈরির জন্য একটি পদ্ধতি:

df['new_col']) = df['column_A'].map(a_function)

সুতরাং, আমি যা চাই এবং (*) ব্যর্থ চেষ্টা করেছি তা হ'ল:

(df['new_col_zetas'], df['new_col_ys']) = df['column_A'].map(calculate)

এটি সম্পাদন করার সর্বোত্তম উপায় কী হতে পারে? আমি কোনও ক্লু ছাড়াই ডকুমেন্টেশন স্ক্যান করেছি ।

** df['column_A'].map(calculate)টিপল জেড, ওয়াই সমন্বিত প্রতিটি আইটেম একটি পান্ডাস সিরিজ প্রদান করে। এবং এটি দুটি ডেটাফ্রেম কলামগুলিতে নির্ধারিত করার চেষ্টা করে একটি ভ্যালুআরআর produces

উত্তর:


119

আমি কেবল ব্যবহার করব zip:

In [1]: from pandas import *

In [2]: def calculate(x):
   ...:     return x*2, x*3
   ...: 

In [3]: df = DataFrame({'a': [1,2,3], 'b': [2,3,4]})

In [4]: df
Out[4]: 
   a  b
0  1  2
1  2  3
2  3  4

In [5]: df["A1"], df["A2"] = zip(*df["a"].map(calculate))

In [6]: df
Out[6]: 
   a  b  A1  A2
0  1  2   2   3
1  2  3   4   6
2  3  4   6   9

ধন্যবাদ, দুর্দান্ত, এটি কাজ করে। ০.৮.১-এর জন্য ডক্সে আমি এর মতো কিছুই পাইনি ... আমি মনে করি আমার সবসময় টিউপসগুলির তালিকা হিসাবে সিরিজে চিন্তা করা উচিত ...
joaquin

পরিবর্তে এটি করার ক্ষেত্রে কি কোনও পার্থক্য রয়েছে? জিপ (* ডিএফ ["এ"] এর পরিবর্তে জিপ (* মানচিত্র (গণনা, ডিএফ ["এ"]))। মানচিত্র (গণনা)), যা (উপরে হিসাবেও) দেয় ([2, 4, 6), ( 3, 6, 9)]?
একতা

4
নতুন কলাম তৈরি করার সময় আমি নিম্নলিখিত সতর্কতা পেয়েছি: "সেটিং উইথকপি ওয়ার্নিং: একটি ডেটা ফ্রেমের একটি স্লাইসের অনুলিপিটিতে একটি মান সেট করার চেষ্টা করা হচ্ছে। আমার কি উদ্বিগ্ন হওয়া উচিত? পান্ডাস v.0.15
তারা

47

শীর্ষের উত্তরটি আমার মতে ত্রুটিযুক্ত। আশা করা যায়, কেউই তাদের নামস্থানে সমস্ত পান্ডা ভর করে আমদানি করছে না from pandas import *। এছাড়াও, mapকোনও অভিধান বা সিরিজ পাস করার সময় পদ্ধতিটি সেই সময়ের জন্য সংরক্ষণ করা উচিত। এটি কোনও ফাংশন নিতে পারে তবে এটিই এর applyজন্য ব্যবহৃত হয়।

সুতরাং, আপনি যদি উপরের পদ্ধতির অবশ্যই ব্যবহার করেন তবে আমি এটি এটি লিখতে চাই

df["A1"], df["A2"] = zip(*df["a"].apply(calculate))

এখানে জিপ ব্যবহার করার আসলে কোনও কারণ নেই। আপনি কেবল এটি করতে পারেন:

df["A1"], df["A2"] = calculate(df['a'])

বৃহত্তর ডেটাফ্রেমে এই দ্বিতীয় পদ্ধতিটি আরও দ্রুত

df = pd.DataFrame({'a': [1,2,3] * 100000, 'b': [2,3,4] * 100000})

300,000 সারি দিয়ে ডেটাফ্রেম তৈরি করা হয়েছে

%timeit df["A1"], df["A2"] = calculate(df['a'])
2.65 ms ± 92.4 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit df["A1"], df["A2"] = zip(*df["a"].apply(calculate))
159 ms ± 5.24 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

জিপের চেয়ে 60x দ্রুত faster


সাধারণভাবে, প্রয়োগ ব্যবহার এড়িয়ে চলুন

পাইথন তালিকার উপরে পুনরাবৃত্তি করার চেয়ে প্রয়োগ সাধারণত খুব দ্রুত হয় না। উপরের মতো একই জিনিসটি করার জন্য ফর-লুপের পারফরম্যান্সটি পরীক্ষা করা যাক

%%timeit
A1, A2 = [], []
for val in df['a']:
    A1.append(val**2)
    A2.append(val**3)

df['A1'] = A1
df['A2'] = A2

298 ms ± 7.14 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

সুতরাং এটি দ্বিগুণ ধীর যা কোনও ভয়াবহ পারফরম্যান্স রিগ্রেশন নয়, তবে আমরা যদি উপরের দিকে সংযুক্ত হয়ে থাকি তবে আমরা আরও ভাল পারফরম্যান্স পাই। ধরে নিচ্ছি, আপনি আইপথন ব্যবহার করছেন:

%load_ext cython

%%cython
cpdef power(vals):
    A1, A2 = [], []
    cdef double val
    for val in vals:
        A1.append(val**2)
        A2.append(val**3)

    return A1, A2

%timeit df['A1'], df['A2'] = power(df['a'])
72.7 ms ± 2.16 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

সরাসরি প্রয়োগ ছাড়াই বরাদ্দ করা

আপনি যদি সরাসরি ভেক্টরাইজড ক্রিয়াকলাপগুলি ব্যবহার করেন তবে আপনি আরও বেশি গতির উন্নতি পেতে পারেন।

%timeit df['A1'], df['A2'] = df['a'] ** 2, df['a'] ** 3
5.13 ms ± 320 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

এটি আমাদের লুপগুলির পরিবর্তে নুমপির অত্যন্ত দ্রুত ভেক্টরাইজড অপারেশনের সুবিধা গ্রহণ করে। মূলটির তুলনায় আমাদের এখন 30x স্পিডআপ রয়েছে।


সঙ্গে সহজ গতি পরীক্ষা apply

উপরের উদাহরণটি পরিষ্কারভাবে দেখানো উচিত যে ধীরে ধীরে কী applyহতে পারে তবে এর অতিরিক্ত স্পষ্টভাবে আসল সর্বাধিক প্রাথমিক উদাহরণটি দেখি। প্রয়োগ এবং ছাড়াই 10 মিলিয়ন সংখ্যার একটি সিরিজ বর্গ করা যাক

s = pd.Series(np.random.rand(10000000))

%timeit s.apply(calc)
3.3 s ± 57.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

প্রয়োগ ছাড়াই 50x দ্রুত হয়

%timeit s ** 2
66 ms ± 2 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

4
এটি সত্যিই দুর্দান্ত উত্তর। আমি জিজ্ঞাসা করতে চেয়েছিলাম: আপনি applymapযখন ডেটাফ্রেমের প্রতিটি উপাদানকে একটি নির্দিষ্ট ফাংশন বাস্তবায়ন করতে চান তখন আপনি মামলার বিষয়ে কী ভাবেন?
ডেভিড

4
যদিও এই উত্তরে কিছু ভাল পরামর্শ রয়েছে, আমি বিশ্বাস করি যে func(series)পরিবর্তে ব্যবহারের মূল পরামর্শটি series.apply(func)কেবল তখনই প্রযোজ্য যখন ফানক সম্পূর্ণরূপে সংজ্ঞায়িত হয় এমন ক্রিয়াকলাপগুলি ব্যবহার করে যা পৃথক মান এবং সিরিজ উভয় ক্ষেত্রে একই রকম আচরণ করে। প্রথম উত্তরে উদাহরণের ক্ষেত্রে এটি একই রকম, তবে এটি ওপি-র প্রশ্নের ক্ষেত্রে নয়, যা কলামগুলিতে ফাংশন প্রয়োগের বিষয়ে আরও সাধারণভাবে জিজ্ঞাসা করছে। 1/2
গ্রাহাম লি

4
উদাহরণস্বরূপ, যদি df প্রয়োগ হল: DataFrame({'a': ['Aaron', 'Bert', 'Christopher'], 'b': ['Bold', 'Courageous', 'Distrusted']})এবং calcহল: def calc(x): return x[0], len(x)তারপর tdf.a.apply(calc))calc(tdf.a)খুব ভিন্ন জিনিস ফিরে যান।
গ্রাহাম লেয়া
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.