panda - 데이터 프레임을 다른 데이터 프레임 단위로 행 요소 단위로 필터링합니다.
데이터 프레임이 있습니다.df1
다음과 같이 보입니다.
c k l
0 A 1 a
1 A 2 b
2 B 2 a
3 C 2 a
4 C 2 d
그리고 또 하나의 부름을 받았습니다.df2
예:
c l
0 A b
1 C a
필터링하고 싶습니다.df1
포함되지 않은 값만df2
. 필터링할 값은 다음과 같습니다.(A,b)
그리고.(C,a)
튜플지금까지 제가 적용을 해봤습니다.isin
방법:
d = df[~(df['l'].isin(dfc['l']) & df['c'].isin(dfc['c']))]
제가 보기엔 너무 복잡하네요, 다시 돌아오네요.
c k l
2 B 2 a
4 C 2 d
하지만 기대하고 있습니다.
c k l
0 A 1 a
2 B 2 a
4 C 2 d
를 사용하여 효율적으로 작업할 수 있습니다.isin
원하는 열로 구성된 다중 인덱스 상에서:
df1 = pd.DataFrame({'c': ['A', 'A', 'B', 'C', 'C'],
'k': [1, 2, 2, 2, 2],
'l': ['a', 'b', 'a', 'a', 'd']})
df2 = pd.DataFrame({'c': ['A', 'C'],
'l': ['b', 'a']})
keys = list(df2.columns.values)
i1 = df1.set_index(keys).index
i2 = df2.set_index(keys).index
df1[~i1.isin(i2)]
@IanS의 유사한 솔루션은 열 유형을 가정하지 않기 때문에 개선되었다고 생각합니다(즉, 문자열뿐만 아니라 숫자로도 작동함).
(위의 답변은 편집입니다.다음은 저의 첫 번째 답변이었습니다.)
재미있네요!전에 본 적이 없는 일인데요저는 아마 두 배열을 병합한 다음에 다음과 같은 행을 놓음으로써 해결할 것입니다.df2
정의되어 있습니다.임시 배열을 사용하는 예는 다음과 같습니다.
df1 = pd.DataFrame({'c': ['A', 'A', 'B', 'C', 'C'],
'k': [1, 2, 2, 2, 2],
'l': ['a', 'b', 'a', 'a', 'd']})
df2 = pd.DataFrame({'c': ['A', 'C'],
'l': ['b', 'a']})
# create a column marking df2 values
df2['marker'] = 1
# join the two, keeping all of df1's indices
joined = pd.merge(df1, df2, on=['c', 'l'], how='left')
joined
# extract desired columns where marker is NaN
joined[pd.isnull(joined['marker'])][df1.columns]
임시 배열을 사용하지 않고 이것을 할 수 있는 방법이 있을지 모르지만, 저는 그 방법이 생각나지 않습니다.데이터가 방대하지 않은 한 위의 방법이 빠르고 충분한 답이 될 것입니다.
이는 매우 간단하며 잘 작동합니다.
df1 = df1[~df1.index.isin(df2.index)]
사용하기 & :
더 우아한 방법은 하는 것일 것입니다.left join
의론으로indicator=True
, 그런 다음 모든 행을 필터링합니다.left_only
와 함께query
:
d = (
df1.merge(df2,
on=['c', 'l'],
how='left',
indicator=True)
.query('_merge == "left_only"')
.drop(columns='_merge')
)
print(d)
c k l
0 A 1 a
2 B 2 a
4 C 2 d
indicator=True
추가 열이 있는 데이터 프레임을 반환합니다._merge
각 행을 표시하는 것.left_only, both, right_only
:
df1.merge(df2, on=['c', 'l'], how='left', indicator=True)
c k l _merge
0 A 1 a left_only
1 A 2 b both
2 B 2 a left_only
3 C 2 a both
4 C 2 d left_only
다른 데이터 프레임의 여러 열을 기준으로 데이터 프레임을 필터링하거나 사용자 지정 목록을 기준으로 필터링하려는 경우에는 이 방법이 매우 간단하다고 생각합니다.
df1 = pd.DataFrame({'c': ['A', 'A', 'B', 'C', 'C'],
'k': [1, 2, 2, 2, 2],
'l': ['a', 'b', 'a', 'a', 'd']})
df2 = pd.DataFrame({'c': ['A', 'C'],
'l': ['b', 'a']})
#values of df2 columns 'c' and 'l' that will be used to filter df1
idxs = list(zip(df2.c.values, df2.l.values)) #[('A', 'b'), ('C', 'a')]
#so df1 is filtered based on the values present in columns c and l of df2 (idxs)
df1 = df1[pd.Series(list(zip(df1.c, df1.l)), index=df1.index).isin(idxs)]
다음은 어떻습니까?
df1['key'] = df1['c'] + df1['l']
d = df1[~df1['key'].isin(df2['c'] + df2['l'])].drop(['key'], axis=1)
추가 열을 만들거나 병합하는 것을 피하는 또 다른 방법은 df2에 그룹을 만들어 별개의 (c, l) 쌍을 얻은 다음 이를 사용하여 df1을 필터링하는 것입니다.
gb = df2.groupby(("c", "l")).groups
df1[[p not in gb for p in zip(df1['c'], df1['l'])]]]
이 작은 예를 들어, 실제로 팬더 기반 접근 방식(666 µ 대 1.76ms)보다 조금 더 빨리 실행되는 것처럼 보이지만, 순수 파이썬으로 떨어지고 있기 때문에 더 큰 예에서는 더 느릴 수 있다고 생각합니다.
두 DataFrame을 연결하고 모든 중복을 삭제할 수 있습니다.
df1.append(df2).drop_duplicates(subset=['c', 'l'], keep=False)
출력:
c k l
0 A 1.0 a
2 B 2.0 a
4 C 2.0 d
중복되는 경우에는 이 방법을 사용할 수 없습니다.subset=['c', 'l']
인에df1
.
언급URL : https://stackoverflow.com/questions/33282119/pandas-filter-dataframe-by-another-dataframe-by-row-elements
'programing' 카테고리의 다른 글
MariaDB SQL에서 정규식을 부정하려면 어떻게 해야 합니까? (0) | 2023.10.25 |
---|---|
Dokku에 MariaDB를 설치하려고 합니다. (0) | 2023.10.25 |
Oracle Database Express Edition 11g 설치 문제 (0) | 2023.10.25 |
표에 없는 목록에서 값 선택 (0) | 2023.10.25 |
jQuery Waypoints 오류:스틱 메서드가 없습니다. (0) | 2023.10.25 |