데이터 조작(Pandas)
- Pandas 라이브러리
- 데이터 입출력
- Series
- DataFrame
Pandas란?
Pandas는 데이터 분석용 라이브러리로 데이터를 다루는 패키지 중 하나
- 데이터 분석 및 조작을 위한 효율적인 데이터 구조를 제공
- 행과 열로 이루어진 데이터 객체를 다룸
- 안정적으로 대용량 데이터들을 처리
- 누락된 데이터를 유연하게 처리할 수 있는 기능 제공
- SQL과 같은 DBMS처럼 데이터를 합치고 관계연산을 수행할 수 있는 기능 제공 - Pandas의 자료구조
- Series: 1차원 자료구조
- DataFrame: 2차원 자료구조
- Pannel: 3차원 자료구조
import pandas as pd
데이터 입출력 (Pandas로 데이터 읽기)
CSV모듈과 판다스 차이
- CSV 모듈: 전부 출력
- Pandas: 최적화(생략 및 )
CSV파일 읽기
- read_csv() 함수에 확장자(.csv)를 포함하여 파일경로(파일명)을 입력하면, CSV 파일을 읽어와서 Pandas Dataframe으로 변환
[countries.csv]
,country,area,capital,population
KR,Korea,98480,Seoul,51780579
US,USA,9629091,Washington,331002825
JP,Japan,377835,Tokyo,125960000
CN,China,9596960,Beijing,1439323688
RU,Russia,17100000,Moscow,146748600
* 첫 번째 열을 인덱스로 사용키 위해 첫 번째 열의 이름을 생략
import pandas as pd
df=pd.read_csv('countries.csv')
print(df)
'''
출력 결과
Unnamed: 0 country area capital population
0 KR Korea 98480 Seoul 51780579
1 US USA 9629091 Washington 331002825
2 JP Japan 377835 Tokyo 125960000
3 CN China 9596960 Beijing 1439323688
4 RU Russia 17100000 Moscow 146748600
'''
* 인덱스 번호는 판다스가 추가한 열
* 각 열은 서로 다른 속성 레이블 표현
CSV파일 읽기
- read_csv() 함수 옵션
옵션 | 설명 |
path | 파일의 위치(파일명 포함), URL |
sep(또는 delimiter) | 텍스트 데이터를 필드별로 구분하는 문자 |
header | 열 이름이 되는 행을 지정(기본값: 0) header가 없고 첫 행부터 데이터가 있는 경우 None으로 지정 가능 |
index_col | 행 주소가 되는 열을 지정 |
names | 열 이름으로 사용할 문자열 리스트 |
skiprows | 처음 몇 줄을 skip할 것인지 설정(숫자 입력) skip하려는 행의 번호를 담은 리스트로 설정 가능(예: [1,3,5]) |
parse_dates | 날짜 텍스트를 datetime64로 변환할 것인지 설정(기본값: False) |
skip_footer | 마지막 몇 줄을 skip할 것인지 설정(숫자 입력) |
encoding | 텍스트 인코딩 종류 지정(예: 'utf-8') |
- header 옵션 비교
옵션 | 코드 |
0행을 열 지정 (기본 값, header = 0) | df = read_csv(파일) |
1행을 열 지정 (header = 1) | df = read_csv(파일, header = 1) |
행을 열 지정하지 않음 (header=None) | df = read_csv(파일, header = None) |
- index_col 옵션 비교
옵션 | 코드 |
인덱스를 지정하지 않음 (index_col = False) | df = read_csv(파일, index_col = False) |
'a0' 열을 인덱스 지정 (index_col = 'a0') | df = read_csv(파일, index_col = 'a0') |
CSV파일 실습 (파일 읽기)
[read_csv_sample.csv]
c0,c1,c2,c3
0,1,4,7
1,2,5,8
2,3,6,9
import pandas as pd
f='read_csv_sample.csv'
df1=pd.read_csv(f)
print(df1)
print('\n')
df2=pd.read_csv(f, header=None)
print(df2)
print('\n')
df3=pd.read_csv(f, index_col=None)
print(df3)
print('\n')
df4=pd.read_csv(f, index_col='c0')
print(df4)
'''
출력 결과
c0 c1 c2 c3
0 0 1 4 7
1 1 2 5 8
2 2 3 6 9
0 1 2 3
0 c0 c1 c2 c3
1 0 1 4 7
2 1 2 5 8
3 2 3 6 9
c0 c1 c2 c3
0 0 1 4 7
1 1 2 5 8
2 2 3 6 9
c1 c2 c3
c0
0 1 4 7
1 2 5 8
2 3 6 9
'''
- header 옵션이 없으면 CSV 파일의 첫 행의 데이터(c0, c1, c2, c3)가 열 이름이 된다.
- 한편, index_col 옵션을 지정하지 않으면 행 인덱스는 정수 0, 1, 2가 자동으로 지정된다.
- 데이터프레임 df4의 경우 index_col='c0' 옵션을 사용하여 'c0' 열이 행 인덱스가 되는 것을 볼 수 있다.
Excel 파일 읽기
- read_excel() 함수 사용 (사용법은 read_csv()와 유사)
- header, index_col 등 대부분의 옵션을 그대로 사용할 수 있음
CSV, Excel 파일 저장
- to_csv() 함수, to_excel() 함수 사용
(저장할 파일 경로와 파일명을 괄호 안에 입력)
import pandas as pd
data= {'name' : ["Jerry", "Riah", "Paul"],
'algo': ["A", "A+", "B"],
'basic': ["C", "B", "B+"],
'C++': ["B+", "C", "C+"]
}
df= pd.DataFrame(data)
df.set_index('name', inplace=True) #name 열을 인덱스로 지정, inplace=True는 df를 변환
print(df)
df.to_csv('df_sample.csv')
df.to_excel('df_sample.xlsx')
'''
출력 결과
algo basic C++
name
Jerry A C B+
Riah A+ B C
Paul B B+ C+
'''
Pandas - Series
Series는 1차원으로 되어 있으며 value와 index 형태를 갖는 자료구조
- 입력 값: 리스트(List)나 딕셔너리(Dictionary) 같은 Sequence 형태의 데이터
- 각 항목 값(value)에 대으되는 색인(index)으로 구성
- 별도의 색인 값이 없으면 0부터 시작
- 딕셔너리가 입력 값으로 들어갈 경우 key : value 쌍 중 key 값이 색인이 됨
Series의 Index와 Value
import pandas as pd
pandas_series=pd.Series([3000,3200,2700],
index=['2016-11-10','2016-11-11','2016-11-12'])
print(type(pandas_series))
pandas_series
'''
출력 결과
<class 'pandas.core.series.Series'>
2016-11-10 3000
2016-11-11 3200
2016-11-12 2700
dtype: int64
'''
Series를 통해 원하는 위치의 값 출력
- List의 슬라이싱과 동일하게 적용 [start:end:step]
- Index 값/번호를 기준으로 슬라이싱 수행
import pandas as pd
pandas_series=pd.Series([3000,3200,2700],
index=['2016-11-10','2016-11-11','2016-11-12'])
print(pandas_series[1:])
'''
출력 결과
2016-11-11 3200
2016-11-12 2700
dtype: int64
'''
Series(Dictionary) 사용 예제
import pandas as pd
menu={"커피":2000, "라떼":2500, "그린티":3000, "카페모카":3500, "카푸치노":4000}
se=pd.Series(menu)
print(se)
'''
출력 결과
커피 2000
라떼 2500
그린티 3000
카페모카 3500
카푸치노 4000
dtype: int64
'''
print(se.index)
print(se.values)
'''
출력 결과
Index(['커피', '라떼', '그린티', '카페모카', '카푸치노'], dtype='object')
[2000 2500 3000 3500 4000]
'''
Pandas - DataFrame
DataFrame은 2차원의 자료구조로 행(index), 열(column), 값(value)으로 구성
- 입력 값: 리스트(List)나 딕셔너리(Dictionary)같은 Sequence 형태의 데이터
- 별도의 색인 값이 없으면 행과 열은 0부터 시작
- 파이선 데이터 분석에 가장 많이 사용되는 구조
함수 | 기능 | 사용 예 |
DataFrame() | 입력된 값을 DataFrame 구조로 생성 옵션: columns, index 값 |
pd.DataFrame([list]) pd.DataFrame({dict}) |
values | 생성된 DataFrame의 값(valeu) 확인 | 객체.values |
index | 생성된 DataFrame의 행(index) 확인 | 객체.index |
columns | 생성된 DataFrame의 열(columns) 확인 | 객체.columns |
DataFrame 구조 예시
Label명 #0 | Label명 #1 | |
Index명 #0 | Data[0,0] | Data[0,1] |
Index명 #1 | Data[1,0] | Data[1,1] |
DataFrame 생성 예제
import pandas as pd
#DataFrame의 Value, Column, Index를 변수 df에 선언
df = pd.DataFrame([100, 150, 200, 250, 300], columns=['numbers'], index=['a','b','c','d','e'])
df
'''
출력 결과
numbers
a 100
b 150
c 200
d 250
e 300
'''
* 인덱스가 비어있을 경우 자동으로 0, 1, 2 순으로 지정
df.index # DataFrame의 index를 표시
'''
출력 결과
Index(['a', 'b', 'c', 'd', 'e'], dtype='object')
'''
df.columns # DataFrame의 column을 표시
'''
출력 결과
Index(['numbers'], dtype='object')
'''
df.loc['c'] # DataFrame의 index값에서 c에 해당하는 값을 출력 (loc은 인덱스 값 입력)
'''
출력 결과
numbers 200
Name: c, dtype: int64
'''
df.loc['c']
'''
출력 결과
numbers 200
Name: c, dtype: int64
'''
DataFrame 연산
df.sum() #DataFrame의 Value를 모두 더함
'''
출력 결과
numbers 1000
dtype: int64
'''
df.numbers**2 #DataFrame의 numbers칼럼의 값을 제곱함
'''
출력 결과
a 10000
b 22500
c 40000
d 62500
e 90000
Name: numbers, dtype: int64
'''
DataFrame 추가 연산 함수
종류 | 설명 |
sum() | 행, 열 전체 성분의 합 계산 |
mean() | 행, 열 전체 성분의 평균 계산 |
min(), max() | 행, 열 전체 성분의 최소값, 최대값 계산 |
count() | 행, 열 전체 성분의(NaN이 아닌) 값의 개수 계산 |
std(), var() | 행, 열 전체 성분의 표준편차, 분산 계산 |
- axis = 0을 주면 열의 합계를 구할 수 있음
df.sum(axis=0) #열의 합계
'''
출력 결과
one 9.25
two -5.80
dtype: float64
'''
- axis = 1을 주면 행의 합계를 구할 수 있음
df.sum(axis= 1) #행의 합계
'''
출력 결과
a 1.40
b 2.60
c 0.00
d -0.55
dtype: float64
'''
- 특정 열에 대한 합(ex. 열이름 사용)과, 행에 대한 합(ex. 행이름 사용)도 구할 수 있음
df['one'].sum()
#출력 결과: 9.25
df.loc['b'].sum()
#출력 결과: 2.5999999
DataFrame의 Column 값 추가 (index를 맞추지 않으면 오류 발생)
numbers | |
a | 100 |
b | 150 |
c | 200 |
d | 250 |
e | 300 |
df['values'] = (10, 50, 40)
df
'''
출력 결과
ValueError
'''
DataFrame의 Column 값 업데이트
- 데이터 프레임 ⇒ df
- 열 추가 ⇒ df['추가하려는 열 이름'] = 데이터의 값
- 데이터의 값 ⇒ 새로 추가되는 열에 공통적인 값이 일괄적으로 대입
#DataFrame의 index의 값에 일치하는 값을 넣음
df['values'] = pd.DataFrame(['Fourth', 'Second', 'First', 'Fifth', 'Third'], index = ['d', 'b', 'a', 'e', 'c']])
df
'''
출력 결과는 아래의 표와 같습니다.
(위: 기존 데이터프레임)
(아래: 업데이트 된 데이터프레임)
'''
numbers | values | |
a | 100 | 10 |
b | 150 | 50 |
c | 200 | 40 |
d | 250 | 30 |
e | 300 | 60 |
numbers | values | |
a | 100 | First |
b | 150 | Second |
c | 200 | Third |
d | 250 | Fourth |
e | 300 | Fifth |
DataFrame의 Column 삭제
#DataFrame의 values라는 칼럼을 삭제
del df['values']
df
'''
출력 결과는 아래 표와 같습니다.
'''
numbers | |
a | 100 |
b | 150 |
c | 200 |
d | 250 |
e | 300 |
DataFrame의 연산 Join 연산
- Pandas에서 2개의 데이터프레임을 합치기 위해 join, merge, concat 등의 함수 사용 가능
- Pandas에서는 DBMS의 Join의 technique들 중 Inner Join, Outer Join, Let Join, Right Join 지원
- Inner Join: 두 데이터 셋 간의 중복된 요소만 Join
- Outer Join: 두 데이터 셋에 대한 모든 데이터 Join
- Left Join: 왼쪽 데이터 셋을 기준으로 Join
- Right Join: 오른쪽 데이터 셋을 기준으로 Join
#Column A에 1, 2, 3 값 넣음
df_1= pd.DataFrame(['1', '2', '3'], columns= ['A'])
#Column B에 4, 5, 6, 7 값 넣음
df_2= pd.DataFrame(['4', '5', '6', '7'], columns= ['B'])
df= df_1.join(df_2, how= 'outer') #두 개의 DataFrame을 outer join으로 합침
df #합친 DataFrame 출력
'''
출력 결과는 아래의 표와 같습니다.
'''
A | B | |
0 | 1 | 4 |
1 | 2 | 5 |
2 | 3 | 6 |
3 | NaN | 7 |
DataFrame의 행과 열의 위치 변경
- Transpose() 함수
- 데이터에 대한 행과 열의 위치를 변경하려면 transpose() 함수 사용
- 또는 df.T와 같이 기존 객체에 새로운 객체를 할당하는 방법 사용 가능
- 데이터 프레임 ⇒ df
- 기존 객체를 사용 ⇒ df.transpose()
- 기존 객체에 새로운 객체를 할당 ⇒ 변수명2 - 변수명1.T
데이터 프레임(행/열 변경 전) : df | ||||
나이 | 성별 | 키 | 체중 | |
이겨레 | 25 | 남 | 185 | 85 |
조약돌 | 19 | 여 | 163 | 53 |
강산애 | 27 | 남 | 177 | 63 |
df.transpose() 또는 df.t
사용 결과
↓
데이터 프레임(행/열 변경 후) : df | |||
이겨레 | 조약돌 | 강산애 | |
나이 | 25 | 19 | 27 |
성별 | 남 | 여 | 남 |
키 | 185 | 163 | 177 |
체중 | 89 | 53 | 63 |
- Transpose(T)를 이용하여 열과 행을 바꿈
import pandas as pd
import numpy as np
index= pd.data_range('2021/9/1', periods=22) #(21년 9월 1일부터 22일까지 날짜 생성)
print(index)
df=pd.DataFrame(np.random.rand(22,3), index= index, columns= list('ABC'))
df.T
'''
실행 결과
DatetimeIndex(['2021-09-01', '2021-09-02', '2021-09-03', '2021-09-04',
'2021-09-05', '2021-09-06', '2021-09-07', '2021-09-08',
'2021-09-09', '2021-09-10', '2021-09-11', '2021-09-12',
'2021-09-13', '2021-09-14', '2021-09-15', '2021-09-16',
'2021-09-17', '2021-09-18', '2021-09-19', '2021-09-20',
'2021-09-21', '2021-09-22'],
dtype='datetime64[ns]', freq='D')
'''
- Transpose() 함수
- Transpose() 함수인 T를 이용하여 변경했던 결과를 다시 Transpose 함수를 이용하여 열과 행을 바꾸고 새로운 데이터프레임에 저장
#추출된 0.4 이상 값만 표시
df2= df[df['B']> 0.4] #대괄호 안을 비우게 될 경우 해당 부분이 부울값으로 출력
df2
'''
출력 결과
A B C
2021-09-01 0.574418 0.597822 0.136169
2021-09-03 0.380596 0.931151 0.182267
2021-09-04 0.560388 0.729994 0.594196
2021-09-05 0.352283 0.938153 0.391497
2021-09-07 0.091595 0.425597 0.639901
2021-09-08 0.626689 0.872006 0.245318
2021-09-09 0.253668 0.940260 0.629749
2021-09-11 0.079116 0.815708 0.602499
2021-09-14 0.000778 0.457459 0.104200
2021-09-19 0.436945 0.535457 0.844806
2021-09-20 0.650658 0.529130 0.412496
2021-09-21 0.943835 0.765298 0.069714
'''
df2= df.transpose()
df2
'''
출력 결과
2021-09-01 2021-09-03 2021-09-04 2021-09-05 2021-09-07 2021-09-08 2021-09-09 2021-09-11 2021-09-14 2021-09-19 2021-09-20 2021-09-21
A 0.574418 0.380596 0.560388 0.352283 0.091595 0.626689 0.253668 0.079116 0.000778 0.436945 0.650658 0.943835
B 0.597822 0.931151 0.729994 0.938153 0.425597 0.872006 0.940260 0.815708 0.457459 0.535457 0.529130 0.765298
C 0.136169 0.182267 0.594196 0.391497 0.639901 0.245318 0.629749 0.602499 0.104200 0.844806 0.412496 0.069714
'''
DataFrame을 이용한 연산
- DataFrame에서는 데이터 분석을 위한 분석 연산 함수를 지원
- 최댓값, 최솟값, 평균값, 표준편차, 컬럼별 누적합, 통계요약값
- 임의의 Random Number로 구성된 DataFrame 생성하고 연산을 해보자
A | B | C | D | E | |
0 | 0.820356 | 0.521813 | 0.173699 | 0.185170 | 0.750767 |
1 | 0.312579 | 0.018222 | 0.586494 | 0.355398 | 0.116833 |
2 | 0.822653 | 0.652477 | 0.086503 | 0.51542 | 0.408119 |
3 | 0.874400 | 0.238460 | 0.351988 | 0.674635 | 0.252693 |
4 | 0.702337 | 0.439907 | 0.186560 | 0.192786 | 0.015812 |
import pandas as pd
import numpy as np
#random 값을 넣은 DataFrame을 생성
#np.random.randn은 5행 5열의 랜덤 데이터를 생성
#재호출 시 데이터가 변형되므로 주의
df= pd.DataFrame(np.random.randn(5,5))
df.columns=['A', 'B', 'C', 'D', 'E']
df
'''
출력 결과
A B C D E
0 0.820356 0.521813 0.173699 0.185170 0.750767
1 0.312579 0.018222 0.586494 0.355398 0.116833
2 0.822653 0.652477 0.086503 0.551542 0.408119
3 0.874400 0.238460 0.351988 0.674635 0.252693
4 0.702337 0.439907 0.186560 0.192786 0.015812
'''
DataFrame을 이용한 연산- 최댓값
#각 Column별 최댓값 출력
df.max()
'''
출력 결과
A 0.874400
B 0.652477
C 0.586494
D 0.674635
E 0.750767
dtype: float64
'''
DataFrame을 이용한 연산 - 최솟값
#각 Column별 최솟값을 나타냄
df.min()
'''
출력 결과
A 0.312579
B 0.018222
C 0.086503
D 0.185170
E 0.015812
dtype: float64
'''
DataFrame을 이용한 연산 - 평균값
#각 Column별 평균값을 나타냄
df.mean
'''
출력 결과
A 0.706465
B 0.374176
C 0.277049
D 0.391906
E 0.308845
dtype: float64
'''
DataFrame을 이용한 연산 - 표준편차
* 괄호 안에 axis=0 (열) axis=1 (행)을 입력하면 행의 평균값, 표준편차를 얻을 수 있음
#각 Column별 표준편차 값을 나타냄
df.std()
'''
출력 결과
A 0.229040
B 0.249345
C 0.197831
D 0.217451
E 0.287681
dtype: float64
'''
Describe 함수를 이용한 DataFrame의 통계적 분포 확인
#Describe함수를 이용해 DataFrame 데이터 통계 요약값을 표현
df.describe()
'''
출력 결과
A B C D E
count 5.000000 5.000000 5.000000 5.000000 5.000000
mean 0.706465 0.374176 0.277049 0.391906 0.308845
std 0.229040 0.249345 0.197831 0.217451 0.287681
min 0.312579 0.018222 0.086503 0.185170 0.015812
25% 0.702337 0.238460 0.173699 0.192786 0.116833
50% 0.820356 0.439907 0.186560 0.355398 0.252693
75% 0.822653 0.521813 0.351988 0.551542 0.408119
max 0.874400 0.652477 0.586494 0.674635 0.750767
'''
shape 함수를 이용한 DataFrame의 크기(행, 열)
#DataFrame의 크기 (행, 열)
df.shape
'''
출력 결과
(5, 5)
'''
Info 함수를 이용한 DataFrame의 기본적인 확인
#DataFrame의 기본정보 확인
df.info()
'''
출력 결과
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 5 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 A 5 non-null float64
1 B 5 non-null float64
2 C 5 non-null float64
3 D 5 non-null float64
4 E 5 non-null float64
dtypes: float64(5)
memory usage: 328.0 bytes
'''
Group by를 이용한 DataFrame의 그룹화
- Group by는 지정된 group 별로 값들을 분류하여 데이터 분석을 가능하게 함
1. Group by를 사용하기 위해 division 컬럼을 추가하여 그룹 분할
#Group by하기 전 그룹별로 구분하기 위해 division이라는 Column을 생성
df['division']= ['X', 'Y', 'X', 'Y', 'Z']
df
'''
출력 결과
A B C D E division
0 0.820356 0.521813 0.173699 0.185170 0.750767 X
1 0.312579 0.018222 0.586494 0.355398 0.116833 Y
2 0.822653 0.652477 0.086503 0.551542 0.408119 X
3 0.874400 0.238460 0.351988 0.674635 0.252693 Y
4 0.702337 0.439907 0.186560 0.192786 0.015812 Z
'''
2. Group by를 ㅇ사용하여 division 컬럼의 값에 따라 평균값으로 출력
#DataFrame에 Group by를 사용해 column 'division'의 값에 따라 평균값을 산출
df.groupby(['division']).mean()
'''
출력 결과
A B C D E
division
X 0.821505 0.587145 0.130101 0.368356 0.579443
Y 0.593490 0.128341 0.469241 0.515016 0.184763
Z 0.702337 0.439907 0.186560 0.192786 0.015812
'''
본 데이터분석기초실습은 [지능형 데이터 공학 및 응용 연구실 - 경상국립대학교 컴퓨터과학부]에서 수업한 자료를 토대로 정리하여 작성하였습니다.