<질문>
공통 행이 있는 두 개의 pandas 데이터 프레임이 있습니다.
dataframe2가 dataframe1의 하위 집합이라고 가정합니다.
dataframe2에 없는 dataframe1의 행을 어떻게 가져올 수 있습니까?
df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5], 'col2' : [10, 11, 12, 13, 14]})
df2 = pandas.DataFrame(data = {'col1' : [1, 2, 3], 'col2' : [10, 11, 12]})
df1
col1 col2
0 1 10
1 2 11
2 3 12
3 4 13
4 5 14
df2
col1 col2
0 1 10
1 2 11
2 3 12
예상 결과:
col1 col2
3 4 13
4 5 14
<답변1>
현재 선택한 솔루션이 잘못된 결과를 생성합니다. 이 문제를 올바르게 해결하기 위해 왼쪽 조인을 수행할 수 있습니다.df1
에게df2
, 먼저 에 대한 고유한 행만 가져오는지 확인합니다.df2
.
먼저 원본 DataFrame을 수정하여 데이터 [3, 10]이 있는 행을 추가해야 합니다.
df1 = pd.DataFrame(data = {'col1' : [1, 2, 3, 4, 5, 3],
'col2' : [10, 11, 12, 13, 14, 10]})
df2 = pd.DataFrame(data = {'col1' : [1, 2, 3],
'col2' : [10, 11, 12]})
df1
col1 col2
0 1 10
1 2 11
2 3 12
3 4 13
4 5 14
5 3 10
df2
col1 col2
0 1 10
1 2 11
2 3 12
왼쪽 조인을 수행하여 중복 항목을 제거합니다.df2
각 행의df1
정확히 1 행의 조인df2
. 매개변수 사용indicator
행이 있는 테이블을 나타내는 추가 열을 반환합니다.
df_all = df1.merge(df2.drop_duplicates(), on=['col1','col2'],
how='left', indicator=True)
df_all
col1 col2 _merge
0 1 10 both
1 2 11 both
2 3 12 both
3 4 13 left_only
4 5 14 left_only
5 3 10 left_only
부울 조건을 만듭니다.
df_all['_merge'] == 'left_only'
0 False
1 False
2 False
3 True
4 True
5 True
Name: _merge, dtype: bool
몇몇 솔루션은 동일한 실수를 범합니다. 각 값이 동일한 행에 함께 있는 것이 아니라 각 열에 독립적으로 있는지만 확인합니다. 고유하지만 두 열의 값이 있는 마지막 행을 추가합니다.df2
실수를 폭로합니다.
common = df1.merge(df2,on=['col1','col2'])
(~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2))
0 False
1 False
2 False
3 True
4 True
5 False
dtype: bool
이 솔루션은 동일한 잘못된 결과를 얻습니다.
df1.isin(df2.to_dict('l')).all(1)
<답변2>
한 가지 방법은 두 dfs 형식의 내부 병합 결과를 저장하는 것입니다. 그런 다음 한 열의 값이 이 공통에 있지 않을 때 단순히 행을 선택할 수 있습니다.
In [119]:
common = df1.merge(df2,on=['col1','col2'])
print(common)
df1[(~df1.col1.isin(common.col1))&(~df1.col2.isin(common.col2))]
col1 col2
0 1 10
1 2 11
2 3 12
Out[119]:
col1 col2
3 4 13
4 5 14
편집하다
찾은 또 다른 방법은 다음을 사용하는 것입니다.isin
생산할 것입니다NaN
삭제할 수 있는 행:
In [138]:
df1[~df1.isin(df2)].dropna()
Out[138]:
col1 col2
3 4 13
4 5 14
그러나 df2가 동일한 방식으로 행을 시작하지 않으면 작동하지 않습니다.
df2 = pd.DataFrame(data = {'col1' : [2, 3,4], 'col2' : [11, 12,13]})
전체 df를 생성합니다.
In [140]:
df1[~df1.isin(df2)].dropna()
Out[140]:
col1 col2
0 1 10
1 2 11
2 3 12
3 4 13
4 5 14
<답변3>
인덱스가 데이터 프레임에서 일관성이 있다고 가정합니다(실제 col 값은 고려하지 않음).
df1[~df1.index.isin(df2.index)]
<답변4>
이미 암시했듯이 isin은 일치를 위해 열과 인덱스가 동일해야 합니다. 행 내용에만 일치해야 하는 경우 존재하는 행을 필터링하기 위한 마스크를 얻는 한 가지 방법은 행을 (Multi)Index로 변환하는 것입니다.
In [77]: df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5, 3], 'col2' : [10, 11, 12, 13, 14, 10]})
In [78]: df2 = pandas.DataFrame(data = {'col1' : [1, 3, 4], 'col2' : [10, 12, 13]})
In [79]: df1.loc[~df1.set_index(list(df1.columns)).index.isin(df2.set_index(list(df2.columns)).index)]
Out[79]:
col1 col2
1 2 11
4 5 14
5 3 10
인덱스를 고려해야 하는 경우 set_index에는 기존 인덱스에 열을 추가하기 위한 키워드 인수 append가 있습니다. 열이 정렬되지 않으면 데이터를 정렬하기 위해 list(df.columns)를 열 사양으로 바꿀 수 있습니다.
pandas.MultiIndex.from_tuples(df.to_records(index = False).tolist())
대안으로 색인을 만드는 데 사용할 수 있지만 이것이 더 효율적일지는 의문입니다.
<답변5>
여러 필드(column_names)가 있는 두 개의 데이터 프레임 df_1 및 df_2가 있고 일부 필드(예: fields_x, fields_y)를 기준으로 df_2에 없는 df_1의 항목만 찾으려면 다음 단계를 따르십시오.
Step1. df_1 및 df_2에 각각 key1 및 key2 열을 추가합니다.
Step2. 아래와 같이 데이터 프레임을 병합합니다. field_x 및 field_y는 원하는 열입니다.
3단계. df_1에서 key1이 key2와 같지 않은 행만 선택합니다.
Step4.key1과 key2를 놓습니다.
이 방법은 문제를 해결하고 큰 데이터 세트에서도 빠르게 작동합니다. 1,000,000개 이상의 행이 있는 데이터 프레임에 대해 시도했습니다.
df_1['key1'] = 1
df_2['key2'] = 1
df_1 = pd.merge(df_1, df_2, on=['field_x', 'field_y'], how = 'left')
df_1 = df_1[~(df_1.key2 == df_1.key1)]
df_1 = df_1.drop(['key1','key2'], axis=1)
<답변6>
조금 늦었지만 pd.merge의 "indicator" 매개변수를 확인하는 것이 좋습니다.
예를 들어 이 다른 질문을 참조하십시오.Compare PandaS DataFrames and return rows that are missing from the first one
<답변7>
df = df1.drop_duplicates().merge(df2.drop_duplicates(), on=df2.columns.to_list(),
how='left', indicator=True)
df.loc[df._merge=='left_only',df.columns!='_merge']
drop duplicated는 비교를 최소화하는 데 사용됩니다. 그들 없이도 작동합니다. 가장 좋은 방법은 인덱스가 아닌 행 내용 자체를 비교하는 것입니다. 또는 하나 또는 두 개의 열과 동일한 코드를 'both' 및 'right_only'와 같은 다른 필터에도 사용하여 유사한 결과를 얻을 수 있습니다. 이 구문의 경우 데이터 프레임은 여러 열과 다른 인덱스를 가질 수 있습니다. 두 데이터 프레임 모두에서 열만 발생해야 합니다.
- index.difference는 고유 인덱스 기반 비교에서만 작동합니다.
pandas.concat()
결합drop_duplicated()
유지하려는 데이터 프레임에만 있을 수 있고 유효한 이유로 복제된 행도 제거하기 때문에 이상적이지 않습니다.
<답변8>
병합을 포함하는 답변은 매우 느립니다. 따라서 두 데이터 프레임 간에 다른 행을 가져오는 다른 방법을 제안합니다.
df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5], 'col2' : [10, 11, 12, 13, 14]})
df2 = pandas.DataFrame(data = {'col1' : [1, 2, 3], 'col2' : [10, 11, 12]})
면책 조항: 내 솔루션은 두 데이터 프레임이 다른 하나의 특정 열에 관심이 있는 경우 작동합니다. 모든 열이 동일한 행에만 관심이 있는 경우 이 방법을 사용하지 마십시오.
col1이 일종의 ID이고 두 데이터 프레임에 포함되지 않은 행만 가져오려고 한다고 가정해 보겠습니다.
ids_in_df2 = df2.col1.unique()
not_found_ids = df[~df['col1'].isin(ids_in_df2 )]
그리고 그게 다야. 두 데이터 프레임 모두에 col1이 나타나지 않는 행만 포함하는 데이터 프레임을 얻습니다.
<답변9>
당신은 또한 연결할 수 있습니다df1
,df2
:
x = pd.concat([df1, df2])
그런 다음 모든 중복을 제거하십시오.
y = x.drop_duplicates(keep=False, inplace=False)
<답변10>
간단한 2단계로 더 쉬운 방법이 있습니다. OP가 언급한 대로dataframe2가 dataframe1의 하위 집합이라고 가정합니다., 2개의 데이터 프레임의 열이 동일합니다.
df1 = pd.DataFrame(data = {'col1' : [1, 2, 3, 4, 5, 3],
'col2' : [10, 11, 12, 13, 14, 10]})
df2 = pd.DataFrame(data = {'col1' : [1, 2, 3],
'col2' : [10, 11, 12]})
### Step 1: just append the 2nd df at the end of the 1st df
df_both = df1.append(df2)
### Step 2: drop rows which contain duplicates, Drop all duplicates.
df_dif = df_both.drop_duplicates(keep=False)
## mission accompliched!
df_dif
Out[20]:
col1 col2
3 4 13
4 5 14
5 3 10
<답변11>
당신은 그것을 사용하여 할 수 있습니다isin(dict)방법:
In [74]: df1[~df1.isin(df2.to_dict('l')).all(1)]
Out[74]:
col1 col2
3 4 13
4 5 14
설명:
In [75]: df2.to_dict('l')
Out[75]: {'col1': [1, 2, 3], 'col2': [10, 11, 12]}
In [76]: df1.isin(df2.to_dict('l'))
Out[76]:
col1 col2
0 True True
1 True True
2 True True
3 False False
4 False False
In [77]: df1.isin(df2.to_dict('l')).all(1)
Out[77]:
0 True
1 True
2 True
3 False
4 False
dtype: bool
<답변12>
이를 해결하는 또 다른 방법은 다음과 같습니다.
df1[~df1.index.isin(df1.merge(df2, how='inner', on=['col1', 'col2']).index)]
또는:
df1.loc[df1.index.difference(df1.merge(df2, how='inner', on=['col1', 'col2']).index)]
<답변13>
병합 기능을 사용하여 유사하지 않은 행 추출
df = df1.merge(df2.drop_duplicates(), on=['col1','col2'],
how='left', indicator=True)
다른 행을 CSV로 저장
df[df['_merge'] == 'left_only'].to_csv('output.csv')
<답변14>
이 작업을 수행하는 방법은 하나의 데이터 프레임에 고유한 새 열을 추가하고 이를 사용하여 항목을 유지할지 여부를 선택하는 것입니다.
df2[col3] = 1
df1 = pd.merge(df_1, df_2, on=['field_x', 'field_y'], how = 'outer')
df1['Empt'].fillna(0, inplace=True)
이렇게 하면 df1의 모든 항목이 df1에 고유한 경우 0, 두 데이터 프레임 모두에 있는 경우 1의 코드를 갖게 됩니다. 그런 다음 이것을 사용하여 원하는 것으로 제한합니다.
answer = nonuni[nonuni['Empt'] == 0]
<답변15>
이것은 어떤가요:
df1 = pandas.DataFrame(data = {'col1' : [1, 2, 3, 4, 5],
'col2' : [10, 11, 12, 13, 14]})
df2 = pandas.DataFrame(data = {'col1' : [1, 2, 3],
'col2' : [10, 11, 12]})
records_df2 = set([tuple(row) for row in df2.values])
in_df2_mask = np.array([tuple(row) in records_df2 for row in df1.values])
result = df1[~in_df2_mask]
<답변16>
더 쉽고 간단하고 우아하게
uncommon_indices = np.setdiff1d(df1.index.values, df2.index.values)
new_df = df1.loc[uncommon_indices,:]
'개발 > Python' 카테고리의 다른 글
[파이썬] 변수가 배열인지 스칼라인지 식별하는 방법 (0) | 2023.01.20 |
---|---|
[파이썬] requests 라이브러리에서 JSON 응답을 구문 분석하는 가장 좋은 방법은? (0) | 2023.01.20 |
[파이썬] Pylint 경고를 비활성화는 방법은? (0) | 2023.01.20 |
[파이썬] 백그라운드 프로세스를 시작하는 방법은? (0) | 2023.01.20 |