데이터 분석
데이터 처리를 위한 Pandas
창민이 개발일지
2022. 6. 17. 10:57
데이터 처리를 위한 Pandas
In [1]:
import pandas as pd
▣ Pandas
- 판다스(Pandas)는 관계형 또는 분류된 데이터 처리를 위한 파이썬 라이브러리.
- 파이썬을 이용한 데이터 분석과 같은 작업에서 필수 라이브러리.
- Pandas는 행 및 열 레이블이 포함된 데이터 처리에 적합함. ex) 주식데이터, 년도별 사망자수 등
Series
- 1차원 배열의 값(value)에 각 값에 대응되는 인덱스(index)을 부여할 수 있는 구조.
In [3]:
sr = pd.Series([17000, 18000, 5000],index=['피자','치킨','맥주'])
sr
Out[3]:
피자 17000
치킨 18000
맥주 5000
dtype: int64
In [4]:
print(sr.index, sr.values)
Index(['피자', '치킨', '맥주'], dtype='object') [17000 18000 5000]
데이터프레임
데이터프레임은 2차원 배열 구조로, 행방향 인덱스와 열방향 인덱스가 존재하는 구조 시리즈가 인덱스와 값으로 구성된다면, 데이터프레임은 열까지 추가되어 열(column), 인덱스(index), 값(value)으로 구성됨.
In [6]:
values = [[1,2,3],[4,5,6],[7,8,9]]
index = ['one','two','three']
columns = ['A','B','C']
df = pd.DataFrame(values,index,columns)
print(df.values)
print(df.index)
print(df.columns)
print(df.shape)
[[1 2 3]
[4 5 6]
[7 8 9]]
Index(['one', 'two', 'three'], dtype='object')
Index(['A', 'B', 'C'], dtype='object')
(3, 3)
In [7]:
df.index = ["first","second","third"]
df.columns = ['1','2','3']
df
Out[7]:
123firstsecondthird
1 | 2 | 3 |
4 | 5 | 6 |
7 | 8 | 9 |
3) 데이터프레임의 생성
데이터프레임은 리스트(List), 시리즈(Series), 딕셔너리(dict), Numpy의 ndarrays, 또 다른 데이터프레임으로 생성할 수 있습니다. 여기서는 리스트와 딕셔너리를 통해서 데이터프레임을 생성 해보겠습니다.
In [94]:
# - List로 생성 -
Image("Image/pandas_dataframe_list.png")
Out[94]:

In [14]:
# - Dictionary로 생성 -
data = {
'학번':['1000','2000','3000','4000','5000'],
'이름':["창민","영준","진우","인영","진표"],
'점수':[90,80,70,60,50]}
df = pd.DataFrame(data)
df
Out[14]:
학번이름점수01234
1000 | 창민 | 90 |
2000 | 영준 | 80 |
3000 | 진우 | 70 |
4000 | 인영 | 60 |
5000 | 진표 | 50 |
4) 데이터프레임 조회하기
아래의 명령어는 데이터프레임에서 원하는 구간만 확인하기 위한 명령어로서 유용하게 사용됩니다.
df.head(n) - 앞 부분을 n개만 보기 df.tail(n) - 뒷 부분을 n개만 보기 df['열이름'] - 해당되는 열을 확인
In [96]:
df.head(3)
Out[96]:
학번이름점수012
1000 | 창민 | 90 |
2000 | 영준 | 80 |
3000 | 진우 | 70 |
In [97]:
df.tail(2)
Out[97]:
학번이름점수34
4000 | 인영 | 60 |
5000 | 진표 | 50 |
In [98]:
df['이름']
Out[98]:
0 창민
1 영준
2 진우
3 인영
4 진표
Name: 이름, dtype: object
4.1) 숫자형 특성의 요약 정보 출력(describe( ))
count : null을 제외한 행의 갯수
mean : 전체 평균
min : 최소값
max : 최대값
std : 표준편차(퍼져 있는 정도)
%. : 백분율이 속하는 하위 부분의 값
In [6]:
df.describe()
Out[6]:
점수countmeanstdmin25%50%75%max
5.000000 |
70.000000 |
15.811388 |
50.000000 |
60.000000 |
70.000000 |
80.000000 |
90.000000 |
4.2) 데이터프레임 정보 조회
In [5]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
학번 5 non-null object
이름 5 non-null object
점수 5 non-null int64
dtypes: int64(1), object(2)
memory usage: 200.0+ bytes
4.3) 데이터프레임 특정 행 또는 열 조회
In [2]:
# - Dictionary로 생성 -
data = {
'학번':['1000','2000','3000','4000','5000'],
'이름':["창민","영준","진우","인영","진표"],
'점수':[90,80,70,60,50]}
df = pd.DataFrame(data)
df
Out[2]:
학번이름점수01234
1000 | 창민 | 90 |
2000 | 영준 | 80 |
3000 | 진우 | 70 |
4000 | 인영 | 60 |
5000 | 진표 | 50 |
In [3]:
# 하나의 열만 조회
df['학번']
Out[3]:
0 1000
1 2000
2 3000
3 4000
4 5000
Name: 학번, dtype: object
In [4]:
# 두개 이상의 열 조회
df.loc[:,['학번','이름']]
Out[4]:
학번이름01234
1000 | 창민 |
2000 | 영준 |
3000 | 진우 |
4000 | 인영 |
5000 | 진표 |
In [5]:
# 하나 행 조회
df.loc[0]
# 두개 이상의 행 조회
df.loc[[1,2]]
Out[5]:
학번이름점수12
2000 | 영준 | 80 |
3000 | 진우 | 70 |
In [8]:
df.columns != '점수'
Out[8]:
array([ True, True, False])
In [7]:
# 특정 열 제외 해서 출력
df.loc[:,df.columns != '점수']
Out[7]:
학번이름01234
1000 | 창민 |
2000 | 영준 |
3000 | 진우 |
4000 | 인영 |
5000 | 진표 |
5) 외부 데이터 읽기
Pandas는 CSV, 텍스트, Excel, SQL, HTML, JSON 등 다양한 데이터 파일을 읽고 데이터 프레임을 생성할 수 있습니다.
예를 들어 csv 파일을 읽을 때는 pandas.read_csv( )를 통해 읽을 수 있습니다. 다음과 같은 example.csv 파일이 있다고 합시다.
In [83]:
data = pd.read_csv("./datasets/test.csv")
In [84]:
data
Out[84]:
Unnamed: 0012301
0 | 1 | 2 | 3 | 4 |
1 | 5 | 6 | 7 | 8 |
한글 csv 불러오기
In [87]:
data = pd.read_csv("./datasets/driving.csv",encoding='cp949')
read_csv 매개변수
- 구분자 sep, delimiter : 구분자를 제거하고 출력(초기값으로 ','로 설정됨)
- thousands = ',' : 천 단위 자리수 구분 콤마 없애고 불러오기
- nrows = n : n 개의 행만 불러오기
In [ ]:
data = pd.read_csv("./datasets/test.csv",thousands=",",encoding="latin1",na_values="n/a",delimiter=",").head(n=5)
In [15]:
data_url = 'http://archive.ics.uci.edu/ml/machine-learning-databases/housing/housing.data'
df_data = pd.read_csv(data_url,sep="\s+")
df_data.head()
Out[15]:
0.0063218.002.31000.53806.575065.204.09001296.015.30396.904.9824.0001234
0.02731 | 0.0 | 7.07 | 0 | 0.469 | 6.421 | 78.9 | 4.9671 | 2 | 242.0 | 17.8 | 396.90 | 9.14 | 21.6 |
0.02729 | 0.0 | 7.07 | 0 | 0.469 | 7.185 | 61.1 | 4.9671 | 2 | 242.0 | 17.8 | 392.83 | 4.03 | 34.7 |
0.03237 | 0.0 | 2.18 | 0 | 0.458 | 6.998 | 45.8 | 6.0622 | 3 | 222.0 | 18.7 | 394.63 | 2.94 | 33.4 |
0.06905 | 0.0 | 2.18 | 0 | 0.458 | 7.147 | 54.2 | 6.0622 | 3 | 222.0 | 18.7 | 396.90 | 5.33 | 36.2 |
0.02985 | 0.0 | 2.18 | 0 | 0.458 | 6.430 | 58.7 | 6.0622 | 3 | 222.0 | 18.7 | 394.12 | 5.21 | 28.7 |
CSV로 저장하기
In [89]:
import pandas as pd
data = [[1,2,3,4],[5,6,7,8]]
dataframe = pd.DataFrame(data)
dataframe.to_csv("./datasets/test.csv")
6) 결측치 제거
In [96]:
data = {
'학번':['1000','2000','3000','4000','5000'],
'이름':["창민","영준","진우","인영","진표"],
'점수':[90,80,70,60,50]}
df = pd.DataFrame(data)
6.1) 결측치 만들기
- pandas의 결측치는 None 또는 np.nan를 의미한다.
In [97]:
df.loc[0,'학번'] = np.nan
In [98]:
df.loc[4,'점수'] = None
In [99]:
df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 학번 4 non-null object
1 이름 5 non-null object
2 점수 4 non-null float64
dtypes: float64(1), object(2)
memory usage: 248.0+ bytes
6.2) 결측치 확인
In [100]:
df.isnull().sum()
Out[100]:
학번 1
이름 0
점수 1
dtype: int64
6.3) 결측치 행 또는 열 제거
In [104]:
# 특정 위치의 행 삭제
df.drop(labels=[2],axis=0)
Out[104]:
학번이름점수0134
NaN | 창민 | 90.0 |
2000 | 영준 | 80.0 |
4000 | 인영 | 60.0 |
5000 | 진표 | NaN |
In [106]:
# 특정 위치의 열 삭제
df.drop(labels=['이름'],axis=1)
Out[106]:
학번점수01234
NaN | 90.0 |
2000 | 80.0 |
3000 | 70.0 |
4000 | 60.0 |
5000 | NaN |
In [169]:
# 행 제거
df.dropna(axis=0)
Out[169]:
학번이름점수123
2000 | 영준 | 80.0 |
3000 | 진우 | 70.0 |
4000 | 인영 | 60.0 |
In [171]:
# 열 제거
df.dropna(axis=1)
Out[171]:
이름01234
창민 |
영준 |
진우 |
인영 |
진표 |
In [181]:
# 행에 대해서 1개라도 NaN값이 존재시 drop
df.dropna(how='any') # 기본 값
Out[181]:
학번이름점수123
2000 | 영준 | 80.0 |
3000 | 진우 | 70.0 |
4000 | 인영 | 60.0 |
In [182]:
# 행에 대해서 모두 NaN값이 존재시 drop
df.dropna(how='all')
Out[182]:
학번이름점수01234
NaN | 창민 | 90.0 |
2000 | 영준 | 80.0 |
3000 | 진우 | 70.0 |
4000 | 인영 | 60.0 |
5000 | 진표 | NaN |
6.4) 특정한 컬럼이 NaN인 경우에만 drop
In [175]:
df.dropna(subset=['점수'])
Out[175]:
학번이름점수0123
NaN | 창민 | 90.0 |
2000 | 영준 | 80.0 |
3000 | 진우 | 70.0 |
4000 | 인영 | 60.0 |
In [178]:
df.dropna(subset=['점수','학번'],how='any')
Out[178]:
학번이름점수123
2000 | 영준 | 80.0 |
3000 | 진우 | 70.0 |
4000 | 인영 | 60.0 |
In [177]:
df.dropna(subset=['점수','학번'],how='all')
Out[177]:
학번이름점수01234
NaN | 창민 | 90.0 |
2000 | 영준 | 80.0 |
3000 | 진우 | 70.0 |
4000 | 인영 | 60.0 |
5000 | 진표 | NaN |
6.4) 결측치 값 추가
In [172]:
df.fillna('hello')
Out[172]:
학번이름점수01234
hello | 창민 | 90.0 |
2000 | 영준 | 80.0 |
3000 | 진우 | 70.0 |
4000 | 인영 | 60.0 |
5000 | 진표 | hello |
7) Pandas 연산
7.1) 데이터프레임 row 인덱스 및 column 인덱스 가져오기
In [19]:
df.columns
Out[19]:
Index(['학번', '이름', '점수'], dtype='object')
In [20]:
df.index
Out[20]:
RangeIndex(start=0, stop=5, step=1)
7.2) Series에서 값만 가져오기
In [21]:
df['학번'].values
Out[21]:
array(['1000', '2000', '3000', '4000', '5000'], dtype=object)
7.3) Pandas 수학 연산
In [105]:
print('평균:',df['점수'].mean())
print('중간값:',df['점수'].median())
print('합:',df['점수'].sum())
print('최대값:',df['점수'].max())
print('최소값:',df['점수'].min())
print('표준편차:',df['점수'].std())
평균: 70.0
중간값: 70.0
합: 350
최대값: 90
최소값: 50
표준편차: 15.811388300841896
8) 데이터프레임 그룹으로 나누기
- groupby: 같은 값을 하나로 묶어 통계 또는 집계 결과를 얻음
In [14]:
df = pd.DataFrame({
'city': ['부산', '부산', '부산', '부산', '서울', '서울', '서울'],
'fruits': ['apple', 'orange', 'banana', 'banana', 'apple', 'apple', 'banana'],
'price': [100, 200, 250, 300, 150, 200, 400],
'quantity': [1, 2, 3, 4, 5, 6, 7]
})
In [15]:
df.groupby('city').describe()
Out[15]:
pricequantitycountmeanstdmin25%50%75%maxcountmeanstdmin25%50%75%maxcity부산서울
4.0 | 212.5 | 85.391256 | 100.0 | 175.0 | 225.0 | 262.5 | 300.0 | 4.0 | 2.5 | 1.290994 | 1.0 | 1.75 | 2.5 | 3.25 | 4.0 |
3.0 | 250.0 | 132.287566 | 150.0 | 175.0 | 200.0 | 300.0 | 400.0 | 3.0 | 6.0 | 1.000000 | 5.0 | 5.50 | 6.0 | 6.50 | 7.0 |
In [16]:
df.groupby('city').mean()
Out[16]:
pricequantitycity부산서울
212.5 | 2.5 |
250.0 | 6.0 |
In [17]:
df.groupby('city').std()
Out[17]:
pricequantitycity부산서울
85.391256 | 1.290994 |
132.287566 | 1.000000 |
In [18]:
df.groupby('city').min()
Out[18]:
fruitspricequantitycity부산서울
apple | 100 | 1 |
apple | 150 | 5 |
In [19]:
df.groupby('city').min().loc['부산']
Out[19]:
fruits apple
price 100
quantity 1
Name: 부산, dtype: object
8,1) 그룹 여러개로 지정 및 조회
In [22]:
df_group = df.groupby(['city','fruits']).mean()
df_group
Out[22]:
pricequantitycityfruits부산applebananaorange서울applebanana
100.0 | 1.0 |
275.0 | 3.5 |
200.0 | 2.0 |
175.0 | 5.5 |
400.0 | 7.0 |
In [57]:
df_group.loc['부산']
Out[57]:
pricequantityfruitsapplebananaorange
100.0 | 1.0 |
275.0 | 3.5 |
200.0 | 2.0 |
In [56]:
df_group.loc['부산'].loc['apple']
Out[56]:
price 100.0
quantity 1.0
Name: apple, dtype: float64
In [58]:
df_group['price']['부산']
Out[58]:
fruits
apple 100.0
banana 275.0
orange 200.0
Name: price, dtype: float64
In [53]:
df_group['price']['부산']['apple']
Out[53]:
100.0
In [ ]:
8.2) 그룹안에 데이터 확인
In [147]:
df_group = df.groupby('city')
df_group.get_group('부산')
Out[147]:
cityfruitspricequantity0123
부산 | apple | 100 | 1 |
부산 | orange | 200 | 2 |
부산 | banana | 250 | 3 |
부산 | banana | 300 | 4 |
8.3) 연속형 데이터를 범주형 데이터로 그룹 짓기
In [62]:
tips = sns.load_dataset("tips")
tips.head()
Out[62]:
total_billtipsexsmokerdaytimesize01234
16.99 | 1.01 | Female | No | Sun | Dinner | 2 |
10.34 | 1.66 | Male | No | Sun | Dinner | 3 |
21.01 | 3.50 | Male | No | Sun | Dinner | 3 |
23.68 | 3.31 | Male | No | Sun | Dinner | 2 |
24.59 | 3.61 | Female | No | Sun | Dinner | 4 |
In [69]:
# 특정 연속형데이터 인 열에 대해서 범주형으로 만들기
total_bill_cut = pd.cut(tips['total_bill'],5)
print(total_bill_cut.head())
# 범주형 데이터를 label로 표현하기
total_bill_cut = pd.cut(tips['total_bill'],5,labels=['A','B','C','D','E'])
print(total_bill_cut.head())
0 (12.618, 22.166]
1 (3.022, 12.618]
2 (12.618, 22.166]
3 (22.166, 31.714]
4 (22.166, 31.714]
Name: total_bill, dtype: category
Categories (5, interval[float64, right]): [(3.022, 12.618] < (12.618, 22.166] < (22.166, 31.714] < (31.714, 41.262] < (41.262, 50.81]]
0 B
1 A
2 B
3 C
4 C
Name: total_bill, dtype: category
Categories (5, object): ['A' < 'B' < 'C' < 'D' < 'E']
In [70]:
total_bill_cut = pd.cut(tips['total_bill'],5)
tips['total_bill_cut'] = total_bill_cut
In [71]:
tips.head()
Out[71]:
total_billtipsexsmokerdaytimesizetotal_bill_cut01234
16.99 | 1.01 | Female | No | Sun | Dinner | 2 | (12.618, 22.166] |
10.34 | 1.66 | Male | No | Sun | Dinner | 3 | (3.022, 12.618] |
21.01 | 3.50 | Male | No | Sun | Dinner | 3 | (12.618, 22.166] |
23.68 | 3.31 | Male | No | Sun | Dinner | 2 | (22.166, 31.714] |
24.59 | 3.61 | Female | No | Sun | Dinner | 4 | (22.166, 31.714] |
In [74]:
tips.groupby('total_bill_cut').describe()['tip']
Out[74]:
countmeanstdmin25%50%75%maxtotal_bill_cut(3.022, 12.618](12.618, 22.166](22.166, 31.714](31.714, 41.262](41.262, 50.81]
49.0 | 1.864286 | 0.740886 | 1.00 | 1.480 | 1.71 | 2.0000 | 5.15 |
119.0 | 2.763025 | 0.788337 | 1.01 | 2.005 | 2.75 | 3.2400 | 5.00 |
50.0 | 3.739200 | 1.315194 | 1.50 | 2.940 | 3.55 | 4.9275 | 6.50 |
19.0 | 4.354737 | 1.514458 | 1.17 | 3.145 | 4.67 | 5.0850 | 7.58 |
7.0 | 5.961429 | 2.769551 | 2.50 | 4.250 | 5.00 | 7.8650 | 10.00 |
9) 그래프로 표현하기
- 기존 matplotlib를 사용하면 되지만, 데이터프레임 또는 시리즈 같은 경우 matplotlib으로 표현하려면 index와 column 부분을 나누어주어야 된다. 따라서 데이터프레임 또는 시리즈 에 내장된 plot를 사용하면 간편하게 표현 할 수 있다.
In [10]:
data = pd.read_csv("./datasets/timeseries.csv",encoding='cp949')
In [11]:
data.loc[:]
Out[11]:
DateCloseStartHighLowVolume01234
2015-07-02 | 10100 | 10850 | 10900 | 10000 | 137977 |
2016-06-29 | 10700 | 10550 | 10900 | 9990 | 170253 |
2017-06-28 | 10400 | 10900 | 10950 | 10150 | 155769 |
2018-06-27 | 10900 | 10800 | 11050 | 10500 | 133548 |
2019-06-26 | 10800 | 10900 | 11000 | 10700 | 63039 |
In [13]:
data.loc[:,['Close','Start']].plot()
plt.show()
