중복 인덱스로 판다 줄 제거
인덱스 값이 중복된 행을 제거하는 방법
아래 DataFrame의 날씨에서는 과학자가 돌아가서 잘못된 행을 편집하는 것이 아니라 파일 끝에 중복 행을 추가하는 방식으로 관찰을 수정하는 경우가 있다.
웹에서 자동화된 기상 데이터를 읽고 있다(관찰은 5분마다 발생하며, 기상 관측소별 월별 파일로 정리).파일을 파싱한 후 DataFrame의 모양:
Sta Precip1hr Precip5min Temp DewPnt WindSpd WindDir AtmPress
Date
2001-01-01 00:00:00 KPDX 0 0 4 3 0 0 30.31
2001-01-01 00:05:00 KPDX 0 0 4 3 0 0 30.30
2001-01-01 00:10:00 KPDX 0 0 4 3 4 80 30.30
2001-01-01 00:15:00 KPDX 0 0 3 2 5 90 30.30
2001-01-01 00:20:00 KPDX 0 0 3 2 10 110 30.28
중복 사례의 예:
import pandas
import datetime
startdate = datetime.datetime(2001, 1, 1, 0, 0)
enddate = datetime.datetime(2001, 1, 1, 5, 0)
index = pandas.DatetimeIndex(start=startdate, end=enddate, freq='H')
data1 = {'A' : range(6), 'B' : range(6)}
data2 = {'A' : [20, -30, 40], 'B' : [-50, 60, -70]}
df1 = pandas.DataFrame(data=data1, index=index)
df2 = pandas.DataFrame(data=data2, index=index[:3])
df3 = df2.append(df1)
df3
A B
2001-01-01 00:00:00 20 -50
2001-01-01 01:00:00 -30 60
2001-01-01 02:00:00 40 -70
2001-01-01 03:00:00 3 3
2001-01-01 04:00:00 4 4
2001-01-01 05:00:00 5 5
2001-01-01 00:00:00 0 0
2001-01-01 01:00:00 1 1
2001-01-01 02:00:00 2 2
그래서 나는 필요하다.df3
결국 다음과 같은 상태가 된다.
A B
2001-01-01 00:00:00 0 0
2001-01-01 01:00:00 1 1
2001-01-01 02:00:00 2 2
2001-01-01 03:00:00 3 3
2001-01-01 04:00:00 4 4
2001-01-01 05:00:00 5 5
행 번호의 열을 추가하는 것이 (라고 생각했다.df3['rownum'] = range(df3.shape[0])
)는 의 모든 값에 대해 맨 아래 행을 선택하는 데 도움이 된다.DatetimeIndex
하지만 난 그 일을 알아내는데만 매달렸어group_by
또는pivot
(혹은 ????) 라는 문장이 효과를 발휘하도록 한다.
나는 판다 지수 자체에 중복된 방법을 사용할 것을 제안한다.
df3 = df3[~df3.index.duplicated(keep='first')]
다른 모든 방법들이 효과가 있는 동안.drop_duplicates
제공된 예에 비해 성능이 훨씬 낮다.게다가, 그룹별 방법이 조금 덜 수행되지만, 나는 복제된 방법이 더 읽기 쉽다고 생각한다.
제공된 샘플 데이터 사용:
>>> %timeit df3.reset_index().drop_duplicates(subset='index', keep='first').set_index('index')
1000 loops, best of 3: 1.54 ms per loop
>>> %timeit df3.groupby(df3.index).first()
1000 loops, best of 3: 580 µs per loop
>>> %timeit df3[~df3.index.duplicated(keep='first')]
1000 loops, best of 3: 307 µs per loop
keep 인수를 다음으로 변경하여 마지막 요소를 유지할 수 있다는 점에 유의하십시오.'last'
.
또한 이 방법은 다음과 함께 작동한다는 점에 유의해야 한다.MultiIndex
또한(폴의 예에 명시된 df1 사용):
>>> %timeit df1.groupby(level=df1.index.names).last()
1000 loops, best of 3: 771 µs per loop
>>> %timeit df1[~df1.index.duplicated(keep='last')]
1000 loops, best of 3: 365 µs per loop
이렇게 하면 인덱스가 DataFrame 열로 추가되고 중복 항목이 삭제된 후 새 열:
df = (df.reset_index()
.drop_duplicates(subset='index', keep='last')
.set_index('index').sort_index())
의 사용법에 유의하십시오..sort_index()
위는 필요에 따라 필요하며 선택 사항이다.
세상에, 이건 정말 간단해!
grouped = df3.groupby(level=0)
df4 = grouped.last()
df4
A B rownum
2001-01-01 00:00:00 0 0 6
2001-01-01 01:00:00 1 1 7
2001-01-01 02:00:00 2 2 8
2001-01-01 03:00:00 3 3 3
2001-01-01 04:00:00 4 4 4
2001-01-01 05:00:00 5 5 5
후속 편집 2013-10-29 상당히 복잡한 경우MultiIndex
, 나는 내가 더 좋아하는 것 같다.groupby
다가오다후세에 대한 간단한 예는 다음과 같다.
import numpy as np
import pandas
# fake index
idx = pandas.MultiIndex.from_tuples([('a', letter) for letter in list('abcde')])
# random data + naming the index levels
df1 = pandas.DataFrame(np.random.normal(size=(5,2)), index=idx, columns=['colA', 'colB'])
df1.index.names = ['iA', 'iB']
# artificially append some duplicate data
df1 = df1.append(df1.select(lambda idx: idx[1] in ['c', 'e']))
df1
# colA colB
#iA iB
#a a -1.297535 0.691787
# b -1.688411 0.404430
# c 0.275806 -0.078871
# d -0.509815 -0.220326
# e -0.066680 0.607233
# c 0.275806 -0.078871 # <--- dup 1
# e -0.066680 0.607233 # <--- dup 2
여기 중요한 부분이 있다.
# group the data, using df1.index.names tells pandas to look at the entire index
groups = df1.groupby(level=df1.index.names)
groups.last() # or .first()
# colA colB
#iA iB
#a a -1.297535 0.691787
# b -1.688411 0.404430
# c 0.275806 -0.078871
# d -0.509815 -0.220326
# e -0.066680 0.607233
중복 제거(키핑 우선)
idx = np.unique( df.index.values, return_index = True )[1]
df = df.iloc[idx]
중복 제거(마지막 보관)
df = df[::-1]
df = df.iloc[ np.unique( df.index.values, return_index = True )[1] ]
테스트: OP 데이터를 사용한 10k 루프
numpy method - 3.03 seconds
df.loc[~df.index.duplicated(keep='first')] - 4.43 seconds
df.groupby(df.index).first() - 21 seconds
reset_index() method - 29 seconds
불행히도, 나는 팬더가 한 마리의 새끼들을 지수에서 떨어뜨리는 것을 허락하지 않는다고 생각한다.나는 다음과 같은 것을 제안하고 싶다.
df3 = df3.reset_index() # makes date column part of your data
df3.columns = ['timestamp','A','B','rownum'] # set names
df3 = df3.drop_duplicates('timestamp',take_last=True).set_index('timestamp') #done!
나와 같은 사람이 팬더 도트 표기법(파이프 등)을 이용한 체인 데이터 조작을 좋아한다면, 다음과 같은 것이 유용할 것이다.
df3 = df3.query('~index.duplicated()')
이를 통해 다음과 같은 체인 문구를 사용할 수 있다.
df3.assign(C=2).query('~index.duplicated()').mean()
같은 실수를 한 경험이 있는데, 모든 df에 다이빙을 해보니 같은 이름의 두 개의 컬럼이 있더라고, 몇 개의 컬럼을 떨어뜨린다고 했으니, 아마도 이것이 이유일 겁니다.
참조URL: https://stackoverflow.com/questions/13035764/remove-pandas-rows-with-duplicate-indices
'programing' 카테고리의 다른 글
Vue 구성 요소의 Vuex 돌연변이에 대한 호출을 테스트하는 방법 (0) | 2022.04.07 |
---|---|
useFooController/useFooHook을 통해 useContext를 사용하는 구성 요소의 렌더 제한 (0) | 2022.04.07 |
외부 JS 스크립트를 VueJS 구성 요소에 추가하는 방법 (0) | 2022.04.06 |
해시/앵커가 있는 페이지에 대한 nuxt 링크 탐색 문제 (0) | 2022.04.06 |
Python 3으로 pip을 설치하는 방법? (0) | 2022.04.06 |