programing

판다 왼쪽 바깥쪽 조인 결과 왼쪽 테이블보다 큰 테이블이 나타남

sourcejob 2023. 9. 16. 08:58
반응형

판다 왼쪽 바깥쪽 조인 결과 왼쪽 테이블보다 큰 테이블이 나타남

제가 알기로는 왼쪽 바깥쪽 조인에 대해 알고 있는데, 결과 테이블의 행 수가 왼쪽 테이블의 행 수보다 많아선 안 됩니다.만약 이것이 잘못되었다면 저에게 알려주세요.

제 왼쪽 테이블은 192572행 8열입니다.

제 오른쪽 테이블은 42160행과 5열입니다.

내 왼쪽 테이블에는 '키'라는 열과 일치하는 'id'라는 필드가 있습니다.

그러므로 다음과 같이 병합합니다.

combined = pd.merge(a,b,how='left',left_on='id',right_on='key')

그런데 그 모양을 합하면 236569입니다.

내가 뭘 잘못 알고 있는 거지?

키가 다른 DataFrame에서 두 개 이상의 행과 일치하는 경우 이 값이 증가할 것으로 예상할 수 있습니다.

In [11]: df = pd.DataFrame([[1, 3], [2, 4]], columns=['A', 'B'])

In [12]: df2 = pd.DataFrame([[1, 5], [1, 6]], columns=['A', 'C'])

In [13]: df.merge(df2, how='left')  # merges on columns A
Out[13]: 
   A  B   C
0  1  3   5
1  1  3   6
2  2  4 NaN

동작을 방지하려면 df2에서 중복을 삭제합니다.

In [21]: df2.drop_duplicates(subset=['A'])  # you can use take_last=True
Out[21]: 
   A  C
0  1  5

In [22]: df.merge(df2.drop_duplicates(subset=['A']), how='left')
Out[22]: 
   A  B   C
0  1  3   5
1  2  4 NaN

주어진 답변에 약간의 추가 사항은 validate라는 매개 변수가 있다는 것입니다. 이 매개 변수는 오른쪽 테이블에 중복된 ID가 있는 경우 오류를 발생시키는 데 사용할 수 있습니다.

combined = pd.merge(a,b,how='left',left_on='id',right_on='key', validate = 'm:1')

예를 들어 모든 열이 중복되지 않을 경우 중복된 데이터가 손실되지 않는 이 동작을 방지하기 위해 사용할 수 있는 전략도 있습니다.있다면

In [1]: df = pd.DataFrame([[1, 3], [2, 4]], columns=['A', 'B'])

In [2]: df2 = pd.DataFrame([[1, 5], [1, 6]], columns=['A', 'C'])

한 가지 방법은 중복의 평균을 취하는 것입니다. (합 등을 취할 수도 있습니다.)

In [3]: df3 = df2.groupby('A').mean().reset_index()

In [4]: df3
Out[4]: 
     C
A     
1  5.5

In [5]: merged = pd.merge(df,df3,on=['A'], how='outer')

In [6]: merged
Out[204]: 
   A  B    C
0  1  3  5.5
1  2  4  NaN

또는 pd.to _message를 사용하여 변환할 수 없는 비반복 데이터가 있거나 단순히 평균을 사용하지 않으려면 중복을 열거하여 병합 변수를 변경할 수 있습니다.그러나 이 전략은 두 데이터셋 모두에 중복이 존재할 때 적용됩니다(이는 동일한 문제 동작을 유발하고 일반적인 문제이기도 함).

In [7]: df = pd.DataFrame([['a', 3], ['b', 4],['b',0]], columns=['A', 'B'])

In [8]: df2 = pd.DataFrame([['a', 3], ['b', 8],['b',5]], columns=['A', 'C'])

In [9]: df['count'] = df.groupby('A')['B'].cumcount()

In [10]: df['A'] = np.where(df['count']>0,df['A']+df['count'].astype(str),df['A'].astype(str))

In[11]: df
Out[11]: 
    A  B  count
0   a  3      0
1   b  4      0
2  b1  0      1

df2에 대해서도 동일한 작업을 수행하고 df와 df2의 카운트 변수를 삭제하고 'A'에 병합합니다.

In [16]: merged
Out[16]: 
    A  B  C
0   a  3  3        
1   b  4  8        
2  b1  0  5        

메모 몇 장.이 마지막 경우에는 주어진 관측치에 대해 두 개 이상의 중복이 있을 수 있으므로 .duplicated 대신 .cumcount()를 사용합니다.또한 np를 사용하기 때문에 .astype(str)을 사용하여 카운트 값을 문자열로 변환합니다.여기서 명령을 사용하지만 pd.concat() 또는 다른 것을 사용하면 다른 응용 프로그램을 사용할 수 있습니다.

마지막으로, 하나의 데이터 세트만 중복을 가지고 있지만 유지하고 싶은 경우, 후자의 전략 전반부를 사용하여 결과적인 병합에서 중복을 구별할 수 있습니다.

키 값이 같은 항목이 여러 개 있을 수 있습니다.오른쪽 표의 키에 대해 중복되는 내용이 없는지 확인합니다.

# One workaround could be remove duplicates from right table w.r.t key.

combined = pd.merge(a.reset_index(),b.drop_duplicates(['key']),how='left',left_on='id',right_on='key')


이 문제를 해결하려면 Left DataFrame에 Unique INDEX 열을 만들어 "Merged DataFrame"이 준비된 후 이 "INDEX" 열을 "Duplicates"에 대해 추적할 수 있습니다.

 1. LEFT_df['INDEX'] = LEFT_df.index + 1
 2. LEFT_df.shape 
 3. Merged_df = pd.merge(LEFT_df , Right_df , how = "left", on = 'Common column')
 4. LEFT_df['INDEX'].duplicated().sum()
 5. Merged_df = Merged_df.drop_duplicates(subset=['INDEX'], keep='first')
 6. Merged_df.shape (will now match with the LEFT_df.shape)

drop_categates를 사용하면 다음과 같습니다.

merged = pd.merge(df,df3,on=['A'], how='outer').drop_duplicates()

언급URL : https://stackoverflow.com/questions/22720739/pandas-left-outer-join-results-in-table-larger-than-left-table

반응형