두 데이터 프레임을 비교하고 차이점 파악
두 개의 데이터 프레임이 있습니다.예:
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에 있는지 확인하는 것입니다.날짜(인덱스)와 첫 번째 열(바나나, 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
위의 jur의 답변에 대한 ling의 코멘트를 업데이트하고 다른 사람들이 더 쉽게 찾을 수 있는 곳에 배치합니다.
df_diff = pd.concat([df1,df2]).drop_duplicates(keep=False)
다음 데이터 프레임을 사용한 테스트:
# with import pandas as pd
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'],
})
결과:
# for df1
Date Fruit Num Color
0 2013-11-24 Banana 22.1 Yellow
1 2013-11-24 Orange 8.6 Orange
2 2013-11-24 Apple 7.6 Green
3 2013-11-24 Celery 10.2 Green
# for df2
Date Fruit Num Color
0 2013-11-24 Banana 22.1 Yellow
1 2013-11-24 Orange 8.6 Orange
2 2013-11-24 Apple 7.6 Green
3 2013-11-24 Celery 10.2 Green
4 2013-11-25 Apple 22.1 Red
5 2013-11-25 Orange 8.6 Orange
# for df_diff
Date Fruit Num Color
4 2013-11-25 Apple 22.1 Red
5 2013-11-25 Orange 8.6 Orange
데이터 프레임을 사전에 전달하면 중복 항목을 쉽게 삭제할 수 있는 다중 인덱스 데이터 프레임이 생성되고, 데이터 프레임 간의 차이가 있는 다중 인덱스 데이터 프레임이 생성됩니다.
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
# THIS WORK FOR ME
# Get all diferent values
df3 = pd.merge(df1, df2, how='outer', indicator='Exist')
df3 = df3.loc[df3['Exist'] != 'both']
# If you like to filter by a common ID
df3 = pd.merge(df1, df2, on="Fruit", how='outer', indicator='Exist')
df3 = df3.loc[df3['Exist'] != 'both']
그래서 저희가 또.
참고: 메소드는 레이블이 동일한 DataFrame 개체만 비교할 수 있습니다. 즉, 행 레이블과 열 레이블이 동일한 DataFrame을 의미합니다.
df1 = pd.DataFrame({'A': [1, 2, 3],
'B': [4, 5, 6],
'C': [7, np.NaN, 9]})
df2 = pd.DataFrame({'A': [1, 99, 3],
'B': [4, 5, 81],
'C': [7, 8, 9]})
A B C
0 1 4 7.0
1 2 5 NaN
2 3 6 9.0
A B C
0 1 4 7
1 99 5 8
2 3 81 9
df1.compare(df2)
A B C
self other self other self other
1 2.0 99.0 NaN NaN NaN 8.0
2 NaN NaN 6.0 81.0 NaN NaN
뻔했던을 바탕으로 과 같이 합니다.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]
다음에서 기존 데이터 가져오기df2
안으로df1
:
dfe = df2[df2["Fruit"].isin(df1["Fruit"])]
존재하지 않는 데이터 가져오기df2
안으로df1
:
dfn = df2[~ df2["Fruit"].isin(df1["Fruit"])]
둘 이상의 비교를 사용할 수 있습니다.
여기에서 간단한 솔루션을 구축하십시오.
https://stackoverflow.com/a/47132808/9656339
pd.concat([df1, df2]).loc[df1.index.symmetric_difference(df2.index)]
더 빠르고 더 나은 간단한 솔루션이 있으며, 숫자가 서로 다를 경우 수량 차이까지 제공할 수 있습니다.
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
저는 이 방법을 시도해 보았는데 효과가 있었습니다.도움이 되길 바랍니다.
"""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']]
merge outer를 사용하여 값이 null인 왼쪽 외부 값을 찾습니다.
txt1="""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"""
txt2="""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"""
from io import StringIO
f = StringIO(txt1)
df1 = pd.read_table(f,sep =',')
df1.set_index('Date',inplace=True)
f = StringIO(txt2)
df2 = pd.read_table(f,sep =',')
df2.set_index('Date',inplace=True)
df3 =pd.merge(df2, df1, left_index=True, right_index=True, how='outer',
indicator=True
,suffixes=("", "_left")
).query("_merge=='left_only'")
remove_columns=[item for item in df3.columns if '_left' in item]
remove_columns.append('_merge')
df3=df3.drop(columns=remove_columns)
print(df3)
출력:
Date Fruit Num Color
0 2013-11-25 Apple 22.1 Red
1 2013-11-25 Orange 8.6 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
"""
데이터 프레임 행 카운트 간의 차이를 찾을 수 있습니다.
df2.value_counts().sub(df1.value_counts(), fill_value=0)
출력:
Date Fruit Num Color
2013-11-24 Apple 7.6 Green 0.0
Banana 22.1 Yellow 0.0
Celery 10.2 Green -1.0
1000.0 Green 1.0
Orange 8.6 Orange 0.0
2013-11-25 Apple 22.1 Red 1.0
Orange 8.6 Orange 1.0
dtype: float6
언급URL : https://stackoverflow.com/questions/20225110/comparing-two-dataframes-and-getting-the-differences
'itsource' 카테고리의 다른 글
AutoConfigureMockMvc 주석에서 secure=false를 무시하는 Spring Boot 통합 테스트에서 401을 얻습니다. (0) | 2023.07.21 |
---|---|
SpringBoot 구성 요소다중 모듈 프로젝트 스캔 문제 (0) | 2023.07.21 |
행 제한 절을 사용하여 Oracle 쿼리에서 열 복제 (0) | 2023.07.21 |
IPython 노트북에서 코드가 실행되는지 확인하려면 어떻게 해야 합니까? (0) | 2023.07.21 |
매트플로트립에서 X축 레이블을 아래로 이동하지만 X축 눈금은 아래로 이동하지 않습니다. (0) | 2023.07.21 |