두 데이터 프레임 간의 차이 찾기
나는 df1과 df2 두 개의 데이터 프레임을 가지고 있는데, 여기서 df2는 df1의 부분 집합입니다.두 데이터 프레임의 차이인 새 데이터 프레임(df3)을 어떻게 얻을 수 있습니까?
즉, df1에 df2에 없는 행/열이 모두 있는 데이터 프레임입니까?
을 사용하여drop_duplicates
pd.concat([df1,df2]).drop_duplicates(keep=False)
Update :
The above method only works for those data frames that don't already have duplicates themselves. For example:
df1=pd.DataFrame({'A':[1,2,3,3],'B':[2,3,4,4]})
df2=pd.DataFrame({'A':[1],'B':[2]})
아래와 같이 출력될 것입니다. 이는 잘못된 것입니다.
잘못된 출력:
pd.concat([df1, df2]).drop_duplicates(keep=False)
Out[655]:
A B
1 2 3
올바른 출력
Out[656]:
A B
1 2 3
2 3 4
3 3 4
어떻게 그것을 달성할 수 있을까요?
1: 1: 사용법isin와 함께tuple
df1[~df1.apply(tuple,1).isin(df2.apply(tuple,1))]
Out[657]:
A B
1 2 3
2 3 4
3 3 4
2: 방법 2:merge와 함께indicator
df1.merge(df2,indicator = True, how='left').loc[lambda x : x['_merge']!='both']
Out[421]:
A B _merge
1 2 3 left_only
2 3 4 left_only
3 3 4 left_only
행의 경우, 이것을 사용해 보십시오.Name는 공동 열(열에 이 될 , " " " " " ( " " " ( " " " 을 지정할 수도 있습니다.left_on그리고.right_on):
m = df1.merge(df2, on='Name', how='outer', suffixes=['', '_'], indicator=True)
그indicator=True은 설은다음열추때유용다니합문라는 합니다._merge사이에 모든 변화가 있음에도 불구하고df1그리고.df2"left_only", "right_only" 또는 "both"의 세 가지 가능한 종류로 분류됩니다.
열의 경우 다음을 수행합니다.
set(df1.columns).symmetric_difference(df2.columns)
수락된 답변 방법 1은 내부에 NaN이 있는 데이터 프레임에 대해 작동하지 않습니다.pd.np.nan != pd.np.nan이것이 최선의 방법인지는 잘 모르겠지만, 그것은 피할 수 있습니다.
df1[~df1.astype(str).apply(tuple, 1).isin(df2.astype(str).apply(tuple, 1))]
문자열에 데이터를 캐스트해야 하기 때문에 속도가 느리지만, 이 캐스트 덕분에pd.np.nan == pd.np.nan.
코드를 살펴봅시다.하고, 먼저문에값캐을적스용고합다니하팅열자를 적용합니다.tuple각 행에 대한 함수입니다.
df1.astype(str).apply(tuple, 1)
df2.astype(str).apply(tuple, 1)
덕분에 우리는pd.Series튜플 목록이 있는 개체입니다.각 튜플에는 다음 행이 모두 포함됩니다.df1/df2그러면 저희가 신청합니다.isin에 있는 방법.df1튜플이 "에 합니다.df2는 결는입니다.pd.Series가치가 있는.tuple의 입니다.df1안에 있습니다.df2, 우는결부정으로 결과를 합니다.~ 명서, 터적에 df1간단히 말해서, 우리는 그 행들만 받습니다.df1에 것df2.
보다 읽기 쉽게 하기 위해 다음과 같이 쓸 수 있습니다.
df1_str_tuples = df1.astype(str).apply(tuple, 1)
df2_str_tuples = df2.astype(str).apply(tuple, 1)
df1_values_in_df2_filter = df1_str_tuples.isin(df2_str_tuples)
df1_values_not_in_df2 = df1[~df1_values_in_df2_filter]
import pandas as pd
# given
df1 = pd.DataFrame({'Name':['John','Mike','Smith','Wale','Marry','Tom','Menda','Bolt','Yuswa',],
'Age':[23,45,12,34,27,44,28,39,40]})
df2 = pd.DataFrame({'Name':['John','Smith','Wale','Tom','Menda','Yuswa',],
'Age':[23,12,34,44,28,40]})
# find elements in df1 that are not in df2
df_1notin2 = df1[~(df1['Name'].isin(df2['Name']) & df1['Age'].isin(df2['Age']))].reset_index(drop=True)
# output:
print('df1\n', df1)
print('df2\n', df2)
print('df_1notin2\n', df_1notin2)
# df1
# Age Name
# 0 23 John
# 1 45 Mike
# 2 12 Smith
# 3 34 Wale
# 4 27 Marry
# 5 44 Tom
# 6 28 Menda
# 7 39 Bolt
# 8 40 Yuswa
# df2
# Age Name
# 0 23 John
# 1 12 Smith
# 2 34 Wale
# 3 44 Tom
# 4 28 Menda
# 5 40 Yuswa
# df_1notin2
# Age Name
# 0 45 Mike
# 1 27 Marry
# 2 39 Bolt
Pandas는 이제 데이터 프레임 차이를 수행할 수 있는 새로운 API를 제공합니다.pandas.DataFrame.compare
df.compare(df2)
col1 col3
self other self other
0 a c NaN NaN
2 NaN NaN 3.0 4.0
열 이름이 같거나 다른 단순한 단일 선일 수 있습니다.df2['Name2']에 중복된 값이 포함된 경우에도 작동했습니다.
newDf = df1.set_index('Name1')
.drop(df2['Name2'], errors='ignore')
.reset_index(drop=False)
edit2, 인덱스를 설정할 필요 없이 새로운 솔루션을 찾았습니다.
newdf=pd.concat([df1,df2]).drop_duplicates(keep=False)
네, 저는 최고 투표의 답이 이미 제가 알아낸 것을 포함하고 있다는 것을 발견했습니다.예, 이 코드는 각 두 개의 dfs에 중복이 없는 경우에만 사용할 수 있습니다.
저는 까다로운 방법이 있습니다.먼저 '이름'을 질문에 의해 주어진 두 데이터 프레임의 인덱스로 설정합니다.두 개의 dfs에 동일한 '이름'이 있으므로 '더 큰' dfs에서 '더 작은' dfs 인덱스를 삭제하면 됩니다.여기 코드가 있습니다.
df1.set_index('Name',inplace=True)
df2.set_index('Name',inplace=True)
newdf=df1.drop(df2.index)
판다에는 두 개의 서로 다른 데이터 프레임을 비교하고 데이터 기록에 대해 각 열에서 변경된 값을 반환하는 새로운 방법이 있습니다.
예
첫 번째 데이터 프레임
Id Customer Status Date
1 ABC Good Mar 2023
2 BAC Good Feb 2024
3 CBA Bad Apr 2022
두 번째 데이터 프레임
Id Customer Status Date
1 ABC Bad Mar 2023
2 BAC Good Feb 2024
5 CBA Good Apr 2024
데이터 프레임 비교
print("Dataframe difference -- \n")
print(df1.compare(df2))
print("Dataframe difference keeping equal values -- \n")
print(df1.compare(df2, keep_equal=True))
print("Dataframe difference keeping same shape -- \n")
print(df1.compare(df2, keep_shape=True))
print("Dataframe difference keeping same shape and equal values -- \n")
print(df1.compare(df2, keep_shape=True, keep_equal=True))
결과
Dataframe difference --
Id Status Date
self other self other self other
0 NaN NaN Good Bad NaN NaN
2 3.0 5.0 Bad Good Apr 2022 Apr 2024
Dataframe difference keeping equal values --
Id Status Date
self other self other self other
0 1 1 Good Bad Mar 2023 Mar 2023
2 3 5 Bad Good Apr 2022 Apr 2024
Dataframe difference keeping same shape --
Id Customer Status Date
self other self other self other self other
0 NaN NaN NaN NaN Good Bad NaN NaN
1 NaN NaN NaN NaN NaN NaN NaN NaN
2 3.0 5.0 NaN NaN Bad Good Apr 2022 Apr 2024
Dataframe difference keeping same shape and equal values --
Id Customer Status Date
self other self other self other self other
0 1 1 ABC ABC Good Bad Mar 2023 Mar 2023
1 2 2 BAC BAC Good Good Feb 2024 Feb 2024
2 3 5 CBA CBA Bad Good Apr 2022 Apr 2024
승인된 답변 외에도, 저는 두 개의 데이터 프레임의 2D 세트 차이를 찾을 수 있는 더 넓은 솔루션을 제안하고 싶습니다.index/columns(두 데이터 이름 모두에 대해 일치하지 않을 수 있음).)▁for▁tolerance다▁also▁allows에 대한 허용오차를 설정할 수 .float 비교를 위한 은 데터프사위요비소한를교레용이(임)입니다.np.isclose)
import numpy as np
import pandas as pd
def get_dataframe_setdiff2d(df_new: pd.DataFrame,
df_old: pd.DataFrame,
rtol=1e-03, atol=1e-05) -> pd.DataFrame:
"""Returns set difference of two pandas DataFrames"""
union_index = np.union1d(df_new.index, df_old.index)
union_columns = np.union1d(df_new.columns, df_old.columns)
new = df_new.reindex(index=union_index, columns=union_columns)
old = df_old.reindex(index=union_index, columns=union_columns)
mask_diff = ~np.isclose(new, old, rtol, atol)
df_bool = pd.DataFrame(mask_diff, union_index, union_columns)
df_diff = pd.concat([new[df_bool].stack(),
old[df_bool].stack()], axis=1)
df_diff.columns = ["New", "Old"]
return df_diff
예:
In [1]
df1 = pd.DataFrame({'A':[2,1,2],'C':[2,1,2]})
df2 = pd.DataFrame({'A':[1,1],'B':[1,1]})
print("df1:\n", df1, "\n")
print("df2:\n", df2, "\n")
diff = get_dataframe_setdiff2d(df1, df2)
print("diff:\n", diff, "\n")
Out [1]
df1:
A C
0 2 2
1 1 1
2 2 2
df2:
A B
0 1 1
1 1 1
diff:
New Old
0 A 2.0 1.0
B NaN 1.0
C 2.0 NaN
1 B NaN 1.0
C 1.0 NaN
2 A 2.0 NaN
C 2.0 NaN
여기서 언급한 바와 같이
df1[~df1.apply(tuple,1).isin(df2.apply(tuple,1))]
올바른 솔루션이지만 다음과 같은 경우 잘못된 출력이 생성됩니다.
df1=pd.DataFrame({'A':[1],'B':[2]})
df2=pd.DataFrame({'A':[1,2,3,3],'B':[2,3,4,4]})
이 경우 위의 솔루션은 Empty DataFrame을 제공하며 대신 다음을 사용해야 합니다.concat각 데이터 프레임에서 중복 항목을 제거한 후의 메서드입니다.
사용하다concate with drop_duplicates
df1=df1.drop_duplicates(keep="first")
df2=df2.drop_duplicates(keep="first")
pd.concat([df1,df2]).drop_duplicates(keep=False)
대칭 차이
데이터 프레임 중 하나에만 있고 둘 다에는 없는 행에 관심이 있는 경우 설정된 차이를 찾는 것입니다.
pd.concat([df1,df2]).drop_duplicates(keep=False)
⚠️ 두 데이터 프레임에 중복이 없는 경우에만 작동합니다.
차이 설정 / 관계 대수 차이
이 있다면, 즉 세적차트차관있/경는이에심우이즉, df1-df2또는df1\df2:
pd.concat([df1,df2,df2]).drop_duplicates(keep=False)
⚠️ 두 데이터 프레임에 중복이 없는 경우에만 작동합니다.
이 있을 때 을 처리하는 ▁i다▁used▁dupl한▁when니icates▁with쪽▁handling▁so사습▁there▁i▁had▁on▁issues했용icates있▁dupl▁were▁and서▁at어▁side▁least에를 사용했습니다.Counter.collections더 나은 차이를 위해 양쪽이 동일한 카운트를 갖도록 보장합니다.이렇게 하면 중복 항목이 반환되지 않지만, 양쪽의 개수가 같을 경우 중복 항목이 반환되지 않습니다.
from collections import Counter
def diff(df1, df2, on=None):
"""
:param on: same as pandas.df.merge(on) (a list of columns)
"""
on = on if on else df1.columns
df1on = df1[on]
df2on = df2[on]
c1 = Counter(df1on.apply(tuple, 'columns'))
c2 = Counter(df2on.apply(tuple, 'columns'))
c1c2 = c1-c2
c2c1 = c2-c1
df1ondf2on = pd.DataFrame(list(c1c2.elements()), columns=on)
df2ondf1on = pd.DataFrame(list(c2c1.elements()), columns=on)
df1df2 = df1.merge(df1ondf2on).drop_duplicates(subset=on)
df2df1 = df2.merge(df2ondf1on).drop_duplicates(subset=on)
return pd.concat([df1df2, df2df1])
> df1 = pd.DataFrame({'a': [1, 1, 3, 4, 4]})
> df2 = pd.DataFrame({'a': [1, 2, 3, 4, 4]})
> diff(df1, df2)
a
0 1
0 2
기존 데이터 프레임의 인덱스를 변경할 필요가 없는 nice @liangli 솔루션의 약간 변형:
newdf = df1.drop(df1.join(df2.set_index('Name').index))
인덱스별 차이 찾기.df1이 df2의 하위 집합이고 하위 집합을 설정할 때 인덱스가 전달된다고 가정합니다.
df1.loc[set(df1.index).symmetric_difference(set(df2.index))].dropna()
# Example
df1 = pd.DataFrame({"gender":np.random.choice(['m','f'],size=5), "subject":np.random.choice(["bio","phy","chem"],size=5)}, index = [1,2,3,4,5])
df2 = df1.loc[[1,3,5]]
df1
gender subject
1 f bio
2 m chem
3 f phy
4 m bio
5 f bio
df2
gender subject
1 f bio
3 f phy
5 f bio
df3 = df1.loc[set(df1.index).symmetric_difference(set(df2.index))].dropna()
df3
gender subject
2 m chem
4 m bio
데이터 프레임 정의:
df1 = pd.DataFrame({
'Name':
['John','Mike','Smith','Wale','Marry','Tom','Menda','Bolt','Yuswa'],
'Age':
[23,45,12,34,27,44,28,39,40]
})
df2 = df1[df1.Name.isin(['John','Smith','Wale','Tom','Menda','Yuswa'])
df1
Name Age
0 John 23
1 Mike 45
2 Smith 12
3 Wale 34
4 Marry 27
5 Tom 44
6 Menda 28
7 Bolt 39
8 Yuswa 40
df2
Name Age
0 John 23
2 Smith 12
3 Wale 34
5 Tom 44
6 Menda 28
8 Yuswa 40
두 가지 차이점은 다음과 같습니다.
df1[~df1.isin(df2)].dropna()
Name Age
1 Mike 45.0
4 Marry 27.0
7 Bolt 39.0
위치:
df1.isin(df2)반합니다환을다▁in의 합니다.df1에도 .df2.~(요소별 NOT)는를 부정하기 에, 는 앞요있는는논에부결다다가로과같니요져옵소를은음 (요소별 논리 NOT)에 있는 요소들을df1에 없는df2–둘 사이의 차이..dropna()이 있는 합니다.NaN하는 것
참고 이것은 다음 경우에만 작동합니다.
len(df1) >= len(df2).한다면df2.df1은 다음과 같은로 할 수 .df2[~df2.isin(df1)].dropna()
나는 찾았습니다.deepdiff라이브러리는 다른 세부사항이 필요하거나 주문 문제가 있는 경우 데이터 프레임으로 잘 확장되는 훌륭한 도구입니다.디핑을 실험할 수 있습니다.to_dict('records'),to_numpy()기타 수출:
import pandas as pd
from deepdiff import DeepDiff
df1 = pd.DataFrame({
'Name':
['John','Mike','Smith','Wale','Marry','Tom','Menda','Bolt','Yuswa'],
'Age':
[23,45,12,34,27,44,28,39,40]
})
df2 = df1[df1.Name.isin(['John','Smith','Wale','Tom','Menda','Yuswa'])]
DeepDiff(df1.to_dict(), df2.to_dict())
# {'dictionary_item_removed': [root['Name'][1], root['Name'][4], root['Name'][7], root['Age'][1], root['Age'][4], root['Age'][7]]}
또 다른 가능한 해결책은 다음과 같습니다.
df1[np.all(~np.all(df1.values == df2.values[:, None], axis=2), axis=0)]
출력:
Name Age
1 Mike 45
4 Marry 27
7 Bolt 39
람 함 를 수 필 있 수 니 다 습으로 행을 수 ._merge 치“left_only” 줄보꿰다의 .df1에서빠에서 빠진 .df2
df3 = df1.merge(df2, how = 'outer' ,indicator=True).loc[lambda x :x['_merge']=='left_only']
df
사용해 보십시오.df_new = df1.merge(df2, how='outer', indicator=True).query('_merge == "left_only"').drop('_merge', 1)
df1에는 있지만 df2에는 없는 값이라는 차이를 가진 새 데이터 프레임이 생성됩니다.
언급URL : https://stackoverflow.com/questions/48647534/find-difference-between-two-data-frames
'programing' 카테고리의 다른 글
| 필드를 com.sun.proxy로 설정할 수 없습니다.$프록시 (0) | 2023.09.10 |
|---|---|
| 단일 쿼리에서 모든 테이블 공간 이름, 할당된 크기, 여유 크기, 용량을 가져오는 방법? (0) | 2023.09.05 |
| 부트스트랩 4에서 드롭다운의 화살표를 제거하는 방법은 무엇입니까? (0) | 2023.09.05 |
| PowerShell에서 데이터 세트를 순환하려면 어떻게 해야 합니까? (0) | 2023.09.05 |
| AJAX 호출에 의해 삽입된 IE 8에서 HTML5 요소를 "활성화"하는 방법은 무엇입니까? (0) | 2023.09.05 |
