2013-02-21 10 views
5

Öğe1'den Öğe 2'ye kaç kez bir hareket gördüğümü gösterdiğim aşağıdaki veri çerçevesine sahibim. Örneğin A'dan B'ye, 2'den A'dan C'ye bir geçiş var. , C 1 ABir veri çerçevesindeki belirli sütunlardan çift yön farkını hesaplayın


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 

çok yeni inşa Dataframe aşağıdaki

Item1 Item2 Moves 
    1 A  B  1 
    2 A  C  1 
    3 B  D  -1 
    4 C  B  5 
    5 D  C  1 
012 olacaktır, iki öğe arasındaki farkı hesaplamak istiyorum

Panda'ları kullanarak bunun nasıl yapılacağı hakkında bir fikri olan var mı? Sanırım ilk iki sütunda indekslemeye ihtiyacım var ama Pandalar'da oldukça yeni ve birçok zorlukla karşılaşıyorum. Teşekkür

DÜZENLEME Orada iki kez b> a- göremiyorum Örneğin pairs.For yinelenen olamaz (ama tabii can bkz b-> a)

+0

İlk geçiş geçişinin korunduğunda veya B C -5 ile bir satırın kabul edilebilir olması sizin için önemli midir? – DSM

+0

Bu önemli değil, ama sanırım iki geçişin ya da ikincisinin ilk karşılaşmasını silme tercihi. – BigScratch

cevap

3

Eminim ki birisi bunu daha az çizgiye indirgeyebilir, ancak neler olup bittiğini açıklığa kavuşturmak için uzun süre bıraktım. Özetle, 'Öğe1' alfabede daha önce 'Öğe2'den daha erken olup olmadığına göre veri çerçevesini iki parçaya bölün. Daha sonra 'Item1' ve 'Item2' tuşlarını çevirin ve tek parça için 'Moves' seçeneğini devre dışı bırakın. Onları bir araya yapıştırın ve satırları toplamak için groupby işlevini kullanın.

>>> 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

Teşekkür ederiz! Bu cevap bana göre oldukça zarif görünüyor - Listeleri kullanarak bunu yapmayı başarmıştım ama her çift için her bir çiftin karşılığını bulmakta zorlandım, bu da oldukça etkisiz – BigScratch

+0

Önerilen öneriniz iyi oldu. Neden başkaları tarafından reddedildiğinden emin değilim, ancak 3 kişi tarafından reddedildikten sonra 'onaylayamıyorum'. Düzenlemeyi yaptım. –

1

İşte bunu yapmak için tek yolu şudur:

Önce Item1 ve Item2 için dize içeren bir satır oluşturun.

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 

ve Items ise (alfabetik) siparişi başka, bırakın onu geçmek ve Moves olumsuzlamak:

yolun en olduğunu ve sizin için yeterli olabilir
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 

.

: olumsuzluk (olanlar için CD yerine örneğin DC etrafında yanlış şekilde) çok doğru olmadığını fark Ancak

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 

:

bir hackey yolu olabilir istenen nihai çıktısını almak için
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