두 데이터 프레임을 비교하고 차이점 얻기
두 개의 데이터 프레임이 있습니다. 예 :
df1:
Date Fruit Num Color
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green
df2:
Date Fruit Num Color
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green
2013-11-25 Apple 22.1 Red
2013-11-25 Orange 8.6 Orange
각 데이터 프레임에는 날짜가 인덱스로 있습니다. 두 데이터 프레임은 동일한 구조를 가지고 있습니다.
내가하고 싶은 것은이 두 데이터 프레임을 비교하고 df1에없는 df2에있는 행을 찾는 것입니다. 날짜 (인덱스)와 첫 번째 열 (Banana, APple 등)을 비교하여 df2와 df1에 존재하는지 확인하고 싶습니다.
나는 다음을 시도했다 :
첫 번째 방법에서는 "예외 : 레이블이 동일한 DataFrame 개체 만 비교할 수 있습니다"라는 오류가 발생 합니다 . 날짜를 인덱스로 제거하려고 시도했지만 동일한 오류가 발생합니다.
온 세 번째 방법 , 나는 False를 반환하기 위해 어설 수 있지만, 실제로 다른 행을 참조하는 방법을 알아낼 수 없습니다.
모든 포인터를 환영합니다
이 접근 방식 df1 != df2
은 행과 열이 동일한 데이터 프레임에서만 작동합니다. 실제로 모든 데이터 프레임 축은 _indexed_same
메서드 와 비교 되며 열 / 인덱스 순서에서도 차이가 발견되면 예외가 발생합니다.
내가 당신을 맞았다면, 당신은 변화가 아니라 대칭적인 차이를 찾고 싶어합니다. 이를 위해 한 가지 접근 방식은 데이터 프레임을 연결하는 것입니다.
>>> df = pd.concat([df1, df2])
>>> df = df.reset_index(drop=True)
그룹화
>>> df_gpby = df.groupby(list(df.columns))
고유 레코드 색인 가져 오기
>>> idx = [x[0] for x in df_gpby.groups.values() if len(x) == 1]
필터
>>> df.reindex(idx)
Date Fruit Num Color
9 2013-11-25 Orange 8.6 Orange
8 2013-11-25 Apple 22.1 Red
데이터 프레임을 전달하여 사전에 연결하면 중복 항목을 쉽게 삭제할 수있는 다중 인덱스 데이터 프레임이 생성되어 데이터 프레임 간의 차이가있는 다중 인덱스 데이터 프레임이 생성됩니다.
import sys
if sys.version_info[0] < 3:
from StringIO import StringIO
else:
from io import StringIO
import pandas as pd
DF1 = StringIO("""Date Fruit Num Color
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green
""")
DF2 = StringIO("""Date Fruit Num Color
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green
2013-11-25 Apple 22.1 Red
2013-11-25 Orange 8.6 Orange""")
df1 = pd.read_table(DF1, sep='\s+')
df2 = pd.read_table(DF2, sep='\s+')
#%%
dfs_dictionary = {'DF1':df1,'DF2':df2}
df=pd.concat(dfs_dictionary)
df.drop_duplicates(keep=False)
결과:
Date Fruit Num Color
DF2 4 2013-11-25 Apple 22.1 Red
5 2013-11-25 Orange 8.6 Orange
필터링 단계 (내가 얻는 곳 :)를 제외하고 거의 나를 위해 거의 효과가 있었던 alko의 대답을 기반 ValueError: cannot reindex from a duplicate axis
으로 한 최종 솔루션은 다음과 같습니다.
# join the dataframes
united_data = pd.concat([data1, data2, data3, ...])
# group the data by the whole row to find duplicates
united_data_grouped = united_data.groupby(list(united_data.columns))
# detect the row indices of unique rows
uniq_data_idx = [x[0] for x in united_data_grouped.indices.values() if len(x) == 1]
# extract those unique values
uniq_data = united_data.iloc[uniq_data_idx]
더 빠르고 더 나은 더 간단한 솔루션이 있으며, 숫자가 다르면 수량 차이를 줄 수도 있습니다.
df1_i = df1.set_index(['Date','Fruit','Color'])
df2_i = df2.set_index(['Date','Fruit','Color'])
df_diff = df1_i.join(df2_i,how='outer',rsuffix='_').fillna(0)
df_diff = (df_diff['Num'] - df_diff['Num_'])
여기서 df_diff는 차이점의 개요입니다. 수량 차이를 찾기 위해 사용할 수도 있습니다. 귀하의 예에서 :
설명 : 두 목록을 비교하는 것과 마찬가지로 효율적으로 수행하려면 먼저 순서를 지정한 다음 비교해야합니다 (목록을 세트 / 해싱으로 변환하는 것도 빠릅니다. 둘 다 단순한 O (N ^ 2) 이중 비교 루프에 대한 놀라운 개선입니다)
참고 : 다음 코드는 테이블을 생성합니다.
df1=pd.DataFrame({
'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24'],
'Fruit':['Banana','Orange','Apple','Celery'],
'Num':[22.1,8.6,7.6,10.2],
'Color':['Yellow','Orange','Green','Green'],
})
df2=pd.DataFrame({
'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24','2013-11-25','2013-11-25'],
'Fruit':['Banana','Orange','Apple','Celery','Apple','Orange'],
'Num':[22.1,8.6,7.6,10.2,22.1,8.6],
'Color':['Yellow','Orange','Green','Green','Red','Orange'],
})
# given
df1=pd.DataFrame({'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24'],
'Fruit':['Banana','Orange','Apple','Celery'],
'Num':[22.1,8.6,7.6,10.2],
'Color':['Yellow','Orange','Green','Green']})
df2=pd.DataFrame({'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24','2013-11-25','2013-11-25'],
'Fruit':['Banana','Orange','Apple','Celery','Apple','Orange'],
'Num':[22.1,8.6,7.6,1000,22.1,8.6],
'Color':['Yellow','Orange','Green','Green','Red','Orange']})
# find which rows are in df2 that aren't in df1 by Date and Fruit
df_2notin1 = df2[~(df2['Date'].isin(df1['Date']) & df2['Fruit'].isin(df1['Fruit']) )].dropna().reset_index(drop=True)
# output
print('df_2notin1\n', df_2notin1)
# Color Date Fruit Num
# 0 Red 2013-11-25 Apple 22.1
# 1 Orange 2013-11-25 Orange 8.6
이 솔루션을 얻었습니다. 도움이 되나요?
text = """df1:
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green
df2:
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green
2013-11-25 Apple 22.1 Red
2013-11-25 Orange 8.6 Orange
argetz45
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 118.6 Orange
2013-11-24 Apple 74.6 Green
2013-11-24 Celery 10.2 Green
2013-11-25 Nuts 45.8 Brown
2013-11-25 Apple 22.1 Red
2013-11-25 Orange 8.6 Orange
2013-11-26 Pear 102.54 Pale"""
.
from collections import OrderedDict
import re
r = re.compile('([a-zA-Z\d]+).*\n'
'(20\d\d-[01]\d-[0123]\d.+\n?'
'(.+\n?)*)'
'(?=[ \n]*\Z'
'|'
'\n+[a-zA-Z\d]+.*\n'
'20\d\d-[01]\d-[0123]\d)')
r2 = re.compile('((20\d\d-[01]\d-[0123]\d) +([^\d.]+)(?<! )[^\n]+)')
d = OrderedDict()
bef = []
for m in r.finditer(text):
li = []
for x in r2.findall(m.group(2)):
if not any(x[1:3]==elbef for elbef in bef):
bef.append(x[1:3])
li.append(x[0])
d[m.group(1)] = li
for name,lu in d.iteritems():
print '%s\n%s\n' % (name,'\n'.join(lu))
결과
df1
2013-11-24 Banana 22.1 Yellow
2013-11-24 Orange 8.6 Orange
2013-11-24 Apple 7.6 Green
2013-11-24 Celery 10.2 Green
df2
2013-11-25 Apple 22.1 Red
2013-11-25 Orange 8.6 Orange
argetz45
2013-11-25 Nuts 45.8 Brown
2013-11-26 Pear 102.54 Pale
여기에 간단한 솔루션을 설립하십시오.
https://stackoverflow.com/a/47132808/9656339
pd.concat([df1, df2]).loc[df1.index.symmetric_difference(df2.index)]
업데이트하고 배치하면 다른 사람들이 쉽게 찾을 수있는 곳에 위의 배심원 의 답변에 대한 ling 의 의견이 있습니다.
df_diff = pd.concat([df1,df2]).drop_duplicates(keep=False)
다음 데이터 프레임으로 테스트 :
df1=pd.DataFrame({
'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24'],
'Fruit':['Banana','Orange','Apple','Celery'],
'Num':[22.1,8.6,7.6,10.2],
'Color':['Yellow','Orange','Green','Green'],
})
df2=pd.DataFrame({
'Date':['2013-11-24','2013-11-24','2013-11-24','2013-11-24','2013-11-25','2013-11-25'],
'Fruit':['Banana','Orange','Apple','Celery','Apple','Orange'],
'Num':[22.1,8.6,7.6,10.2,22.1,8.6],
'Color':['Yellow','Orange','Green','Green','Red','Orange'],
})
주의해야 할 한 가지 중요한 세부 사항은 데이터에 중복 인덱스 값 이 있다는 것입니다 . 따라서 간단한 비교를 수행하려면 모든 항목을 고유하게 설정해야 df.reset_index()
하므로 조건에 따라 선택을 수행 할 수 있습니다. 귀하의 경우 색인이 정의되면 색인을 유지하고 싶으므로 한 줄짜리 솔루션이 있다고 가정합니다.
[~df2.reset_index().isin(df1.reset_index())].dropna().set_index('Date')
파이썬 적 관점에서 목표가 가독성을 높이는 것이라면, 우리는 조금 깰 수 있습니다 :
# keep the index name, if it does not have a name it uses the default name
index_name = df.index.name if df.index.name else 'index'
# setting the index to become unique
df1 = df1.reset_index()
df2 = df2.reset_index()
# getting the differences to a Dataframe
df_diff = df2[~df2.isin(df1)].dropna().set_index(index_name)
이것이 당신에게 유용하기를 바랍니다. ^ o ^
df1 = pd.DataFrame({'date': ['0207', '0207'], 'col1': [1, 2]})
df2 = pd.DataFrame({'date': ['0207', '0207', '0208', '0208'], 'col1': [1, 2, 3, 4]})
print(f"df1(Before):\n{df1}\ndf2:\n{df2}")
"""
df1(Before):
date col1
0 0207 1
1 0207 2
df2:
date col1
0 0207 1
1 0207 2
2 0208 3
3 0208 4
"""
old_set = set(df1.index.values)
new_set = set(df2.index.values)
new_data_index = new_set - old_set
new_data_list = []
for idx in new_data_index:
new_data_list.append(df2.loc[idx])
if len(new_data_list) > 0:
df1 = df1.append(new_data_list)
print(f"df1(After):\n{df1}")
"""
df1(After):
date col1
0 0207 1
1 0207 2
2 0208 3
3 0208 4
"""
이 방법을 시도해 보았는데 효과가있었습니다. 도움이되기를 바랍니다.
"""Identify differences between two pandas DataFrames"""
df1.sort_index(inplace=True)
df2.sort_index(inplace=True)
df_all = pd.concat([df1, df12], axis='columns', keys=['First', 'Second'])
df_final = df_all.swaplevel(axis='columns')[df1.columns[1:]]
df_final[df_final['change this to one of the columns'] != df_final['change this to one of the columns']]
참고 URL : https://stackoverflow.com/questions/20225110/comparing-two-dataframes-and-getting-the-differences
'Programing' 카테고리의 다른 글
rails 4 자산 파이프 라인 공급 업체 자산 이미지가 사전 컴파일되지 않습니다. (0) | 2020.12.05 |
---|---|
Selenium WebDriver에서 브라우저 너비와 높이를 어떻게 설정합니까? (0) | 2020.12.05 |
Swift-추가 인수 호출 (0) | 2020.12.05 |
Eclipse + Spring Boot의 "throw new SilentExitException ()"에서 중단 점 (0) | 2020.12.05 |
TypeScript React 애플리케이션의 PropTypes (0) | 2020.12.05 |