두 데이터 프레임 간의 차이 찾기
나는 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 |