pandas 쿡북
Chris Albon 과 비슷하게 적어보려고 함
pandas python
Tip1 : dataframe 에서 중복되는 data의 Unique한 값 목록을 추출할 때
시뮬레이션 데이터 세트 만들기
- 예를 들면, 다음과 같은 도서관 대출 목록 dataframe 이 있다고 하자
1
2
3
4
5
6
7
8
# 예제용 dataframe 만들기
import pandas as pd
raw_data = {'제목': ['Unity', 'Rust', 'Rust2', 'Java', 'Java1', 'Java6'],
'대출기관': ['방배도서관', '방배도서관', '동작도서관', '동작도서관', '동작도서관', '동작도서관'],
'대여자': ['철수', '철수', '영희', '영희', '영희', '영희'],
'반납일': ['2022-09-15', '2022-09-15', '2022-09-15', '2022-10-01', '2022-10-01', '2022-10-03'],
}
df1 = pd.DataFrame(raw_data)
인덱스 | 제목 | 대출기관 | 대여자 | 반납일 |
---|---|---|---|---|
0 | Unity | 방배도서관 | 철수 | 2022-09-15 |
1 | Rust | 방배도서관 | 철수 | 2022-09-15 |
2 | Rust2 | 동작도서관 | 영희 | 2022-09-15 |
3 | Java | 동작도서관 | 영희 | 2022-10-01 |
4 | Java1 | 동작도서관 | 영희 | 2022-10-01 |
5 | Java6 | 동작도서관 | 영희 | 2022-10-03 |
문제 상황 정리
- 도서 반납 일정을 짜기 위해 위의 도서관 대출 목록을 자료로 반납일을 출력하고 싶다
- 즉, 중복되는 데이터가 존재하는
반납일
열에서 (2022-09-15
,2022-10-01
,2022-10-03
) Unique 한 데이터가 3개 있다 - 즉,
반납일 목록
과반납일에 가야하는 대출기관 목록
및몇권을 반납해야는지
를 연계하여 출력하고 싶다 - 한데 자세히 보니
2022-09-15
일 에는 도서관을 2군데(방배도서관
,동작도서관
) 가야 한다 - 따라서, 위 데이터 세트에서 출력되어야 하는 데이터 형식은 다음과 같다
- 구체적으로 DataFrame 형식으로 출력하고 싶다
인덱스 | 반납일 | 대출기관 | 권수 |
---|---|---|---|
0 | 2022-09-15 | 방배도서관 | 2 |
1 | 2022-09-15 | 동작도서관 | 1 |
2 | 2022-10-01 | 동작도서관 | 2 |
3 | 2022-10-03 | 동작도서관 | 1 |
방법 분석
- 우선, 제일먼저 생각나는 방법은 List 구조에서 중복 데이터를 제거하고 Unique한 값들을 추출하는 방법들이다
-
파이썬 리스트 중복제거
로 찾아보면 여러가지가 있다. 아래는 한가지 예.
-
- 하지만, Pandas에서는 위의 방법보다 훨씬 간단한 방법이 있다
- Find Unique Values In Pandas Dataframes, chrisalbon.com
- 이 방법을 적용해보면 결과는 다음과 같다
1 2
print(df1["반납일"].unique()) # ['2022-09-15', '2022-10-01', '2022-10-03']
- 그런데, 위 방법보다도 이 상황에 더 알맞은 다른 방법이 있다
선택된 방법과 결과 확인
- DataFrame의 method중에 Unique한 목록을 뽑아내는 용도로
value_counts
도 사용가능하다1 2 3 4 5 6 7 8 9 10 11 12 13 14
df1.loc[:,['반납일', '대출기관']].value_counts() """ print 출력 반납일 대출기관 2022-09-15 방배도서관 2 2022-10-01 동작도서관 2 2022-09-15 동작도서관 1 2022-10-03 동작도서관 1 dtype: int64 """ df1.value_counts(subset=["반납일", "대출기관"]) """ value_counts의 파라미터를 사용하면 df1을 사전에 가공할 필요가 없다 출력결과는 위와 동일하다 """
- 응? 출력된 모습만 보면 이미 원하는 최종결과를 뽑아낸 것 같지만 착각이다
-
value_counts api 문서를 보면 결과값을
Series
로 반환한다 - 위 문서에도 나와있지만, 반환된
Series
Object는 기본적으로 제공된subset
으로 이루어진MultiIndex
를 가진다 - 즉,
반납일
,대출기관
부분이 인덱스이고 숫자를 센 부분이value
이다
-
value_counts api 문서를 보면 결과값을
- 이 상태에서 우리가 원하는 최종 결과는 추가적인 method를 통해 다음과 같이 만들수 있다
1
2
3
4
5
6
7
8
9
10
11
12
13
df1_result = df1.value_counts(subset=['반납일', '대출기관'])\
.reset_index(name='권수')\
.sort_values(by=['반납일'], ascending=[True], ignore_index=True)
""" df1_result 출력 결과
반납일 대출기관 권수
0 2022-09-15 방배도서관 2
1 2022-09-15 동작도서관 1
2 2022-10-01 동작도서관 2
3 2022-10-03 동작도서관 1
** Line Continuation 사용시에 PEP 8 을 준수 하기 위해 `.` operator의 위치를 맞춘다
참조(https://peps.python.org/pep-0008/#should-a-line-break-before-or-after-a-binary-operator)
"""
Method Chaining 분석
- 위의 Method chaining 에서 중요한 부분을 하나씩 알아보자
- 버전별 차이가 다소 존재하므로 현재 사용하고 있는 버전의 매뉴얼을 참조하자 (아래 링크는 최신버전으로 걸어놓았다)
- Pandas 버전 확인 방법
- conda의 경우 : conda 환경에서
conda list pandas
- pip의 경우 : 가상환경에서
pip show pandas
- conda의 경우 : conda 환경에서
- Pandas 버전 확인 방법
DataFrame.value_count()
- 위에서 확인된 바와 갈이 DataFrame.value_count() 의 결과로 원하는 결과의
재료
가 이미 준비되었다 - subset 파라미터로 갯수를 계산할 고유한 조합 (Unique combinations)의 기준을 정한다
- 결과는 Series로 반환 된다
Series.reset_index()
- Series.reset_index() 로 MultiIndex부분을 일반적인 Column으로 변경한다
- name 파라미터로 Series의 Value 부분에 컬럼 이름을 줄 수 있다
- 결과는 상황에 따라 Dataframe 혹은 Series로 반환된다. 위 경우에는 DataFrame 이다
DataFrame.sort_values()
- 가까운 날짜부터 차례로 정렬되는 것이 일정짜기에 좋으므로
반납일
기준으로 배열한다 - 정렬 기준이 여러개 일수 있으므로
by
,ascending
은 리스트를 받는다 -
ignore_index
옵션으로 sort 이전의 기존 인덱스를 무시하고 정렬순으로 다시 0 부터 인덱스를 부여한다