2013-02-21 16 views
5

में विशिष्ट कॉलम से जोड़ी के अंतर की गणना करें मेरे पास निम्न डेटाफ्रेम है जहां मैं दिखाता हूं कि मैंने आइटम 1 से आइटम 2 में कितनी बार देखा है। उदाहरण के लिए ए से बी, 2 से ए से सी में एक संक्रमण है , 1 सी से करने के लिए एकडेटाफ्रेम


Item1 Item2 Moves 
    1 A  B  1 
    2 A  C  2 
    3 B  D  3 
    4 C  A  1 
    5 C  B  5 
    6 D  B  4 
    7 D  C  1 

मैं दो आइटम के बीच अंतर की गणना करने के, तो एक नवनिर्मित Dataframe निम्नलिखित

Item1 Item2 Moves 
    1 A  B  1 
    2 A  C  1 
    3 B  D  -1 
    4 C  B  5 
    5 D  C  1 
012 होगा चाहते हैं

क्या किसी को भी पांडस का उपयोग करके ऐसा करने का कोई विचार है? मुझे लगता है कि मुझे पहले दो कॉलम पर इंडेक्स करने की ज़रूरत है, लेकिन मैं पांडस में काफी नया हूं और मुझे कई कठिनाइयों का सामना करना पड़ता है। धन्यवाद

संपादित वहाँ किसी भी डुप्लिकेट उदाहरण pairs.For आप दो बार A-> ख नहीं कर सकते देखने के नहीं किया जा सकता (लेकिन आप निश्चित रूप से कर सकते हैं देखने के बी> एक)

+0

क्या आपके लिए यह महत्वपूर्ण है कि पहले देखा गया संक्रमण दिशा संरक्षित है, या 'बी सी -5' के साथ एक पंक्ति स्वीकार्य होगी? – DSM

+0

यह महत्वपूर्ण नहीं है, लेकिन मुझे लगता है कि यह दो संक्रमणों या दूसरे के पहले मुठभेड़ को हटाने की प्राथमिकता का विषय है। – BigScratch

उत्तर

3

मुझे यकीन है कि कोई इसे कम लाइनों तक सरल बना सकता है, लेकिन मैंने इसे स्पष्ट करने में सहायता के लिए लंबे समय तक छोड़ा है कि क्या हो रहा है। संक्षेप में, 'item1' पहले 'आइटम 2' की तुलना में वर्णमाला में है या नहीं, इस आधार पर डेटा फ्रेम को दो टुकड़ों में विभाजित करें। फिर 'आइटम 1' और 'आइटम 2' फ्लिप करें और एक टुकड़े के लिए 'मूव' को अस्वीकार करें। उन्हें एक साथ वापस गोंद करें और पंक्तियों को एकत्रित करने के लिए groupby फ़ंक्शन का उपयोग करें।

>>> df 
    Item1 Item2 Moves 
0  A  B  1 
1  A  C  2 
2  B  D  3 
3  C  A  1 
4  C  B  5 
5  D  B  4 
6  D  C  1 
>>> swapidx = df['Item1'] < df['Item2'] 
>>> df1 = df[swapidx] 
>>> df2 = df[swapidx^True] 
>>> df1 
    Item1 Item2 Moves 
0  A  B  1 
1  A  C  2 
2  B  D  3 
>>> df2 
    Item1 Item2 Moves 
3  C  A  1 
4  C  B  5 
5  D  B  4 
6  D  C  1 
>>> df2[['Item1', 'Item2']] = df2[['Item2', 'Item1']] 
>>> df2['Moves'] = df2['Moves']*-1 
>>> df2 
    Item1 Item2 Moves 
3  A  C  -1 
4  B  C  -5 
5  B  D  -4 
6  C  D  -1 
>>> df3 = df1.append(df2) 
>>> df3.groupby(['Item1', 'Item2'], as_index=False).sum() 
    Item1 Item2 Moves 
0  A  B  1 
1  A  C  1 
2  B  C  -5 
3  B  D  -1 
4  C  D  -1 
+0

धन्यवाद! यह जवाब मेरे लिए काफी सुरुचिपूर्ण लगता है- मैंने सूचियों का उपयोग करके ऐसा करने में कामयाब रहा था, लेकिन मैं प्रत्येक जोड़ी के लिए विपरीत जोड़ी ढूंढने के लिए शब्दकोश के माध्यम से लूपिंग कर रहा था, जो काफी अक्षम है – BigScratch

+0

आपका सुझाया गया संपादन एक अच्छा था। मुझे यकीन नहीं है कि इसे दूसरों द्वारा क्यों खारिज कर दिया गया है, लेकिन 3 लोगों द्वारा खारिज किए जाने के बाद मैं इसे स्वीकार करने में असमर्थ था। मैंने संपादन किया है। –

1

यहाँ एक तरीका यह करना है:

पहले एक पंक्ति बनाएं जिसमें केवल आइटम 1 और आइटम 2 के लिए स्ट्रिंग शामिल है।

In [11]: df['Items'] = df.apply(lambda row: row['Item1'] + row['Item2'], axis=1) 

In [12]: df 
Out[12]: 
    Item1 Item2 Moves Items 
1  A  B  1 AB 
2  A  C  2 AC 
3  B  D  3 BD 
4  C  A  1 CA 
5  C  B  5 CB 
6  D  B  4 DB 
7  D  C  1 DC 

और Items में है अगर (वर्णमाला) आदेश, इसे छोड़ वरना यह स्विच और Moves नकारना:

In [13]: df[['Items','Moves']] = df.apply(lambda row: (row[['Items', 'Moves']]) 
                 if row['Items'][0] <= row['Items'][1] 
                 else (row['Items'][::-1], -row['Moves']), 
              axis=1) 

In [14]: df 
Out[14]: 
    Item1 Item2 Moves Items 
1  A  B  1 AB 
2  A  C  2 AC 
3  B  D  3 BD 
4  C  A  -1 AC 
5  C  B  -5 BC 
6  D  B  -4 BD 
7  D  C  -1 CD 

In [15]: g = df.groupby('Items') 

In [16]: g.sum() 
Out[16]: 
     Moves 
Items  
AB   1 
AC   1 
BC  -5 
BD  -1 
CD  -1 

किस तरह के सबसे अधिक है, और आप के लिए पर्याप्त हो सकता है।

वांछित अंतिम आउटपुट एक hackey तरीका हो सकता है पाने के लिए:

In [17]: df1 = g.first() # the first row in each group 

In [18]: df1.Moves = g.sum() 

In [19]: df2 = df1.reset_index(drop=True) 

In [20]: df2 
Out[20]: 
    Item1 Item2 Moves 
0  A  B  1 
1  A  C  1 
2  C  B  -5 
3  B  D  -1 
4  D  C  -1 

हालांकि, नोटिस निषेध बहुत सही (उन लोगों के लिए चारों ओर नहीं बल्कि सीडी से जैसे डीसी गलत तरीके से) नहीं है:

In [21]: df2.Moves = df2.apply(lambda row: row['Moves'] 
              if row['Item1'] <= row['Item2'] 
              else -row['Moves'], 
           axis=1) 

In [22]: df2 
Out[22]: 
    Item1 Item2 Moves 
0  A  B  1 
1  A  C  1 
2  C  B  5 
3  B  D  -1 
4  D  C  1 
संबंधित मुद्दे