2016-07-08 10 views
3

나는 판다 데이터 프레임 A와 B가 두 개 있습니다.두 팬더 데이터 프레임의 행을 비교하는 가장 빠른 방법은 무엇입니까?

A는 존재 또는 부존재를 나타내는 이진 값으로 채워져 있습니다.

B는 1024 행 × 10 열이며 0과 1의 전체 반복이므로 1024 행을가집니다.

A의 특정 10 열에서 B의 주어진 행과 일치하는 행을 찾으려고합니다. 전체 행이 요소가 아닌 요소와 일치해야합니다.

예를 들어, 나는

A[(A.ix[:,(1,2,3,4,5,6,7,8,9,10)==(1,0,1,0,1,0,0,1,0,0)).all(axis=1)] 

그 특정 열 (1,2,3,4,5,6,7,8,9,10)

에서 B의 (1,0,1,0,1,0,0,1,0,0) 행과 일치 업에 그 행 (3,5,8,11,15) 뭔가를 반환 할 것입니다 그리고 모든을 통해이 작업을 수행 할 수 B.에서 행 내가이 일을 알아낼 수있는 가장 좋은 방법이었다 :

import numpy as np 
for i in B: 
    B_array = np.array(i) 
    Matching_Rows = A[(A.ix[:,(1,2,3,4,5,6,7,8,9,10)] == B_array).all(axis=1)] 
    Matching_Rows_Index = Matching_Rows.index 

이를 한 인스턴스에서는 끔찍한 것이 아니지만, 약 2 만 회 실행되는 while 루프에서 사용합니다. 그러므로, 꽤 느려집니다.

저는 DataFrame.apply를 사용하여 아무 소용이 없습니다. 더 잘 매핑 할 수 있을까요?

필자는 Python을 처음 접했을 때 누군가가 분명히 더 효율적인 것을 보길 바랬습니다.

감사합니다.

+1

A의 단일 행에 B가 여러 개 일치 할 수도 있습니다. 따라서 A 행의 특정 행에 적어도 하나의 일치가 필요합니까? 또는 col1-col10 사이의 일치 항목을 게시 된 코드로 판단하는 경우에만 찾으십니까? – Divakar

+1

일치하는 행으로 무엇을 할 예정입니까? 여러분은 B를 완전히 피하고 A 그룹의 관심사에 groupby를 사용할 수있는 것처럼 보입니다. –

+0

일치하는 행을 기반으로 엔트로피 값을 계산할 것입니다. –

답변

2

당신은 reset_indexmerge을 사용할 수 있습니다 - 출력 사용자 정의 열 A에 동일한 B의 인덱스입니다

A = pd.DataFrame({'A':[1,0,1,1], 
        'B':[0,0,1,1], 
        'C':[1,0,1,1], 
        'D':[1,1,1,0], 
        'E':[1,1,0,1]}) 

print (A) 
    A B C D E 
0 1 0 1 1 1 
1 0 0 0 1 1 
2 1 1 1 1 0 
3 1 1 1 0 1 

B = pd.DataFrame({'0':[1,0,1], 
        '1':[1,0,1], 
        '2':[1,0,0]}) 

print (B) 
    0 1 2 
0 1 1 1 
1 0 0 0 
2 1 1 0 
print (pd.merge(B.reset_index(), 
       A.reset_index(), 
       left_on=B.columns.tolist(), 
       right_on=A.columns[[0,1,2]].tolist(), 
       suffixes=('_B','_A'))) 

    index_B 0 1 2 index_A A B C D E 
0  0 1 1 1  2 1 1 1 1 0 
1  0 1 1 1  3 1 1 1 0 1 
2  1 0 0 0  1 0 0 0 1 1  

print (pd.merge(B.reset_index(), 
       A.reset_index(), 
       left_on=B.columns.tolist(), 
       right_on=A.columns[[0,1,2]].tolist(), 
       suffixes=('_B','_A'))[['index_B','index_A']])  

    index_B index_A 
0  0  2 
1  0  3 
2  1  1 
+0

감사합니다! 내 코드의 다른 변경 사항과 함께 실행 시간이 10 시간에서 10 분으로 단축되었습니다. –

+0

@ jezrael. 내가 올바르게 질문을 이해하지 못했지만, 위의 솔루션을 사용하면 솔루션에서 지정한 범위를 벗어나는 A의 행을 어떻게 비교할 것입니까? (예 : A의 행 22:32가 B의 행 7과 일치 함)? 내 이해에 따라 비교 목적 (예 : cols 0,1,2)을 위해 A 열의 조회 목록을 하드 코어했습니다. –

1

loc 또는 ix를 사용하고 열 열이 모두 같은 행을 찾기 위해 판다에서 할 수 있습니다. 이처럼 :

A.loc[(A[1]==B[1]) & (A[2]==B[2]) & (A[3]==B[3]) & A[4]==B[4]) & (A[5]==B[5]) & (A[6]==B[6]) & (A[7]==B[7]) & (A[8]==B[8]) & (A[9]==B[9]) & (A[10]==B[10])] 

이 내 의견에 매우 추악한 그러나 그것은 작동하고 훨씬 더 빠르게 처리 될 수 있도록 루프를 제거한다. 만약 누군가가 같은 작업을보다 우아하게 코딩 할 수 있다면 나는 놀라지 않을 것이다.

3

우리는 모두 dataframes 이진 값 0 이상이 있다는 사실을 남용 할 수는 1의 각 열을 A에서 축약하고 B의 모든 열을 1D 개의 배열로 축소하여 각 행을 동등한 10 진수로 변환 될 수있는 2 진수. 이렇게하면 문제가 상당히 줄어들어 성능에 도움이됩니다. 이제 1D 배열을 얻은 후 의 일치 항목을 A에 찾고의 일치 항목을 찾으려면 np.in1d을 사용할 수 있습니다.

# Setup 1D arrays corresponding to selected cols from A and entire B 
S = 2**np.arange(10) 
A_ID = np.dot(A[range(1,11)],S) 
B_ID = np.dot(B,S) 

# Look for matches that exist from B_ID in A_ID, whose indices 
# would be desired row indices that have matched from B 
out_row_idx = np.where(np.in1d(A_ID,B_ID))[0] 

샘플 실행 - -

따라서, 우리가 같이 구현했을

In [157]: # Setup dataframes A and B with rows 0, 4 in A having matches from B 
    ...: A_arr = np.random.randint(0,2,(10,14)) 
    ...: B_arr = np.random.randint(0,2,(7,10)) 
    ...: 
    ...: B_arr[2] = A_arr[4,1:11] 
    ...: B_arr[4] = A_arr[4,1:11] 
    ...: B_arr[5] = A_arr[0,1:11] 
    ...: 
    ...: A = pd.DataFrame(A_arr) 
    ...: B = pd.DataFrame(B_arr) 
    ...: 

In [158]: S = 2**np.arange(10) 
    ...: A_ID = np.dot(A[range(1,11)],S) 
    ...: B_ID = np.dot(B,S) 
    ...: out_row_idx = np.where(np.in1d(A_ID,B_ID))[0] 
    ...: 

In [159]: out_row_idx 
Out[159]: array([0, 4]) 
+0

따라서이 질문에 대한 후속 질문이 있습니다.이 방법의 효율성은 정말 좋지만 내 dataframes를 사용하여 그것을 실행할 때,'out_row_idx'는 단지 A의 모든 인덱스를 포함하는 크기 1000의 배열을 반환합니다. 왜 그런지에 대한 입력이 있습니까? –

+0

'S = 2 ** np.arange (10); A_ID = np.dot (A [X], S); B_ID = np.dot (B, S); out_row_idx = np.where (np.in1d ​​(A_ID, B_ID)) [0]' –

0

이 특별한 경우를, 10 0과 1의 당신의 행은 10 자리 바이너리로 해석 될 수 . B가 순서가 맞으면 0에서 1023까지의 범위로 해석 할 수 있습니다.이 경우, A 열을 10 열 청크로 가져와 이진 값이 무엇인지 계산하면됩니다.

나는 2의 거듭 제곱의 범위를 정의함으로써 시작하여 행렬 곱셈을 할 수 있습니다.

twos = pd.Series(np.power(2, np.arange(10))) 

다음으로, 내가 얻을 twosA_를 곱 것, 마지막으로 10

A = pd.DataFrame(np.random.binomial(1, .5, (1000, 500))) 
A.columns = pd.MultiIndex.from_tuples(zip((A.columns/10).tolist(), (A.columns % 10).tolist())) 
A_ = A.stack(0) 

A_.head() 

enter image description here

의 내 덩어리를 얻기 위해 MultiIndex 및 stack에 A의 열 레이블을 다시 지정합니다 각 행의 정수 표현 및 unstack.

enter image description here

A_.dot(twos).unstack() 
은 필요도 없다 이제 각 셀 우리 A.의 특정 행에 대해 특정 10 컬럼 청크에 일치 B의 행의 어떤 대표 1000 × 50 DataFrame 인 B.

관련 문제