मेरे पास इस तरह एक डेटाफ्रेम है:

 index   customerID    item_tag   orderID    Amount
   0         23            A         1        34.50
   1         55            B         2        11.22
   2         23            A         3         9.34
   3         55            D         4       123.44
   4         55            F         5       231.40

मेरे पास इस तरह की item_tags वाली एक सूची भी है:

my_list = ['A', 'B', 'D']

अब मैं यह जांचना चाहता हूं कि प्रत्येक ग्राहक द्वारा my_list से कितने प्रकार के आइटम ऑर्डर किए गए थे। उदाहरण के लिए, ग्राहक २३ के लिए यह संख्या = १ होगी, क्योंकि ग्राहक २३ ऑर्डर केवल ए के रूप में टैग की गई वस्तु है, लेकिन बी नहीं और न ही डी। ग्राहक 55, हालांकि, आइटम बी और डी का आदेश दिया, इसलिए यह संकेतक चर 2 होगा, क्योंकि उसके ऑर्डर में my_list से दो आइटम प्रकार मौजूद हैं। (उसने आइटम F का भी आदेश दिया, लेकिन यह आइटम my_list में नहीं है)।

अब तक मैंने groupby([customerId, item_tag], as_index = False).count() की कोशिश की, लेकिन इसके लिए नया डेटाफ्रेम बनाने की आवश्यकता है (शायद जरूरी नहीं?) हालांकि मुझे कोई नहीं मिला, न तो Google में और न ही यहां। मेरे डेटाफ़्रेम में लाखों पंक्तियाँ हैं इसलिए मैं सबसे कुशल समाधान की तलाश में हूँ।

नतीजतन, मुझे इस तरह डेटाफ्रेम चाहिए:

 index   customerID   if_A  if_B  if_D  sum_in_list
   0         23         1     0    0        1
   1         55         0     1    1        2
1
Bonzogondo 24 जून 2018, 00:29

3 जवाब

सबसे बढ़िया उत्तर

get_dummies + groupby का उपयोग करने का एक तरीका यहां दिया गया है, आपको निःशुल्क गणनाएं मिलती हैं:

res = pd.get_dummies(df[['customerID', 'item_tag']], columns=['item_tag'])\
        .groupby(['customerID'], as_index=False).sum()

print(res)

   customerID  item_tag_A  item_tag_B  item_tag_D  item_tag_F
0          23           2           0           0           0
1          55           0           1           1           1

यदि आप बाइनरी परिणाम चाहते हैं और विशिष्ट टैग तक सीमित हैं तो कुछ अतिरिक्त चरण हैं:

L = ['A', 'B', 'D']

df_filtered = df.loc[df['item_tag'].isin(L), ['customerID', 'item_tag']] 

res = pd.get_dummies(df_filtered, columns=['item_tag'])\
        .groupby(['customerID']).any().astype(int).reset_index()

res['total_count'] = res.iloc[:, 1:].sum(axis=1)

print(res)

   customerID  item_tag_A  item_tag_B  item_tag_D  total_count
0          23           1           0           0            1
1          55           0           1           1            2
2
jpp 24 जून 2018, 00:41

यह एक फ़िल्टर किया गया क्रॉस टेबुलेशन है और हम उत्तर के तहत उन्हें यहां करने के लिए कई विकल्प देख सकते हैं। प्रश्न #9

crosstab और clip_upper का उपयोग करें

pd.crosstab(df.customerID, df.item_tag).clip_upper()[my_list]

item_tag    A  B  D
customerID         
23          1  0  0
55          0  1  1

इनलाइन रखने के लिए lambda का उपयोग करते समय योग प्राप्त करने के लिए assign जोड़ें

pd.crosstab(df.customerID, df.item_tag).clip_upper(1)[my_list].assign(
    Total=lambda d: d.sum(1))

item_tag    A  B  D  Total
customerID                
23          1  0  0      1
55          0  1  1      2

pandas.Series

एक नई श्रृंखला वस्तु के निर्माण के साथ दिलचस्प विकल्प। मैं इसे इस तरह से बनाता हूं जैसे कि item_tag को एक मल्टीइंडेक्स के पहले स्तर में रखने के लिए loc का उपयोग करना सुविधाजनक हो जाता है और उन टैग्स को काट देता है जिनकी मुझे परवाह है।

s = pd.Series(1, set(zip(df.item_tag, df.customerID)))
s.loc[my_list].unstack(0, fill_value=0).assign(
    Total=lambda d: d.sum(1))

    A  B  D  Total
23  1  0  0      1
55  0  1  1      2
2
piRSquared 24 जून 2018, 07:51

मेरा समाधान अवांछित उत्पादों को फ़िल्टर करता है और फिर समूहीकरण करता है:

wanted = df[df['item_tag'].isin(my_list)]
wanted.groupby(['customerID', 'item_tag'])\
      .count().unstack()['Amount'].fillna(0).astype(int)

#item_tag    A  B  D
#customerID         
#23          2  0  0
#55          0  1  1
2
DYZ 24 जून 2018, 00:41