일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- Excel
- SQL
- matplotlib
- GIT
- c#
- PostgreSQL
- google apps script
- Google Excel
- Apache
- django
- Python
- Tkinter
- dataframe
- Github
- list
- Mac
- PySpark
- 파이썬
- Kotlin
- hive
- array
- Google Spreadsheet
- string
- math
- Redshift
- PANDAS
- Java
- numpy
- gas
- Today
- Total
달나라 노트
Python Pandas : DataFrame filtering 본문
DataFrame filtering
엑셀에선 필터 기능을 이용하여 내가 원하는 조건으로 row filter를 걸고 원하는 데이터들만 조작이 가능하죠.Pandas의 DataFrame도 이러한 기능을 제공합니다.
이러한 필터링 기능을 어떻게 이용할 수 있는지 알아봅시다.
먼저 test용 DataFrame을 생성합니다.
import pandas as pd
dict_name = {
'item_id': [1, 2, 3, 4, 5, 6, 7, 8, 9, 10],
'item_name': ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'],
'status': [1, 1, 1, 0, 0, 1, 0, 1, 1, 1]
}
df_name = pd.DataFrame(dict_name)
print(df_name)
print(type(df_name))
- Output
item_id item_name status
0 1 a 1
1 2 b 1
2 3 c 1
3 4 d 0
4 5 e 0
5 6 f 1
6 7 g 0
7 8 h 1
8 9 i 1
9 10 j 1
<class 'pandas.core.frame.DataFrame'>
item_id별 이름과, 상태를 나타내는 DataFrame입니다.
filtering을 알아보기 전에 먼저, DataFrame에서 어떤 컬럼에 존재하는 모든 데이터를 변경하고싶다면 어떻게 하면 될까요?
아래처럼 loc를 이용하면 됩니다.
df_name.loc[:, 'item_name'] = 'z'
print(df_name)
- Output
item_id item_name status
0 1 z 1
1 2 z 1
2 3 z 1
3 4 z 0
4 5 z 0
5 6 z 1
6 7 z 0
7 8 z 1
8 9 z 1
9 10 z 1
결과를 보면 item_name 컬럼의 모든 값이 z로 바뀐 것을 볼 수 있죠.
만약 item_id = 5인 행의 item_name 값을 'z'로 변경하고싶다면 어떻게 하면 될까요?
아래 예시에서처럼 loc의 행 표시 부분에 :(모든 행)이 아닌 조건을 적어주면 됩니다.
df_name.loc[(df_name['item_id'] == 5), ['item_name']] = 'z'
print(df_name)
- Output
item_id item_name status
0 1 a 1
1 2 b 1
2 3 c 1
3 4 d 0
4 5 z 0
5 6 f 1
6 7 g 0
7 8 h 1
8 9 i 1
9 10 j 1
어떻게 위와 같은 일이 가능했을지를 보려면 먼저 조건으로 적힌 'df_name['item_id'] == 5' 이것이 어떤 의미를 가지는지 볼 필요가 있습니다.
test = df_name['item_id'] == 5
print(test)
print(type(test))
- Output
0 False
1 False
2 False
3 False
4 True
5 False
6 False
7 False
8 False
9 False
Name: item_id, dtype: bool
<class 'pandas.core.series.Series'>
조건 부분이었던 'df_name['item_id'] == 5'만 따로 출력을 해 보았더니 위와 같이 index가 있으며
각 index별로 True, False값을 가진 'Series'가 반환되었습니다.
그리고 기존 df_name데이터에서 item_id가 5였던 행의 index가 4였기 때문에
item_id 컬럼의 값이 5인 조건을 만족하여 index 4번은 True로 표시되었습니다.
DataFrame은 위처럼 True, False값을 가진 Series를 loc의 행 표기 부분에 받아 True값으로 표기된 index만 골라서 반환할 수 있습니다.
위 예시에선 True값으로 표시된 index = 4인 행을 추출하였고 그 행의 item_id를 'z'로 바꾸게 된겁니다.
아래의 예시는 위와 동일한 예시이지만 이번에는 filtering의 조건을 다른 변수에 먼저 할당한 후 해당 변수를 loc의 row 부분에 넣었습니다.
결과는 동일하지만 이렇게 조건을 별도의 변수에 할당하여 관리하게된다면 여러 개의 조건을 적용할 때 편리합니다.
con = (df_name['item_id'] == 5)
df_name.loc[con, ['item_name']] = 'z'
print(df_name)
- Output
item_id item_name status
0 1 a 1
1 2 b 1
2 3 c 1
3 4 d 0
4 5 z 0
5 6 f 1
6 7 g 0
7 8 h 1
8 9 i 1
9 10 j 1
여러 개의 조건을 이용하여 filtering하고싶다면 조건끼리 |(or), &(and) 기호를 사용하여 구문해주면 됩니다.
con = (df_name['item_id'] == 5) | (df_name['item_id'] == 6)
df_name.loc[con, ['item_name']] = 'z'
print(df_name)
- Output
item_id item_name status
0 1 a 1
1 2 b 1
2 3 c 1
3 4 d 0
4 5 z 0
5 6 z 1
6 7 g 0
7 8 h 1
8 9 i 1
9 10 j 1
item_id가 5 또는 6인 행의 item_name이 'z'로 바뀌었음을 알 수 있습니다.
con = (df_name['item_id'] >= 5) & (df_name['status'] == 1)
df_name.loc[con, ['item_name']] = 'z'
print(df_name)
- Output
item_id item_name status
0 1 a 1
1 2 b 1
2 3 c 1
3 4 d 0
4 5 e 0
5 6 z 1
6 7 g 0
7 8 z 1
8 9 z 1
9 10 z 1
item_id >= 5이면서 status == 1인 값을 가진 행에 대해 item_name값이 모두 z로 변했음을 알 수 있습니다.
만약 item_id가 1, 3, 5, 7인 행의 item_name만 바꾸고 싶다면 어떻게 하면 될까요?
con = (df_name['item_id'] == 1) | (df_name['item_id'] == 3 | (df_name['item_id'] == 5 | (df_name['item_id'] == 7)
df_name.loc[con, ['item_name']] = 'z'
print(df_name)
- Output
item_id item_name status
0 1 z 1
1 2 b 1
2 3 z 1
3 4 d 0
4 5 z 0
5 6 f 1
6 7 z 0
7 8 h 1
8 9 i 1
9 10 j 1
위처럼 |(or)를 이용해서 각각의 조건을 모두 명시해주는 것도 하나의 방법일 수 있습니다만,
위처럼 진행할 경우 조건이 너무 길어지는 단점이 있죠.
따라서 우리는 Series의 isin을 사용하면됩니다.
df_name.loc[(df_name['item_id'].isin([1, 3, 5, 7])), ['item_name']] = 'z'
print(df_name)
- Output
item_id item_name status
0 1 z 1
1 2 b 1
2 3 z 1
3 4 d 0
4 5 z 0
5 6 f 1
6 7 z 0
7 8 h 1
8 9 i 1
9 10 j 1
위 예시를 보면 item_id가 1, 3, 5, 7인 행의 item_name이 'z'로 잘 바뀌었음을 알 수 있습니다.여기에 사용된 조건을 자세히 봅시다.
test_1 = df_name['item_id']
print(test_1)
print(type(test_1))
test_2 = df_name['item_id'].isin([1, 3, 5, 7])
print(test_2)
print(type(test_2))
- Output
0 1
1 2
2 3
3 4
4 5
5 6
6 7
7 8
8 9
9 10
Name: item_id, dtype: int64
<class 'pandas.core.series.Series'>
0 True
1 False
2 True
3 False
4 True
5 False
6 True
7 False
8 False
9 False
Name: item_id, dtype: bool
<class 'pandas.core.series.Series'>
df_name['item_id'] -> df_name의 item_id컬럼을 추출하여 Series 데이터를 반환합니다.
df_name['item_id'].isin([1, 3, 5, 7]) -> df_name['item_id']에 의해 반환된 Series 데이터에 isin함수를 적용합니다.
isin 함수는 Series에 존재하는 각각의 데이터가 주어진 list에 존재하는지를 체크하며 결과적으로 Boolean Series를 반환합니다.
그래서 test_2를 print한 결과를 보면 item_id값이 1, 3, 5, 7인 행(row)에만 True라고 명시되어있죠.
그리고 이러한 boolean series는 우리가 True값만 조회하려는 loc의 조건 Series로서 사용할 수 있기 때문에 위의 코드가 가능해지는 것입니다.
위 예시와는 조건을 반전하여 item_id가 1, 3, 5, 7가 '아닌' 행의 item_name만 바꾸고 싶다면 조건 앞에 not의 의미를 가지는 기호 ~를 붙여주면 됩니다.
df_name = pd.DataFrame(dict_name)
df_name.loc[(~df_name['item_id'].isin([1, 3, 5, 7])), ['item_name']] = 'z'
print(df_name)
- Output
item_id item_name status
0 1 a 1
1 2 z 1
2 3 c 1
3 4 z 0
4 5 e 0
5 6 z 1
6 7 g 0
7 8 z 1
8 9 z 1
9 10 z 1
위 결과를 보면 item_id가 1, 3, 5, 7이 아닌 행의 item_name컬럼 데이터가 모두 'z'로 바뀌었음을 알 수 있습니다.
'Python > Python Pandas' 카테고리의 다른 글
Python Pandas : DataFrame.join (0) | 2020.11.06 |
---|---|
Python Pandas : DataFrame.loc & DataFrame.iloc (0) | 2020.11.04 |
Python Pandas : merge (2개의 DataFrame join하기. DataFrame join, DataFrame left join, DataFrame right join, DataFrame outer join) (0) | 2020.11.03 |
Python Pandas : DataFrame.groupby (0) | 2020.11.02 |
Python Pandas : DataFrame.assign (0) | 2020.11.02 |