পান্ডাস গ্রুপবাই: স্ট্রিংগুলির ইউনিয়ন কীভাবে পাবেন


122

আমার কাছে এই জাতীয় ডেটাফ্রেম রয়েছে:

   A         B       C
0  1  0.749065    This
1  2  0.301084      is
2  3  0.463468       a
3  4  0.643961  random
4  1  0.866521  string
5  2  0.120737       !

কল করা হচ্ছে

In [10]: print df.groupby("A")["B"].sum()

ফিরে আসবে

A
1    1.615586
2    0.421821
3    0.463468
4    0.643961

এখন আমি কলাম "সি" এর জন্য "একই" করতে চাই। যেহেতু সেই কলামটিতে স্ট্রিং রয়েছে, যোগফল () কাজ করে না (যদিও আপনি মনে করতে পারেন যে এটি স্ট্রিংগুলি একত্রিত করবে)। আমি যা দেখতে চাই তা হ'ল প্রতিটি গ্রুপের স্ট্রিংগুলির তালিকা বা সেট set

A
1    {This, string}
2    {is, !}
3    {a}
4    {random}

আমি এটি করার উপায়গুলি চেষ্টা করার চেষ্টা করছি।

সিরিজ.উনিক () ( http://pandas.pydata.org/pandas-docs/stable/generated/pandas.Series.unique.html ) কাজ করে না, যদিও

df.groupby("A")["B"]

ইহা একটি

pandas.core.groupby.SeriesGroupBy object

সুতরাং আমি আশা করছিলাম যে কোনও সিরিজ পদ্ধতি কাজ করবে। কোন ধারনা?

উত্তর:


178
In [4]: df = read_csv(StringIO(data),sep='\s+')

In [5]: df
Out[5]: 
   A         B       C
0  1  0.749065    This
1  2  0.301084      is
2  3  0.463468       a
3  4  0.643961  random
4  1  0.866521  string
5  2  0.120737       !

In [6]: df.dtypes
Out[6]: 
A      int64
B    float64
C     object
dtype: object

আপনি যখন নিজের ফাংশনটি প্রয়োগ করেন, অ-সংখ্যাযুক্ত কলামগুলির স্বয়ংক্রিয় বাদ নেই। এই ধীর, যদিও হয়, প্রয়োগ চেয়ে .sum()থেকেgroupby

In [8]: df.groupby('A').apply(lambda x: x.sum())
Out[8]: 
   A         B           C
A                         
1  2  1.615586  Thisstring
2  4  0.421821         is!
3  3  0.463468           a
4  4  0.643961      random

sum ডিফল্ট অনুসারে

In [9]: df.groupby('A')['C'].apply(lambda x: x.sum())
Out[9]: 
A
1    Thisstring
2           is!
3             a
4        random
dtype: object

আপনি যা চান তা বেশ কিছু করতে পারেন

In [11]: df.groupby('A')['C'].apply(lambda x: "{%s}" % ', '.join(x))
Out[11]: 
A
1    {This, string}
2           {is, !}
3               {a}
4          {random}
dtype: object

পুরো ফ্রেমে এটি করা, একবারে একটি গ্রুপ। কীটি ফেরত দেওয়া হয়Series

def f(x):
     return Series(dict(A = x['A'].sum(), 
                        B = x['B'].sum(), 
                        C = "{%s}" % ', '.join(x['C'])))

In [14]: df.groupby('A').apply(f)
Out[14]: 
   A         B               C
A                             
1  2  1.615586  {This, string}
2  4  0.421821         {is, !}
3  3  0.463468             {a}
4  4  0.643961        {random}

দেখে মনে হচ্ছে এই অপারেশনগুলি এখন প্রয়োজন applyএবং lambdaএর অপসারণকে ভেক্টরাইজ করা হয়েছে। আমি এখানে এসে ভাবছি কেন pandasআসলে সংক্ষেপ করে এবং স্ট্রিংয়ের সংমিশ্রণে কোনও ত্রুটি ফিরিয়ে দেয় না।
নেলসনগন

1
আপনি যদি স্ট্রিংগুলি সংঘবদ্ধ করার এবং এর মধ্যে একটি চরিত্র যুক্ত করার চেষ্টা করছেন তবে নীচে @Vithos দ্বারা প্রস্তাবিত .agg সমাধানটি এখানে প্রয়োগ করা সুপারিশের চেয়ে অনেক দ্রুত। আমার পরীক্ষায় আমি 5-10x দ্রুত পাচ্ছিলাম।
ডাবলডাউন

70

আপনি applyগোষ্ঠীযুক্ত ডেটাতে একটি স্বেচ্ছাসেবী ফাংশন প্রয়োগ করতে পদ্ধতিটি ব্যবহার করতে পারেন । সুতরাং আপনি যদি একটি সেট চান, আবেদন করুন set। আপনি যদি একটি তালিকা চান, আবেদন করুন list

>>> d
   A       B
0  1    This
1  2      is
2  3       a
3  4  random
4  1  string
5  2       !
>>> d.groupby('A')['B'].apply(list)
A
1    [This, string]
2           [is, !]
3               [a]
4          [random]
dtype: object

আপনি যদি অন্য কিছু চান, কেবল একটি ফাংশন লিখুন যা আপনি যা চান তা করে এবং তারপরে applyএটি।


ভাল কাজ করছে, কিন্তু কলাম কমেছে।
ভিনিশ টিপি

@ ভিনিশটিপি: কলাম এ একটি গ্রুপিং কলাম হিসাবে ব্যবহৃত হয়েছিল, সুতরাং এটি সূচীতে রয়েছে, যেমন আপনি উদাহরণে দেখতে পারেন। আপনি এটি ব্যবহার করে কলাম হিসাবে এটি ফিরিয়ে আনতে পারেন .reset_index()
ব্রেইনবারন

30

আপনি মানগুলিকে একত্রিত করতে aggregate(বা agg) ফাংশনটি ব্যবহার করতে সক্ষম হতে পারেন । (স্বাক্ষরিত কোড)

df.groupby('A')['B'].agg(lambda col: ''.join(col))

এটা সত্যিই কাজ করেছে. অ্যামেজিং। @ অভিটোস যেমন "অরক্ষিত" হিসাবে উল্লেখ করেছেন, আমি খুব আশাবাদী ছিলাম না। বিট আমি একটি সংস্করণ অভিধানে এন্ট্রি হিসাবে তার সংস্করণটি পরীক্ষা করেছিলাম এবং এটি উদ্দেশ্য হিসাবে কাজ করেছে: .agg ({'tp': 'যোগফল', 'বেসওয়াজিট': 'সর্বোচ্চ', 'টিপি_শোর্ট': ল্যাম্বদা কল: ',' .জাইন (কল) my) আমার দিনটি তৈরি করেছে
মঠিয়াস

2
যদি আপনি কোনও ধরণের বিভাজকের সাথে একসাথে স্ট্রিংগুলি সংঘবদ্ধ করার চেষ্টা করে থাকেন তবে আমি। অ্যাপ্লিকেশন এর চেয়ে অনেক দ্রুত হতে এই .agg পরামর্শটি পেয়েছি found 600k + পাঠ্য স্ট্রিংয়ের ডেটাসেটের জন্য, আমি অভিন্ন ফলাফল 5-10x দ্রুত পেয়েছি।
ডাবলডাউন

14

আপনি এটি চেষ্টা করতে পারেন:

df.groupby('A').agg({'B':'sum','C':'-'.join})

2
পর্যালোচনা থেকে: আপনি আপনার উত্তর আরও ব্যাখ্যা যোগ করতে পারেন?
toti08

1
গ্রুপবি 'এ' কলামে প্রয়োগ করা হয় এবং আগ্রাসী ফাংশন সহ আমি বিভিন্ন কলামগুলিতে বিভিন্ন ফাংশন ব্যবহার করতে পারি বলি কলাম 'সি'তে উপাদানগুলি যোগ করতে পারি, কলাম' সি 'তে উপাদানগুলি যুক্ত করতে পারি
user3241146

8

একটি সহজ সমাধান হবে:

>>> df.groupby(['A','B']).c.unique().reset_index()

এটি সঠিক উত্তর হওয়া উচিত। আপনি পরিষ্কার উত্তর দিন। অনেক ধন্যবাদ!
imsrgadich

যদি কেউ তালিকার বিষয়বস্তুগুলিকে একটি স্ট্রিংয়ে যোগ দিতে আগ্রহী হয় df.groupby(['A','B']).c.unique().apply(lambda x: ';'.join(x)).reset_index()
বিবেক-অনন্ত

8

এর সাথে নামকরণ করা সমষ্টি pandas >= 0.25.0

পান্ডাস সংস্করণ 0.25.0 সাল থেকে আমরা সমষ্টিগুলির নামকরণ করেছি যেখানে আমরা গ্রুপবদ্ধ করতে পারি, একইসাথে এবং একই সাথে আমাদের কলামগুলিতে নতুন নাম নির্ধারণ করতে পারি। এইভাবে আমরা মাল্টিআইডেক্স কলামগুলি পাব না এবং কলামের নামগুলি এতে থাকা ডেটা দিয়ে আরও অর্থবোধ করে:


একত্রিত করুন এবং স্ট্রিংগুলির একটি তালিকা পান

grp = df.groupby('A').agg(B_sum=('B','sum'),
                          C=('C', list)).reset_index()

print(grp)
   A     B_sum               C
0  1  1.615586  [This, string]
1  2  0.421821         [is, !]
2  3  0.463468             [a]
3  4  0.643961        [random]

সামগ্রিক এবং স্ট্রিং যোগ দিন

grp = df.groupby('A').agg(B_sum=('B','sum'),
                          C=('C', ', '.join)).reset_index()

print(grp)
   A     B_sum             C
0  1  1.615586  This, string
1  2  0.421821         is, !
2  3  0.463468             a
3  4  0.643961        random

6

আপনি যদি ডেটাফ্রেমে কলাম বিটি ওভাররাইট করতে চান তবে এটি কাজ করা উচিত:

    df = df.groupby('A',as_index=False).agg(lambda x:'\n'.join(x))

2

@ ইরফানের ভাল উত্তর অনুসরণ করে, বেশিরভাগ সময় সামগ্রিক মানগুলির বিশ্লেষণে আপনি এই বিদ্যমান চরিত্রের মানগুলির অনন্য সম্ভাব্য সংমিশ্রণ চান:

unique_chars = lambda x: ', '.join(x.unique())
(df
 .groupby(['A'])
 .agg({'C': unique_chars}))
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.