오늘은 pandas 기초에 대해 공부했다.
키워드 : pandas, DataFrame, Series, rows & columns, Indexing, 요약통계, 파일 저장 & 로드
pandas
Python 라이브러리로, 데이터 조작 및 분석을 할 때 사용한다. 데이터 구조를 표현하는 객체인 DataFrame과 Series라는 클래스 객체를 이해해야 pandas를 다루는 데 문제 없을 것이다.
DataFrame과 Series의 이해
DataFrame은 2차원 리스트 구조이며 수학적으로는 행렬로 표현할 수 있다.
- 2차원 리스트 구조 예시 : [[1, 2, 3], [4, 5, 6]]
Series는 1차원 리스트 구조이며 수학적으로는 벡터로 표현할 수 있다.
- 1차원 리스트 구조 예시 : [1, 2, 3]
Series는 row, column의 개념이 없고 DataFrame은 2차원으로 row, column이 존재한다.
그림의 DataFrame 예시는 5 rows 4 columns 구조이다.
이제 코드로 구현해보자.
import pandas as pd
import numpy as np
df = pd.DataFrame()
라이브러리 로드를 먼저 하고 빈 데이터프레임을 하나 생성했다.
df를 5행 4열 데이터프레임으로 구성해보자.
df['약품명'] = ['비타민', 'Omega3', '오메가3', 'Vitamin', 'vitamin']
df['종류'] = ['일반', '전문', '전문', '일반', '일반']
df['제조'] = '국내'
df['가격'] = 3500
dictionary에 데이터를 추가하는 것과 같이 추가한다.
'제조'와 '가격'과 같이 값을 하나만 쓰면 모든 행에 그 값이 들어간다.
이 결과 5행 4열의 아래와 같은 데이터 프레임이 만들어진다.
하나의 컬럼 "종류"만 출력해보면
print(df['종류'])
# 실행 결과
0 일반
1 전문
2 전문
3 일반
4 일반
Name: 종류, dtype: object
1차원 벡터 형태인 시리즈가 출력됨을 확인할 수 있다.
데이터 타입 확인
# type 을 사용해서 데이터의 타입을 출력할 수 있다.
print(type(df['종류']))
print(type(df))
# 실행 결과
<class 'pandas.core.series.Series'>
<class 'pandas.core.series.DataFrame'>
df['종류']와 df의 타입 출력 결과 Series와 DataFrame가 출력된다.
컬럼값 변경하기
df['가격'] = [3500, 3200, 4000, np.nan, 2000]
print(df['가격'])
# 실행 결과
0 3500.0
1 3200.0
2 4000.0
3 NaN
4 2000.0
Name: 가격, dtype: float64
'가격' 컬럼의 데이터가 변경되었다.
nan은 not a number의 약자로 결측치(missing value)를 의미한다.
nan의 데이터 타입은 float이다.
데이터 타입 : object > float > int
print(pd.Series([1, 2, 3])) # int
# 실행 결과
0 1
1 2
2 3
dtype: int64
print(pd.Series([1, 2, np.nan, 4])) # float
# 실행 결과
0 1.0
1 2.0
2 NaN
3 4.0
dtype: float64
결측치의 존재로 1, 2, 4 또한 float로 저장
print(pd.Series([1, 2, np.nan, 4, '문자'])) # object
# 실행 결과
0 1
1 2
2 NaN
3 4
4 문자
dtype: object
'문자'의 존재로 1, 2, nan, 4 또한 object로 저장
컬럼 삭제
# 방법 1 : df.drop(column = '종류')
# 방법 2 : df.drop('종류', axis=1)
df = df.drop('종류', axis=1)
'종류' 컬럼을 삭제했다. drop 메소드 사용 후 df에 다시 할당해 주는 것을 잊지 말자.
여기까지 했다면 현재 DataFrame의 구성은 아래와 같다.
데이터 요약하기
# DataFrame의 정보 확인 : info() 함수 사용
df.info()
# 실행 결과
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 약품명 5 non-null object
1 제조 5 non-null object
2 가격 4 non-null float64
dtypes: float64(1), object(2)
memory usage: 248.0+ bytes
데이터프레임의 전체 정보를 출력하고 있다. 전체 entries, 컬럼 개수, 컬럼별 data type, non-null 데이터 개수 등을 확인할 수 있다.
# 데이터 프레임의 크기를 출력합니다.
# (행, 열)
print(df.shape)
# 실행 결과
(5, 3)
df는 5행 3열임을 shape을 통해 확인
# 데이터의 타입만 봅니다.
print(df.dtypes)
# 실행 결과
약품명 object
제조 object
가격 float64
dtype: object
데이터타입만 확인. 이 정보는 info()를 통해서도 확인이 가능하다.
info()는 괄호를 사용하고, shape와 dtypes는 괄호 없이 동작하는데 차이가 무엇일까?
=> info()는 데이터프레임의 method이며 shape과 dtypes는 property이기 때문이다.
수치형 데이터의 기술통계
print(df.describe())
# 실행 결과
가격
count 4.0
mean 3175.0
std 850.0
min 2000.0
25% 2900.0
50% 3350.0
75% 3625.0
max 4000.0
별도의 파라미터를 설정하지 않았음에도 수치형 데이터인 '가격' 컬럼에 대한 통계만 출력된다.
count : 결측치를 제외한 데이터 개수
mean : 평균
std : 표준편차
min, max : 최솟값, 최댓값
25%, 50%, 75% : 최솟값이 0%, 최댓값이 100%일 때 25%, 50%, 75% 위치 값
- 1사분위수, 2사분위수, 3사분위수
범주형 데이터의 기술통계
print(df.describe(include='object'))
# 실행 결과
약품명 제조
count 5 5
unique 5 1
top 비타민 국내
freq 1 5
describe 메소드의 파라미터로 include='object'를 사용하여 범주형 데이터의 기술통계를 확인한다.
include='O' 과 exclude='number' 또한 같은 결과를 얻는다.
count : 결측치를 제외한 데이터 개수
unique : 유일값 개수
top : 최빈값(가장 개수가 많은 값)
freq : 최빈값의 빈도수
'약품명'은 5개의 모두 다른 데이터를 가지고, '제조'는 5개 데이터 모두 국내라는 점을 생각하며 결과를 이해해보자.
2개 이상의 컬럼 가져오기
파이썬에서 2개 이상의 데이터를 다룰 때는 보통 리스트[]를 사용한다.
print(df[['약품명', '가격']])
# 실행 결과
약품명 가격
0 비타민 3500.0
1 Omega3 3200.0
2 오메가3 4000.0
3 Vitamin NaN
4 vitamin 2000.0
하나의 컬럼을 리스트형으로 사용해서 데이터프레임 형태로 가져오기
print(df[['약품명']])
# 실행 결과
약품명
0 비타민
1 Omega3
2 오메가3
3 Vitamin
4 vitamin
'약품명' 컬럼을 Series가 아닌 DataFrame 형태로 출력하였다.
행을 기준으로 데이터 가져오기
# 인덱스 번호로 첫번째 데이터 가져오기
print(df.loc[0])
# 실행 결과
약품명 비타민
제조 국내
가격 3500.0
Name: 0, dtype: object
# 위에서 3개의 행 데이터 가져오기
print(df.loc[[0, 1, 2]])
# 실행 결과
약품명 제조 가격
0 비타민 국내 3500.0
1 Omega3 국내 3200.0
2 오메가3 국내 4000.0
행과 열을 함께 가져오기
- loc과 iloc을 비교하며 사용
# loc[행, 열]
print(df.loc[0:3, :'제조']) # 0부터 3까지 포함
# 실행 결과
약품명 제조
0 비타민 국내
1 Omega3 국내
2 오메가3 국내
3 Vitamin 국내
# iloc[행index, 열index]
print(df.iloc[0:4, :2]) # 0부터 4-1까지
# 실행 결과
약품명 제조
0 비타민 국내
1 Omega3 국내
2 오메가3 국내
3 Vitamin 국내
# loc[행, 열]
print(df.loc[[0, 1, 2], ['약품명', '가격']])
# 실행 결과
약품명 가격
0 비타민 3500.0
1 Omega3 3200.0
2 오메가3 4000.0
# iloc[행index, 열index]
print(df.iloc[0:3, 0:2])
# 실행 결과
약품명 제조
0 비타민 국내
1 Omega3 국내
2 오메가3 국내
특정 약품명만 가져오기 - indexing 사용
# 파이썬의 정규표현식에서는 |는 or를 &는 and를 의미합니다.
# 여러 검색어로 검색을 한다 가정하고 | 로 검색어를 넣어준다고 생각하면 됩니다.
# str.contains 를 사용해서 약품명을 가져올 수 있습니다.
print(df['약품명'].str.contains('비타|vita'))
# 실행 결과
0 True
1 False
2 False
3 False
4 True
Name: 약품명, dtype: bool
'약품명' 컬럼 데이터 5개 각각에 비타 혹은 vita가 포함되는지 여부에 따라 bool 값이 Series로 출력
이를 활용하여 비타 혹은 vita가 포함되는 약품명을 가진 데이터만 출력
print(df[df['약품명'].str.contains('비타|vita')])
# 이렇게 써도 같은 결과 얻음 print(df[[True, False, False, False, True]])
# 실행 결과
약품명 제조 가격
0 비타민 국내 3500.0
4 vitamin 국내 2000.0
하지만 약품명 'Vitamin'은 대소문자 차이로 False가 되었다.
약품명을 모두 소문자로 만든 컬럼을 추가해보자.
파생변수 만들기
# 약품명을 모두 소문자로 만든 컬럼을 추가
df['약품명2'] = df['약품명'].str.lower()
새로 추가한 '약품명2' 컬럼을 사용해보자.
print(df[df['약품명2'].str.contains('비타|vita')]) # 3행이 나온다
# 실행 결과
약품명 제조 가격 약품명2
0 비타민 국내 3500.0 비타민
3 Vitamin 국내 NaN vitamin
4 vitamin 국내 2000.0 vitamin
이를 그림으로 표현하면 아래와 같다
가격이 특정 조건에 만족하는 데이터 찾기
3500원 이상인 의약품 데이터만 추출해보자.
print(df[df['가격'] >= 3500])
# 실행 결과
약품명 제조 가격 약품명2
0 비타민 국내 3500.0 비타민
2 오메가3 국내 4000.0 오메가3
비교 연산자와 Indexing을 사용하여 원하는 데이터를 출력했다.
정렬하기 - sort_values 메소드 사용
print(df.sort_values(['약품명2','가격'], ascending=[False, True]))
# 실행 결과
약품명 제조 가격 약품명2
2 오메가3 국내 4000.0 오메가3
0 비타민 국내 3500.0 비타민
4 vitamin 국내 2000.0 vitamin
3 Vitamin 국내 NaN vitamin
1 Omega3 국내 3200.0 omega3
약품명2를 기준으로 내림차순 정렬한 상태에서 가격을 기준으로 오름차순 정렬한 결과이다.
약품명2가 서로 같은 데이터 2개의 가격은 2000.0과 NaN인데, 결측치가 숫자보다 더 크다는 규칙이 있기 때문에 오름차순 정렬할 경우 2000.0의 순번이 먼저다.
파일로 저장하고 로드하기
- DataFrame의 to_excel 또는 to_csv 메소드를 통해 xlsx 파일 또는 csv 파일로 저장
- pandas의 read_excel 또는 read_csv 메소드를 통해 xlsx 파일 또는 csv 파일 로드
- 예시로 xlsx 파일로 지금까지 다룬 데이터프레임을 저장하고 로드해본다
# to_excel 를 통해 xlsx 파일로 저장
df.to_excel('pandas_test.xlsx', encoding='cp949', index=False)
df에 한글이 포함되어 있기 때문에 encoding 방식을 cp949로 설정하고
기본 index까지 포함하여 저장하는 것을 방지하기 위해 index=False로 설정한다.
# 저장된 xlsx 파일을 로드하고 출력
df_test = pd.read_excel('pandas_test.xlsx')
print(df_test)
# 실행 결과
약품명 제조 가격 약품명2
0 비타민 국내 3500.0 비타민
1 Omega3 국내 3200.0 omega3
2 오메가3 국내 4000.0 오메가3
3 Vitamin 국내 NaN vitamin
4 vitamin 국내 2000.0 vitamin
df를 저장한 pandas_test를 로드하여 출력해본 결과 잘 출력된 것을 확인할 수 있다.
'AI SCHOOL > TIL' 카테고리의 다른 글
[DAY 13] BeautifulSoup, 쿼리스트링, 슈도코드 등 (0) | 2023.01.11 |
---|---|
[DAY 12] API, 로봇 배제 표준, FinanceDataReader 등 (0) | 2023.01.10 |
[DAY 10] getter, setter, name mangling (0) | 2023.01.06 |
[DAY 9] 클래스, 객체, 메소드 (2) | 2023.01.05 |
[DAY 8] parameter와 argument, lambda, list comprehension (0) | 2023.01.05 |
댓글