데이터 분석

데이터 처리를 위한 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()