파이썬과 라이브러리_5

우주먼지·2020년 7월 9일
0

인공지능 사관학교

목록 보기
10/15

파이썬과 라이브러리

Pandas

대부분의 데이터는 구조화가 되어 있지 않다. 간혹가다 구조화된 데이터를 얻을 수 있겠지만, 이는 경제적으로 매우 높은 가치를 가지고 있는 데이터 일 것이다.

  • pandas는 데이터를 구조화하기 위해서 Dataframe, Series이라는 객체를 다룰 수 있게 한다.
  • pandas는 numpy와 비슷한 면이 많고, numpy가 기본으로 깔려있다.
  • Pandas는 통계, 결측치처리, 시각화등의 많은 기능이 있다.
import pandas as pd
import numpy as np

pandas를 사용하기 위한 라이브러리를 불러와준다.

Series

  • 1차원 numpy배열과 유사하다
x = {'a':1,'b':2,'c':3}
s = pd.Series(x)
s.index() # array(['a', 'b', 'c'])
s.values() # array([1, 2, 3])
s['a'] # ( =a[0]) 1

Series를 Dict형으로 만들었다. 사전은 원래 순서가 없으나, Series는 순서가 중요하다.
인덱스에 이름을 넣어서 배열을 만든것과 같다. 값을 얻기 위해서 인덱스나 순서로 검색할 수 있다.

x = np.array([111, 222, 333])
s = pd.Series(x)
s # 0 111 = / 1 222 / 2 333
my_index = ['a', 'b', 'c']
s = pd.Series(x, index=my_index)
s # 'a' 111 / 'b' 222 / 'c' 333

인덱스를 명시하지 않으면 원래 우리가 아는 인덱스가 자동 생성된다.
인덱스를 따로 지정하여 넣어줄 수 있다.
리스트 인덱싱하는 것과 같은 방법을 인덱싱이 가능하다. (ex) s['a':'c'] => a 111 / b 222 / c 333, s['a', 'c'] => 111, 333)

type(s.values)

numpy.ndarray
Series는 numpy배열의 확장형이라고 생각하면 된다.

s = pd.Series(data=[111, 222, 333, 444], index=['a', 'b', 'c', 'd'], name='MySeries', dtype='float64')
s

a 111.0/b 222.0/c 333.0/d 444.0/ Name:MySeries, dtype:float64
이름과 데이터 타입을 선언해줄 수 있다. 특히 이름은 Series에만 있는 속성이다. name을 확인하기 위해서는 s.name을 사용한다.

s1 = pd.Series(data=[1, 2, 3, 4])
s2 = pd.Series(data=[1, 2, 3, 4])
s1 * 2 # 0 2/ 1 4/ 2 6/ 3 8
s1 + s2 # 0 2 / 1 4 / 2 6 / 3 8

인덱스가 같은 Series끼리의 연산은 numpy배열의 연산과 같은 방식으로 진행된다.

s1 = pd.Series(data=[1, 2, 3, 4], index=['d' 'b', 'c', 'a'])
s2 = pd.Series(data=[1, 2, 3, 4], index=['a', 'b', 'd', 'e'])
s1 + s2 # a 5.0 / b 4.0 / c NaN / d 4.0 / e NaN

인덱스가 다른 Series끼리의 사칙연산을 하면 인덱스가 같은 값끼리 연산을 한 후, 한쪽에만 있는 인덱스의 값은 NaN으로 결측치 처리가 된다. 결측치가 생기는 경우 데이터타입이 floa64로 바뀐다.

s1.sum() # 10
s1.mean() # 2.5
s1.median() # 2.5
s1.std() # 1.290944...
s1.var() # 1.666666...
s1.sort_values() # d 1 / b 2/ c 3/ d 1
s1.sort_index() # a 4 / b 2 / c 3 / d 1
s.value_counts() # 도수표 생성
s.nunique() # 4 unique한 요소가 몇개인지

기본적인 통계 메소드가 존재하며, 특이한 것으로는 value기준 또는 index기준으로 나눠서 sort가 가능하다
value_counts()는 각각의 요소가 배열에 몇개가 있는지를 나타내준다.(도수표를 생성)

DataFrame

  • 2차원 객지체이지만, 열마다는 자료형이 일치해야하나, 열과 열사이의 자료형은 일치하지 않아도 된다.
  • csv, 엑셀파일, sql테이블 등의 데이터를 담기에 적합하다.
  • DataFrame의 컬럼 하나를 뽑아오면 Series가 된다.
import pandas as pd
import numpy as np
import os
os.chdir(r"../data")
df = pd.read_csv('data_studentlist_en.csv', header='infer', encoding='ms949')
df.head(3) # df.tail(3) : 하단 3행

data_studentlist_en파일을 불러와서 상위 3개만 출력(head(3)).
한글이 있을 경우, utf-8이 잘 작동하지 않을 수 있으므로, encoding을 'ms949'로 작성해주어야한다. header에 infer라는 것은 파일 안에 있는 제일 첫줄을 헤더라고 지칭해준다. 만약 header가 없는 경우는 header=None이라고 입력하면 0, 1, 2...로 대체해준다.

df.columns # 컬럼의 이름들을 출력
df.index # 인덱스의 이름들을 출력
df.shape() # (17, 8) 행의 수와 열의 수를 출력
df.size # 138 (= 17 * 8) 총 데이터의 개수(셀의 수)
df.ndim # 2 차원의 수
df.info() # 자료형을 보여줌

데이터 프레임의 정보를 알 수 있는 메소드들.
인덱스는 Series와 마찬가지로 내가 원하는 값으로 바꿀 수 있다.

np.round(df.describe(), 1) # 수치형 변수에 대한 기술 통계량를 제공.

수치형 변수에 대한 개수, 평균, 표준편차, 최소값, 4분위수, 최대값이 데이터 프레임으로 출력된다.

df['bloodtype'] # Series로 컬럼 하나를 출력가능 ( =df.bloodtype)
df[['bloodtype']]
df[['bloodtype', 'gender']] # 여러개의 값도 추출 가능

출력한 한 컬럼의 이름은 'bloodtype'이 된다. df['blooltype']과 df.bloodtype은 같은 결과를 출력한다. 하지만 이름에 공백이나 특수문자가 있는 경우는 df.---이 안된다.
출력물을 대괄호로 묶어주면 다시 DataFrame으로 출력된다.

df.loc[:, 'name'] # 모든 행의 name열만 출력
df.loc [0:5, ['name', 'gender']] # 데이터 프레임으로 0~4번째 행의 name, gender를 출력
df.iloc[:, 2] # 숫자로만 열과 행의 위치를 나타내어 출력가능

loc은 이름으로 값을 추출해오는 것이고, iloc은 숫자(위치)로 값을 추출해오는 것이다.
또한 loc는 처음과 끝 모두를 포함시키지만, iloc은 뒤에 (숫자 -1)까지 포함이다.
loc[3:5] => 3, 4, 5 / iloc[3:5] => 3, 4

my_index = 'a b c d e f g h i j k l m n o p q'.split() # 공백으로 잘라서 리스트에 저장
df.index = my_index # 인덱스 값을 지정

df.drop(columns=['name']) # 특정 컬럼 제거, 항구적으로 사라지지는 않음
df.drop(columns=['name'], inplace=True) # 제거하고 남은 내용을 항구적으로 저장
np.round(df['BML'] = 10000 * df['wdight'] / df['height'] ** 2, 1) # 특정 컬럼 생성

인덱스 값은 원하는 값으로 지정해주었다. 이때의 loc('a', 'name')이런식으로 사용해줘야한다.
drop을 이용하여 필요없는 컬럼을 제거할 수 있따. 하지만 항구적이지 않아 변수에 저장이 필요하다.

조건부 슬라이싱

df['df.GENDER == 'M'] # 성별이 M인경우만 가져옴
df[{df.GENDER == 'M') & ((df.HEIGHT < 160) | (df.HEIGHT > 180))] # 남자중 키가 160~180사이인 경우만 가져옴

numpy의 fancy인덱싱과 같은 방식으로 사용가능하다.

df.to_csv('data_new.csv', index=False) # 외부에 save

수정한 데이터를 외부의 파일로 저장하는 방법.

dfx = read_excel('data_studentlist_en.xlsx', sheet_name = 'Sheet1')
dfx.to_excel('data_studentlist_en2.xlsx', s) # 읽은 파일을 출력

엑셀 파일을 읽고 이 내용을 출력하는 코드.

데이터 프레임 만들기

data = {'name':['jake', 'john', 'david', 'sarah'], 'age':[23, 20, 15, 29], 'gender':['M', 'M', 'M', 'F']} #dict 생성
df = pd.DataFrame(data = data, index=['a', 'b', 'c', 'd'])

사전을 이용하여 데이터 프레임을 생성했다. 이 때, index를 별도로 지정해주었다.

x = np.round(np.random.randn(16), 2) # 100개의 랜덤 숫자 생성
x = x.reshape(4, 4)
df = pd.DataFrame(data = x, columns=['First', 'Second', 'Third', 'Fourth'], index=['a', 'b', 'c', 'd'])

데이터프레임을 생성해주었는데 그냥 넣으면 단순 숫자로만 데이터가 이루어져있어 컬럼이름이 없다. 따라서 원하는 이름을 columns로 넣어주었다.

df = pd.read_csv('data_studentlist_en.csv', header='infer', encoding='ms949')
df_left = df[['name', 'age', 'gender', 'absence']] # ( =df.loc[:, ['name', 'age', 'gender', 'absence']])
df_right = df[['name', 'bloodtype', 'weight', 'height']]
df_left_small = df_left.loc[:10,]
df_right_small = df_right.loc[7:,] # 좀 더 직관적으로 보기 위해 
pd.merge(df_left_small, df_right_small, left_on='name', right_on='name', how='inner') # name을 가지고 두 데이터를 inner join한다

왼쪽의 key를 name, 오른쪽의 key를 name으로 inner조인을 시행한다. 이 경우 겹치는 7, 8, 9, 10행만이 출력된다. how의 left, right, inner, outer를 입력함으로써 조인 방법을 바꿀 수 있다.

조인은 왼쪽, 오른쪽만 조인이 가능하다.

조인이 아닌 다른 합치는 방법이 있다.

pd.concat([df_left_small, df_right_small], ignore_index=True, axis=0)

concat을 사용하면 내용을 위아래로 이어붙일수 있다. ignore_index가 True이면 원래 있던 인덱스를 무시한다. axis가 0이 default로 들어가 있으므로, 세로방향으로 합쳐진다.
axis가 1이면 그냥 이어붙인 결과이므로 같은 컬럼이 두개 생긴다(예시에서는 키로 사용한 name이 두개가 된다)

profile
안녕하세요 ㅎㅎ

0개의 댓글