2013-02-21 25 views
5

Tôi có khung dữ liệu sau đây tôi hiển thị số lần tôi đã chuyển từ Mục 1 sang Mục 2. Ví dụ: có một chuyển đổi từ A sang B, 2 từ A đến C , 1 từ C đến ATính toán sự khác biệt theo cặp từ các cột cụ thể trong một khung dữ liệu


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 

tôi muốn để tính toán sự khác biệt giữa hai mặt hàng, do đó, một Dataframe mới được xây dựng sẽ là sau

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

Có ai có ý tưởng làm thế nào để làm điều đó bằng cách sử dụng Pandas? Tôi đoán tôi cần phải lập chỉ mục trên hai cột đầu tiên nhưng tôi khá mới trong Pandas và tôi phải đối mặt với rất nhiều khó khăn. Cảm ơn

EDIT Không thể có bất kỳ bản sao pairs.For dụ bạn không thể nhìn thấy hai lần A-> B (nhưng bạn có thể dĩ nhiên thấy b-> a)

+0

Điều quan trọng với bạn là hướng chuyển đổi được nhìn thấy lần đầu tiên được giữ nguyên, hoặc một hàng có 'B C -5' có thể chấp nhận được không? – DSM

+0

Nó không phải là quan trọng, nhưng tôi đoán rằng đó là một vấn đề của sở thích hoặc xóa cuộc gặp gỡ đầu tiên của hai quá trình chuyển đổi hoặc thứ hai. – BigScratch

Trả lời

3

Tôi chắc rằng ai đó có thể đơn giản hóa việc này xuống ít dòng hơn, nhưng tôi đã để nó dài để giúp làm rõ những gì đang diễn ra. Tóm lại, chia khung dữ liệu thành hai phần dựa trên liệu 'Item1' có sớm hơn trong bảng chữ cái hay không 'Item2'. Sau đó lật 'Item1' và 'Item2' và phủ nhận 'Di chuyển' cho một phần. Dán chúng lại với nhau và sử dụng chức năng groupby để tổng hợp các hàng.

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

Cảm ơn bạn! Câu trả lời này có vẻ khá tao nhã với tôi - tôi đã quản lý để làm điều này bằng cách sử dụng danh sách nhưng tôi đã lặp qua từ điển cho mỗi cặp để tìm cặp đối diện, đó là khá kém hiệu quả – BigScratch

+0

Chỉnh sửa được đề xuất của bạn là tốt nhất. Tôi không chắc tại sao nó lại bị người khác từ chối, nhưng tôi không thể 'chấp nhận' nó sau khi nó đã bị từ chối bởi 3 người. Tôi đã thực hiện chỉnh sửa. –

1

Dưới đây là một cách để làm điều đó:

Trước tiên hãy tạo hàng chỉ chứa chuỗi cho Item1 và Item2.

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 

và nếu Items là trong (ABC) để rời khỏi nó, nếu không chuyển đổi nó và phủ nhận 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 

Đó là hầu hết các cách, và có thể đủ cho bạn.

Để có được kết quả cuối cùng mong muốn một cách hackey có thể là:

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 

Tuy nhiên, chú ý phủ định là không hoàn toàn đúng (đối với những người xung quanh một cách sai lầm ví dụ DC chứ không phải là đĩa CD):

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 
Các vấn đề liên quan