저번 시간까지 기본, loc, iloc를 이용해서 데이터를 검색하는 법에 대해 공부했었습니다.
이번 시간부터는 특정한 조건에 해당하는 데이터를 검색하는 방법을 알아보겠습니다.
생각보다 어렵지 않습니다.
import pandas as pd
df = pd.read_excel('score.xlsx', index_col='지원번호')
df
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
1번 채치수 북산고 197 90 85 100 95 85 Python
2번 정대만 북산고 184 40 35 50 55 25 Java
3번 송태섭 북산고 168 80 75 70 80 75 Javascript
4번 서태웅 북산고 187 40 60 70 75 80 NaN
5번 강백호 북산고 188 15 20 10 35 10 NaN
6번 변덕규 능남고 202 80 100 95 85 80 C
7번 황태산 능남고 188 55 65 45 40 35 PYTHON
8번 윤대협 능남고 190 100 85 90 95 95 C#
- 기본적인 조건
예를 들어 키가 185 이상인 조건을 걸어보겠습니다.
df['키'] >= 185
지원번호
1번 True
2번 False
3번 False
4번 True
5번 True
6번 True
7번 True
8번 True
Name: 키, dtype: bool
이렇게 키가 185 이상인 데이터에 대한 True, False가 나옵니다.
이를 이용해서 filt(필터) 변수를 만들어보겠습니다.
filt = df['키'] >= 185
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
1번 채치수 북산고 197 90 85 100 95 85 Python
4번 서태웅 북산고 187 40 60 70 75 80 NaN
5번 강백호 북산고 188 15 20 10 35 10 NaN
6번 변덕규 능남고 202 80 100 95 85 80 C
7번 황태산 능남고 188 55 65 45 40 35 PYTHON
8번 윤대협 능남고 190 100 85 90 95 95 C#
이렇게 하시면 키가 185이상인 데이터를 뽑아올 수 있습니다.
filt에는 위의 True, False 값이 들어가있겠죠?
굳이 filt를 쓰고 싶지 않으시다면,
df[df['키'] >= 185]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
1번 채치수 북산고 197 90 85 100 95 85 Python
4번 서태웅 북산고 187 40 60 70 75 80 NaN
5번 강백호 북산고 188 15 20 10 35 10 NaN
6번 변덕규 능남고 202 80 100 95 85 80 C
7번 황태산 능남고 188 55 65 45 40 35 PYTHON
8번 윤대협 능남고 190 100 85 90 95 95 C#
이렇게 하셔도 됩니다.
만약에 키가 185 미만인 데이터를 검색하고 싶으시면, filt 앞에 ~(물결)을 넣어주시면 됩니다. 그러면 True는 False가 되고, False는 True가 됩니다.
df[~filt] # filt를 역으로 적용
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
2번 정대만 북산고 184 40 35 50 55 25 Java
3번 송태섭 북산고 168 80 75 70 80 75 Javascript
이렇게 하시면 키가 185 미만인 데이터를 검색합니다.
이렇게 정수 형태 뿐만 아니라 다른 형태의 데이터에 대해서도 조건을 추가할 수 있습니다.
filt = df['이름'].isin(['채치수', '강백호'])
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
1번 채치수 북산고 197 90 85 100 95 85 Python
5번 강백호 북산고 188 15 20 10 35 10 NaN
isin에 대한 내용은 뒤에서 설명하니까 지금은 그냥 굳이 정수가 아니어도 된다 정도로 알고 있으시면 될 것 같습니다.
- loc와 응용해서 검색
df.loc[df['키'] >= 185, '수학']
지원번호
1번 100
4번 70
5번 10
6번 95
7번 45
8번 90
Name: 수학, dtype: int64
이렇게 하시면 키가 185 이상인 데이터들에서 수학 과목의 성적을 가지고 옵니다.
df.loc[df['키']>=185, ['수학', '과학', '사회']]
수학 과학 사회
지원번호
1번 100 95 85
4번 70 75 80
5번 10 35 10
6번 95 85 80
7번 45 40 35
8번 90 95 95
이렇게 하시면 키가 185 이상인 데이터들에서 수학, 과학, 사회 과목을 가지고 옵니다.
근데 사실 이런 방법 굳이 loc를 안 써도 되긴 합니다.
df[df['키'] >= 185][['수학','과학','사회']]
이렇게 해도 되긴합니다...ㅎㅎ...
- and, or 조건을 사용하기
키가 185 이상이고, 학교가 북산고인 데이터를 추출해보겠습니다.
filt = (df['키'] >= 185) & (df['학교'] == '북산고')
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
1번 채치수 북산고 197 90 85 100 95 85 Python
4번 서태웅 북산고 187 40 60 70 75 80 NaN
5번 강백호 북산고 188 15 20 10 35 10 NaN
이렇게 &를 사용하시면 됩니다.
당연히 or은 '|' 를 사용해주시면 됩니다. 참고로 and, or 아닙니다!!
filt = (df['키'] < 170) | (df['키'] > 200)
df.loc[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
3번 송태섭 북산고 168 80 75 70 80 75 Javascript
6번 변덕규 능남고 202 80 100 95 85 80 C
이렇게 | 를 사용해주시면 됩니다!
- str를 이용한 조건
이름에 '송'으로 시작하는 데이터를 추출해보겠습니다.
filt = df['이름'].str.startswith('송')
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
3번 송태섭 북산고 168 80 75 70 80 75 Javascript
이렇게 데이터를 string으로 바꿔서 startswith함수를 이용할 수 있습니다.
contains 함수도 쓸 수 있습니다.
filt = df['이름'].str.contains('태') # 태가 들어가는 사람을 뽑음
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
3번 송태섭 북산고 168 80 75 70 80 75 Javascript
4번 서태웅 북산고 187 40 60 70 75 80 NaN
7번 황태산 능남고 188 55 65 45 40 35 PYTHON
이렇게 하시면 이름에 '태'가 들어가는 데이터를 추출할 수 있습니다.
isin에 대해 한 번 알아보겠습니다. isin은 특정 데이터가 안에 있는지를 확인할 수 있습니다.
langs = ['Python', 'Java']
filt = df['SW특기'].isin(langs) #SW특기가 Python이거나 Java인 사람을 뽑음
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
1번 채치수 북산고 197 90 85 100 95 85 Python
2번 정대만 북산고 184 40 35 50 55 25 Java
이렇게 하시면 SW특기가 Python이거나 Java인 데이터를 추출합니다.
근데 여기서 df를 확인하시면,
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
1번 채치수 북산고 197 90 85 100 95 85 Python
2번 정대만 북산고 184 40 35 50 55 25 Java
3번 송태섭 북산고 168 80 75 70 80 75 Javascript
4번 서태웅 북산고 187 40 60 70 75 80 NaN
5번 강백호 북산고 188 15 20 10 35 10 NaN
6번 변덕규 능남고 202 80 100 95 85 80 C
7번 황태산 능남고 188 55 65 45 40 35 PYTHON
8번 윤대협 능남고 190 100 85 90 95 95 C#
7번 황태산의 SW특기는 PYTHON입니다. 즉 isin은 대문자와 소문자를 구별한다는 뜻입니다
여기서 str의 lower()함수를 이용할 수 있습니다.
langs = ['python', 'java']
filt = df['SW특기'].str.lower().isin(langs)
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
1번 채치수 북산고 197 90 85 100 95 85 Python
2번 정대만 북산고 184 40 35 50 55 25 Java
7번 황태산 능남고 188 55 65 45 40 35 PYTHON
이렇게 str.lower()로 모든 SW특기를 소문자로 만든 후, isin을 이용해주시면 됩니다!
만약 제가 SW특기에 Java가 들어가있는 모든 데이터를 추출하려면 어떻게 해야할까요?
제가 데이터를 모두 안다는 가정하에는,
langs = ['Javascript', 'Java']
filt = df['SW특기'].isin(langs)
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
2번 정대만 북산고 184 40 35 50 55 25 Java
3번 송태섭 북산고 168 80 75 70 80 75 Javascript
이렇게 하시면 되지만, 보통 저희는 모든 데이터를 모르기 때문에, isin을 이용할 수 없습니다.
따라서 contains를 이용해야합니다.
filt = df['SW특기'].str.contains('Java')
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
~\AppData\Local\Temp/ipykernel_6808/876867708.py in <module>
1 filt = df["SW특기"].str.contains('Java')
----> 2 df[filt]
~\anaconda3\lib\site-packages\pandas\core\frame.py in __getitem__(self, key)
3446
3447 # Do we have a (boolean) 1d indexer?
-> 3448 if com.is_bool_indexer(key):
3449 return self._getitem_bool_array(key)
3450
~\anaconda3\lib\site-packages\pandas\core\common.py in is_bool_indexer(key)
137 # Don't raise on e.g. ["A", "B", np.nan], see
138 # test_loc_getitem_list_of_labels_categoricalindex_with_na
--> 139 raise ValueError(na_msg)
140 return False
141 return True
ValueError: Cannot mask with non-boolean array containing NA / NaN values
오류가 발생하네요..
NA/NaN 데이터를 처리할 수 없기 때문에 이런 오류가 뜨는 것 같습니다.
어떡할까요?
이때 NA/ NaN 데이터를 따로 처리해주는 인자를 추가해주면 됩니다.
df['SW특기'].str.contains('Java', na=True) #Nan 데이터에 대해서 True로 바꿔줌
지원번호
1번 False
2번 True
3번 True
4번 True
5번 True
6번 False
7번 False
8번 False
Name: SW특기, dtype: bool
이렇게 해주시면, 모든 na를 처리할 때, True로 처리합니다.
아래처럼 쓰시면 됩니다!
filt = df['SW특기'].str.contains('Java', na=False)
df[filt]
이름 학교 키 국어 영어 수학 과학 사회 SW특기
지원번호
2번 정대만 북산고 184 40 35 50 55 25 Java
3번 송태섭 북산고 168 80 75 70 80 75 Javascript
이렇게 na=True/False를 해주시면 na를 True로 처리하던가, False로 처리하던가 둘 중에 하나를 합니다.
1. 요약
조건을 사용하시면 정수뿐만 아니라 다양한 형태의 조건을 걸 수 있습니다.
and, or을 사용하고 싶으면 &와 |를 사용하시면 됩니다.
또한 loc와 연동해서 사용할 수도 있습니다.
string에 대한 특별한 조건을 부여하고 싶으시면 df['column name'].str 를 쓰신 후 string의 함수를 쓰시면 됩니다.
이때, contains는 Na/NaN에 해당하는 값을 처리하지 못하므로 na = True/False를 사용해주셔야 합니다.
감사합니다.
지적 환영합니다.
참고 : 나도코딩
'Python Library > Pandas' 카테고리의 다른 글
[Pandas - Python] Pandas 라이브러리와 데이터 수정(Column과 Row, Cell) (0) | 2022.02.07 |
---|---|
[Pandas - Python] Pandas 라이브러리와 결측치 및 데이터 정렬(fillna, sort_values, sort_index) (0) | 2022.02.07 |
[Pandas - Python] Pandas 라이브러리와 데이터의 선택(loc, iloc) (0) | 2022.02.07 |
[Pandas - Python] Pandas 라이브러리와 데이터 확인 및 선택(기본) (0) | 2022.02.05 |
[Pandas - Python] Pandas 라이브러리와 파일 저장 및 열기(excel, csv, txt) (0) | 2022.02.05 |