220927 Day23

유예지·2022년 9월 27일

[0926 복습]

1. np.max 와 np.maximum

>>> import numpy as np
>>> a = [[1,2,3], [4,5,6]]
	b = [[2,4,6], [1,2,3]]

>>> np.maximum(a, b)    #2개의 인자를 받을 수 있다

>>> print(np.max(a))
	np.max(b)          #하나의 인자만 받는다

2. 입력값을 행과 열의 개수(n)로 하는 정사각행렬의 원소를 1~100 사이의 정수로 출력 (난수행렬)

>>> n = int(input())
	np.random.randint(1, 100, size = (n,n))

3. 각 행의 평균을 구하고, 그 값을 뺀 행렬

>>> np.random.rand(3, 4)
>>> np.random.uniform(size = (3,4))    #좀 더 일반화된 느낌

>>> np.random.rand(3, 4)*100
	np.round((np.random.rand(3, 4)*100), 2)
    
>>> arr = np.round((np.random.rand(3, 4)*100), 2)
    arr_a = np.round(arr.mean(axis = 1), 2).reshape(3, 1)
    arr_a

>>> print(arr)
	arr - arr_a
    
#각 열의 평균
>>> arr_b = np.array(np.round(arr.mean(axis = 0), 2))
	arr_b
    
>>> arr - arr_b    

4. 슬라이싱

>>> np.arange(1, 10).reshape(3,3)
array([[1, 2, 3],
       [4, 5, 6],
       [7, 8, 9]])
       
>>> a = np.arange(1, 10).reshape(3,3)

#5,6,8,9 출력
>>> a[1:, 1:]

#5,9 출력
>>> a[[1,2], [1,2]]

>>> np.array([[[1,2,3], [4,5,6]], [[7,8,9], [10,11,12]]])
>>> b = np.array([[[1,2,3], [4,5,6]], [[7,8,9], [10,11,12]]])
	b
    
#12 출력
>>> b[1,1][2]

#8 출력
>>> b[1][0][1]

5. 리스트를 dictionary comprehension을 사용해서 dictionary로 (index를 key로)

>>> li = ['apple', 'banana', 'cherry', 'date']
>>> {i:j for i, j in enumerate(li)}

6. 변수 추가 방법

list[] : li.append()
dict{:} : dic['key'] = 'value'
set{} : set.add()

* 7. 0 -> 170, 시그마값 1 -> 5 변경

>>> np.random.randn(3,4)
>>> np.random.randn(3,4) * 5 + 170

4. Pandas

(1) Pandas 자료구조

① Series

일련의 객체를 담을 수 있는 '1차원 배열' 같은 자료구조
Series의 배열과 인덱스는 각각 values 와 index 속성을 통해 알 수 있다

>>> import pandas as pd
>>> pd.Series([4,7,-5,3])

>>> s = pd.Series([4,7,-5,3])
	s.values
array([ 4,  7, -5,  3], dtype=int64)

>>> s.index
RangeIndex(start=0, stop=4, step=1)

#각각의 데이터를 지칭하는 인덱스를 지정해줄 수 있다
>>> s = pd.Series([4,7,-5,3], index = ['a','b','c','d'])
	s
    
#인덱싱을 할 수 있다
>>> s[['a','b']]

>>> s > 0
a     True
b     True
c    False
d     True
dtype: bool

파이썬 사전형에 데이터를 저장해야 한다면 사전 객체로부터 Series 객체를 생성할 수도 있다
생성된 Series 객체의 인덱스 자리에는 사전의 key 값이 순서대로 들어간다

>>> sdata = {'Ohio': 35000, 'Texas': 71000, 'Oregon': 16000, 'Utah': 5000}
    
>>> obj = pd.Series(sdata)
	obj    
   
>>> states = ['California', 'Ohio', 'Oregon', 'Texas']
	obj1 = pd.Series(sdata, index = states)
	obj1
    
#누락된 데이터를 찾을 때
>>> obj1.isnull()
>>> obj1.notnull()

#간단한 연산도 할 수 있다
>>> obj + obj1    #계산할 수 있는 것만 계산 -> NaN 값이 2개 나온다
  • name 속성
>>> obj1.index
Index(['California', 'Ohio', 'Oregon', 'Texas'], dtype='object')

>>> obj1.index.name = 'state'    #인덱스의 목록 이름 추가
	obj1
state
California        NaN
Ohio          35000.0
Oregon        16000.0
Texas         71000.0
dtype: float64    

>>> obj1.name = 'population'    #Series 객체의 이름이 생성된다
	obj1

#name은 대입하여 변경할 수도 있다
>>> obj1.index = ['a','b','c','d']
	obj1
    
>>> obj1.index[0]
'a'

② DataFrame

DataFrame 객체는 리스트에 담긴 사전을 이용하거나 Numpy 배열을 이용해 만든다

>>> data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
            'year': [2000, 2001, 2002, 2001, 2002, 2003],
            'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
    data
    
>>> frame = pd.DataFrame(data)
	frame
    
#원하는 순서대로 columns를 지정할 수 있다
>>> pd.DataFrame(data, columns = ['year', 'state', 'pop', 'debt'])
#새 칼럼 'debt' 추가 -> 사전에 없는 값은 결측치로 저장된다

* 검색하기 (읽어오기)

DataFrame의 칼럼은 '[ ]' 또는 '.~' 으로 접근할 수 있다
frame['column'] 의 형태로 사용하는 것은 어떤 칼럼이든 가능하지만, frame.column 의 형태로 사용하는 것은 파이썬에서 사용가능한 변수 이름 형식일 때만 작동한다

>>> frame['state']
>>> frame.state

* 접근하기

df[ , ] -> x
df.loc : '행의 이름' 으로 접근
df.iloc : '행의 인덱스 번호' 로 접근

>>> df = frame.copy()

>>> df.loc[ : , 'state']
>>> df.loc[ : , ['state']]

>>> df.loc[ : , ['state', 'year']]
>>> df.loc[1:3, ['state', 'year']]    #인덱스 번호 '1'부터 '3'까지 나온다

>>> df.iloc[ : , 0]
>>> df.iloc[ : , [0,1]]
>>> df.iloc[1:3, [0,1]]

>>> df['state']    #[]안에 칼럼의 이름 -> '열' 을 기본으로 잡아준다
>>> df[:2]    	   #[]안에 숫자 -> '행' 을 기본으로 잡아준다

* 칼럼에 대입, 칼럼 삭제

칼럼은 대입이 가능하다
리스트나 배열을 칼럼에 대입할 때는 대입하려는 값의 길이가 DataFrame의 크기와 동일해야 한다
Series를 대입하면 DataFrame의 인덱스에 따라 값이 대입되며, 존재하지 않는 인덱스에는 결측치가 대입된다

>>> frame['debt'] = 16.5
>>> frame['debt'] = np.arange(6.)

존재하지 않는 칼럼을 대입하면 새로운 칼럼을 생성한다
또한 'del' 을 사용해서 칼럼을 삭제할 수도 있다

>>> frame.state == 'Ohio'

>>> frame['eastern'] = frame.state == 'Ohio'
	frame    #frame.eastern 형태의 문법으로는 생성되지 않는다
    
>>> del frame['eastern']
	frame    

Numpy 배열과 유사한 문법으로 데이터를 전치(칼럼과 로우를 뒤집음) 할 수도 있다

>>> frame.T
>>> frame.values    #pd.DataFrame을 np.array로 바꾸는 방법
#Series와 유사하게 value 속성은 DataFrame에 저장된 데이터를 2차원 배열로 반환한다

③ index

파이썬의 집합과는 달리 pandas의 인덱스는 중복되는 값을 허용한다

>>> df = frame.copy()
	df
    
>>> df.index = ['a','b','c','a','b','c']
	df    
    
#index가 'a' 인 것을 검색 -> index를 검색에 사용할 수 있다
>>> df.loc['a', : ]    

(2) 핵심 기능

① 재색인 .reindex()

>>> obj2 = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c'])
	obj2
d    4.5
b    7.2
a   -5.3
c    3.6
dtype: float64    

#인덱스에 따라 데이터 값도 정렬된다
>>> obj2.reindex(['a','b'])
>>> obj2.reindex(['a','b', 'c','d','e'])

#칼럼 재색인
>>> frame.reindex(columns = 칼럼이름)

② 하나의 로우나 칼럼 삭제하기 : .drop()

drop 함수는 디폴트 값이 row(axis = 0) 이다

>>> df.drop('state', axis = 1)
>>> df.drop('state', axis = 1, inplace = True)    #변경된 형태 저장
>>> df.drop('a')
>>> df.drop(['a', 'b'])

③ 필터링 (인덱싱, 슬라이싱)

Series의 인덱싱은 Numpy 배열의 인덱싱과 유사하게 동작하지만, '정수가 아니어도 된다'는 점이 다르다

>>> obj2

#검색
>>> obj2['a']

>>> obj2 = obj2.reindex(['a','b','c','d'])
	obj2
    
#슬라이싱 - 라벨 이름으로 슬라이싱을 하면 시작점과 끝점을 포함한다
>>> obj2['a' : 'c']
>>> obj2[['a','b']]

>>> obj2 > 0
>>> obj2[obj2 > 0]

④ 함수 적용과 맵핑

pandas 객체에도 Numpy의 유니버설 함수(배열의 각 원소에 적용되는 메서드)를 적용할 수 있다

>>> frame = pd.DataFrame(np.random.randn(4, 3), columns=list('bde'),
                      index=['Utah', 'Ohio', 'Texas', 'Oregon'])
    frame
    
#음수 -> 양수로
>>> frame = np.abs(frame)   #df 이어도 np 함수가 잘 적용된다
    frame    

* DataFrame 의 apply 메서드를 이용해 각 칼럼이나 로우의 1차원 배열에 함수를 적용할 수 있다

.apply() : map, filter와 비슷하고, '함수'를 인자로 받는다
.apply()에 들어가는 함수는 각 컬럼에 대해 '한번만' 수행되며 결과값은 계산을 적용한 칼럼을 인덱스로 하는 Series로 반환된다

>>> frame

#각 열별로 합 구하기
>>> frame.apply(sum)

#행별로 합 구하기
>>> frame.apply(sum, axis = 1)

>>> print(frame.apply(np.mean))
	frame.apply(np.mean, axis = 1)

배열에 대한 일반적인 통계(sum이나 mean)는 DataFrame의 메서드로 존재하므로 apply 메서드를 사용할 필요가 없다

>>> frame.sum(axis = 1)
>>> frame.mean()
  • 최대값과 최소값의 차이를 구해보자
    apply 메서드에 적용되는 함수는 스칼라값(하나의 값)만을 반환할 필요가 없다
    여러 값을 가진 Series를 반환해도 된다
>>> print(frame.max())
	frame.min()    #칼럼 각각의 최대, 최소값을 구해서 보여준다
    
>>> frame.max() - frame.min()

>>> def f(x):
		return x.max() - x.min()
>>> frame.apply(f)

>>> frame.apply(lambda x: x.max() - x.min())

>>> print(frame.apply(max))
	frame.apply(min)    
  • 배열의 각 원소에 적용되는 파이썬의 함수를 사용할 수도 있다 -> applymap()
>>> form = lambda x: '%.2f' %x    #'%.2f' : 소숫점 이하 둘째자리까지 출력

>>> frame.apply(form)
	frame.applymap(form)    

⑤ 정렬과 순위

* 정렬 sorting -> .sort_index()

.sort_index() : 로우나 칼럼의 인덱스 이름이 알파벳 순으로 정렬된, 새로운 객체를 반환한다

>>> obj3 = pd.Series([4.5, 7.2, -5.3, 3.6], index=['d', 'b', 'a', 'c']) 
	obj3
    
>>> obj3.sort_index()
  • Series 객체를 '값에 따라' 정렬하고 싶다면 -> .sort_values()
>>> obj3.sort_values()

#정렬 옵션을 줄수도 있다
>>> df = pd.DataFrame({'b' : [4,7,-3,2], 'a' : [0,1,0,1]})
	df
    
>>> df.sort_values(by='b')    

* 순위 ranking -> .rank()

기본적으로 Series와 DataFrame의 rank 메서드는 동점인 항목에 대해서는 '평균 순위' 를 매긴다

#Series
>>> obj4 = pd.Series([7, -5, 7, 4, 2, 0, 4])
	obj4
    
>>> obj4.rank()

>>> obj4.rank(method = 'first')

#DataFrame : 로우나 칼럼에 대해 순위를 정할 수 있다
>>> frame1 = pd.DataFrame({'b' : [4.3, 7, -3, 2],
						'a' : [0,1,0,1], 'c' : [-2, 5, 8, -2.5]})
	frame1                        

>>> frame1.rank(axis = 'columns')

>>> fram1.rank(axis = 0)
>>> fram1.rank(axis = 1)

(3) 기술 통계 계산과 요약

pandas 의 메서드는 처음부터 누락된 데이터를 제외하도록 설계되었다
전체 로우나 칼럼의 값이 NA가 아니라면, NA 값은 제외되고 계산된다

>>> df = pd.DataFrame([[1.4, np.nan], [7.1, -4.5],
					   [np.nan, np.nan], [0.75, -1.3]],
                      index = ['a','b','c','d'],
                      columns = ['one','two'])
	df
   
#df.sum() : 각 칼럼의 합을 담은 Series 반환
>>> df.sum()
>>> df.sum(axis = 1)

#idxmin이나 idxmax 같은 메서드는 최소값 혹은 최대값을 가지고 있는 인덱스와 같은 간접 통계를 반환한다
>>> df.idxmax()

#누산(누적합) : .cumsum()
>>> df.cumsum()

#한번에 여러개의 통계 결과 출력 : .describe()
>>> df.describe()

#퍼센트 변화율 계산
>>> df.pct_change()

① 상관관계와 공분산

두 쌍의 인자를 필요로 한다

https://destrudo.tistory.com/15

* 공분산 (Covariance)

2개의 확률 변수 x와 y가 어떻게 퍼져있는지,
x가 커지면 y도 커지는지 혹은 작아지는지, 아니면 별 상관 없는지 등을 나타낸다

Cov(X, Y) > 0 : X가 증가 할 때 Y도 증가한다.
Cov(X, Y) < 0 : X가 증가 할 때 Y는 감소한다.
Cov(X, Y) = 0 : 공분산이 0이라면 두 변수간에는 아무런 선형관계가 없으며 두 변수는 서로 독립적인 관계에 있음을 알 수 있다.

두 변수가 독립적이라면 공분산은 0이 되지만, 공분산이 0이라고 해서 항상 독립적이라고 할 수 없다.

* 상관계수 (Correlation)

공분산의 문제점은 x와 y의 단위의 크기에 영향을 받는다는 것인데, 예를 들어 100점 만점인 두 과목의 점수 공분산은 상관성이 부족하더라도 100점 만점이기 때문에 큰 값이 나오고, 10점짜리 두 과목의 점수 공분산은 상관성이 아주 높더라도 10점 만점이기 때문에 작은값이 나온다.

이것을 보완하기 위해 상관계수가 나타난다.
확률변수의 절대적 크기에 영향을 받지 않도록 단위화 시킨 것이다. 즉, 분산의 크기만큼 나누었다고 생각하면 된다.

※ 상관계수의 성질
1. 상관계수의 절대값은 1을 넘을 수 없다.
2. 확률변수 X, Y가 독립이라면 상관계수는 0이다.
3. X와 Y가 선형적 관계라면 상관계수는 1 혹은 -1이다.
(양의 선형관계면 1, 음의 선형관계면 -1)

>>> pip install pandas-datareader
>>> import pandas_datareader.data as web

>>> all_data = {ticker: web.get_data_yahoo(ticker) for ticker in ['AAPL', 'IBM', 'MSFT', 'GOOG']}

    price = pd.DataFrame({ticker: data['Adj Close'] for ticker, data in all_data.items()})

    volume = pd.DataFrame({ticker: data['Volume'] for ticker, data in all_data.items()})
    
>>> price

corr 메서드 : NA가 아니며 정렬된 인덱스에서 연속하는 두 Series에 대한 상관관계 계산
cov 메서드 : 공분산 계산

#각 주식의 퍼센트 변화율(pct_change)
>>> price.pct_change()

>>> price.corr()
>>> price[['AAPL', 'IBM']].corr()

>>> price.cov()

② 유일값 세기 .unique()

중복되는 값을 제거하고 유일값만 담고 있는 Series 반환

>>> if 'a' in ['a','b','c']:
    	print('yes')

#isin 메서드 : 어떤 값이 Series에 존재하는지 True, False로 확인
>>> data = {'state': ['Ohio', 'Ohio', 'Ohio', 'Nevada', 'Nevada', 'Nevada'],
                'year': [2000, 2001, 2002, 2001, 2002, 2003],
                'pop': [1.5, 1.7, 3.6, 2.4, 2.9, 3.2]}
>>> frame = pd.DataFrame(data)
	frame

>>> frame.isin(['Ohio'])
>>> frame['state'].isin(['Ohio'])

#DataFrame의 여러 칼럼에 대해 막대 그래프를 구해보자
>>> data = pd.DataFrame({'Qu1': [1, 3, 4, 3, 4],
                         'Qu2': [2, 3, 1, 2, 3],
                          'Qu3': [1, 5, 2, 4, 4]}) 
    data
    
>>> data['Qu1'].value_counts()    #어떤 값이 몇번 나왔는지 (빈도수)
>>> data['Qu1'].value_counts(sort = False)    #오름차순 정렬
>>> import seaborn as sns
>>> sns.countplot(data['Qu1'])

>>> data.apply(pd.value_counts)     #빈도수를 출력해줌
>>> df = data.apply(pd.value_counts)
	df.info()
    
>>> df['Qu1'] = df['Qu1'].astype('category')
>>> sns.barplot(data = df, x = 'Qu1')

5. 데이터 로딩과 저장, 파일 형식

pandas 에서는 표 형식의 자료를 DataFrame 객체로 읽어오는 몇 가지 기능을 제공한다
read_csv, read_excel, read_table ...

* JSON 데이터

JSON 문자열을 파이썬 형태로 : json.loads
파이썬 객체를 JSON 형태로 : json.dumps

>>> import json
>>> obj = """
{"name" : "Wes",
"places_lived" : ["United States", "Spain", "Germany"],
"pet" : null,
"siblings" : [{"name" : "Scott", "age" : 30, "pets" : ["Zeus", "Zuko"]},
              {"name" : "Katie", "age" : 38,
              "pets" : ["Sixes", "Stache", "Cisco"]}]
}
"""

>>> result = json.loads(obj)
	result

>>> asjson = json.dumps(result)

>>> siblings = pd.DataFrame(result['siblings'], columns = ['name', 'age'])
	siblings

* 웹 API와 함께 사용하기

>>> import requests
>>> url = 'https://api.github.com/repos/pandas-dev/pandas/issues' 

>>> resp = requests.get(url)
	resp
    
>>> data = resp.json()
	data    #.json() : JSON의 내용을 파이썬 사전 형태로 변환한 객체를 반환한다
    
>>> data[0]['title']

>>> issues = pd.DataFrame(data)
	issues

6. 데이터 정제 및 준비

(1) 누락된 데이터 처리하기 (결측치 NA)

pandas는 누락된 데이터를 실수값인 NaN 으로 취급한다

결측치는 NA로 취급하며, NA는 분석 애플리케이션에서 데이터가 존재하지 않거나, 존재하더라도 데이터를 수집하는 과정 등에서 검출되지 않았음을 의미한다

파이썬의 내장 None 값 또한 NA 값으로 취급된다

* NA 처리 메서드

dropna
누락된 데이터가 하나라도 포함되어 있는 축(로우, 칼럼)을 제외시킨다
Series에 dropna 메서드를 적용하면 null이 아닌 데이터와 인덱스 값만 들어있는 Series를 반환한다

어느 정도의 누락 데이터까지 용인할 것인지 지정할 수 있다
dropna(how = 'all') : 모두 NA 값인 로우만 제외

fillna
누락된 데이터를 대신할 값을 채우거나, 'ffill' 과 'bfill' 같은 보간 메서드를 적용한다

isnull
누락되거나 NA인 값을 True, False로 알려준다

notnull
isnull과 반대되는 메서드

>>> df.isnull()

>>> df.isnull().sum()

(2) 데이터 변형

① 중복 제거하기 .duplicated()

각 로우가 중복인지 아닌지를 True, False 로 알려준다
중복이다 -> True, 아니다 -> False

  • .drop_duplicates() : duplicated 배열이 False 인 DataFrame 반환

  • 'keep = 'last'
    .duplicated() 와 .drop_duplicates() 는 기본적으로 처음 발견된 값을 유지한다
    'keep = 'last' 옵션을 쓰면 마지막으로 발견된 값을 반환한다

>>> data = pd.DataFrame({'k1' : ['one', 'two'] * 3 + ['two'], 'k2' : [1,1,2,3,3,4,4]})

>>> data.drop_duplicates(['k1', 'k2'], keep='last')

0개의 댓글