일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | 7 |
8 | 9 | 10 | 11 | 12 | 13 | 14 |
15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 | 23 | 24 | 25 | 26 | 27 | 28 |
29 | 30 | 31 |
- 티스토리챌린지
- Python
- Apple
- 해외주식
- 공모주
- SK텔레콤
- esp32
- 현대통신
- 힐스테이트 광교산
- homebridge
- 나스닥
- 월패드
- Espressif
- 국내주식
- 애플
- 매터
- 홈네트워크
- MQTT
- 미국주식
- 파이썬
- raspberry pi
- Home Assistant
- 오블완
- 코스피
- matter
- RS-485
- ConnectedHomeIP
- Bestin
- cluster
- 배당
- Today
- Total
YOGYUI
pandas - 중복된 요소 넘버링하기 본문
pandas - numbering duplicated elements
pandas 데이터프레임(DataFrame) 객체의 특정 열(column)의 값들이 중복될 경우, 중복된 행(row)에 고유번호를 순차적으로 매겨보자 (간단한 개념인데 한국말로 정리하는게 더 어렵다)
1. 데이터 준비하기
간단하게 가상의 구매 목록을 하나 만들어주자
from datetime import date
import pandas as pd
df = pd.DataFrame([
{'구매일': date(2021,12,1), '품목': '계란', '수량': 1, '가격': 3000},
{'구매일': date(2021,12,1), '품목': '라면', '수량': 1, '가격': 1000},
{'구매일': date(2021,12,1), '품목': '우유', '수량': 2, '가격': 2500},
{'구매일': date(2021,12,4), '품목': '케찹', '수량': 1, '가격': 2000},
{'구매일': date(2021,12,4), '품목': '마요네즈', '수량': 1, '가격': 2000},
{'구매일': date(2021,12,5), '품목': '두부', '수량': 1, '가격': 1000},
{'구매일': date(2021,12,8), '품목': '쌀', '수량': 1, '가격': 10000},
{'구매일': date(2021,12,8), '품목': '고추장', '수량': 1, '가격': 4000},
{'구매일': date(2021,12,8), '품목': '된장', '수량': 1, '가격': 3500},
{'구매일': date(2021,12,8), '품목': '커피', '수량': 1, '가격': 20000},
{'구매일': date(2021,12,10), '품목': '콜라', '수량': 1, '가격': 1000},
{'구매일': date(2021,12,10), '품목': '사이다', '수량': 1, '가격': 1000}
])
df = df[['구매일', '품목', '수량', '가격']]
In [1]:df
Out[1]:
구매일 품목 수량 가격
0 2021-12-01 계란 1 3000
1 2021-12-01 라면 1 1000
2 2021-12-01 우유 2 2500
3 2021-12-04 케찹 1 2000
4 2021-12-04 마요네즈 1 2000
5 2021-12-05 두부 1 1000
6 2021-12-08 계란 1 3000
7 2021-12-08 계란 1 3000
8 2021-12-08 계란 1 3000
9 2021-12-08 계란 1 3000
10 2021-12-10 계란 1 3000
11 2021-12-10 계란 1 3000
'구매일' 칼럼에 중복이 발생되게 데이터프레임을 만들었다 (장보러갔을 때 1회당 여러 제품을 사는 상황을 가정)
2. 값 중복 확인
DataFrame, Series 객체의 duplicated 메서드를 사용하면 값 중복 여부를 확인할 수 있다
In [2]: df.duplicated('구매일', keep='first')
Out[2]:
0 False
1 True
2 True
3 False
4 True
5 False
6 False
7 True
8 True
9 True
10 False
11 True
dtype: bool
keep 인자는 'first', 'last', False 셋 중 하나로, 중복되는 데이터 중 첫번째/마지막 데이터를 중복되지 않은 것으로 판단할지 여부를 결정한다
In [3]:df.duplicated('구매일', keep='last')
Out[3]:
0 True
1 True
2 False
3 True
4 False
5 False
6 True
7 True
8 True
9 False
10 True
11 False
dtype: bool
In [4]: df.duplicated('구매일', keep=False)
Out[4]:
0 True
1 True
2 True
3 True
4 True
5 False
6 True
7 True
8 True
9 True
10 True
11 True
dtype: bool
drop_duplicates 메서드를 사용하면 중복된 데이터를 제거할 수 있다
이 포스팅에서 원하는 작업은 아니므로 패스~
3. 중복된 행 개수 구하기
중복된 행의 개수를 구해보자
for문을 사용하는 알고리즘으로 구현하면 다음과 같다
temp = None
result = []
for i in range(len(df)):
if temp is None:
temp = {df.iloc[i]['구매일']: 1}
result.append(temp)
else:
if list(temp.keys())[0] == df.iloc[i]['구매일']:
temp[df.iloc[i]['구매일']] += 1
else:
temp = {df.iloc[i]['구매일']: 1}
result.append(temp)
(급하게 짜다보니 너무 허접한 경항이?! ㅎㅎ)
In [5]: result
Out[5]:
[{datetime.date(2021, 12, 1): 3},
{datetime.date(2021, 12, 4): 2},
{datetime.date(2021, 12, 5): 1},
{datetime.date(2021, 12, 8): 4},
{datetime.date(2021, 12, 10): 2}]
중복된 '구매일'에 대한 행들의 개수가 각각 3/2/1/4/2개로 제대로 카운팅되었다
pandas DataFrame 객체의 groupby 메서드를 활용하면 위 과정을 간단하게 구현할 수 있다
(SQL 개발자라면 너무나 익숙한 ㅎㅎ)
In [6]: df.groupby('구매일')
Out[6]: <pandas.core.groupby.generic.DataFrameGroupBy object at 0x000001D93FC239E8>
groupby를 호출하면 DataFrameGroupBy 객체가 생성이 되는데, groupby 객체에 적용할 수 있는 메서드가 굉장히 많으니 한번 살펴보길 바란다
https://pandas.pydata.org/docs/reference/groupby.html
여기서는 집계된 그룹들의 개수를 합산하기 위해 count 메서드를 호출하면
In [7]: df.groupby('구매일').count()
Out[7]:
품목 수량 가격
구매일
2021-12-01 3 3 3
2021-12-04 2 2 2
2021-12-05 1 1 1
2021-12-08 4 4 4
2021-12-10 2 2 2
구매일을 기준으로 각 열별로 레코드가 몇 개씩인지를 합산해준다 (SQL GROUP BY COUNT랑 동일)
In [8]: df.groupby('구매일').count()[df.columns[1]]
Out[8]:
구매일
2021-12-01 3
2021-12-04 2
2021-12-05 1
2021-12-08 4
2021-12-10 2
Name: 품목, dtype: int64
요렇게 깔끔하게 정리할 수도 있다
4. 중복되는 데이터에 고유번호 부여
for문 활용 알고리즘으로 구현하고자 한다면
index = 0
temp = None
result = []
for i in range(len(df)):
if temp is None:
temp = df.iloc[i]['구매일']
index = 1
else:
if temp == df.iloc[i]['구매일']:
index += 1
else:
temp = df.iloc[i]['구매일']
index = 1
result.append(index)
In [9]: result
Out[9]: [1, 2, 3, 1, 2, 1, 1, 2, 3, 4, 1, 2]
앞서 살펴본 groupby를 활용하면 한줄로 구현할 수 있다
In [10]: df.groupby('구매일').cumcount() + 1
Out[10]:
0 1
1 2
2 3
3 1
4 2
5 1
6 1
7 2
8 3
9 4
10 1
11 2
dtype: int64
그룹화된 객체에 cumcount 메서드 (cumulative count)를 호출하면 중복되는 요소별로 순차적으로 카운팅한 Series 객체를 얻을 수 있다 (zero-based이므로 1을 더해줬다)
끝~!
[참고]
https://stackoverflow.com/questions/39481609/number-duplicates-sequentially-in-pandas-dataframe
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.duplicated.html
https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.groupby.html
https://pandas.pydata.org/docs/reference/api/pandas.core.groupby.DataFrameGroupBy.cumcount.html
'Software > Python' 카테고리의 다른 글
Pyppeteer - Chromium 다운로드 시 SSLCertVerificationError 발생할 경우 (0) | 2022.01.04 |
---|---|
2022년 공휴일을 알아보자 (feat. 공공데이터포털) (0) | 2021.12.22 |
pandas - 데이터프레임 데이터형(dtype) 확인 (0) | 2021.09.21 |
PyQt5 - QMenuBar location in macOS (0) | 2021.09.17 |
PyQt5 - QtWebEngine Chromium Version 확인하기 (0) | 2021.09.10 |