욱이의 냉철한 공부

[Python, 정리] Pandas - 데이터 처리 본문

데이터분석/Python : Basic

[Python, 정리] Pandas - 데이터 처리

냉철한 욱 2022. 3. 28. 08:05

 

1. 데이터베이스처럼 DataFrame 합치기. - merging (병합)

df1 = pd.DataFrame({"key" : list("bbacaab"), "data1":range(7)})

df2 = pd.DataFrame({"key" : list("abd"), "data1":range(3)})

 

pd.merge(df1,df2,on="key")

pd.merge(df1,df2,on="key",how="outer")

pd.merge(df1,df2,on="key",how="left")

pd.merge(df1,df2,on="key",how="right")

pd.merge(df1,df2,on="key",how="inner")

pd.merge(left, right, on='key', suffixes=('_left', '_right'))

-> suffixes인자는 각각의 key열 이름 뒤에 붙는다.

 

 

- 기준 열 이름이 다를 때.

df3 = pd.DataFrame({"lkey":list("bbacaab"),"data1:range(7)})

df4 = pd.DataFrame({"rkey":list("abd"),"data2:range(3)})

 

pd.merge(df3,df4,left_on="lkey",right_on = "rkey")

 

- 한 쪽 데이터프레임은 index 기준.

left1 = pd.DataFrame({"key" : ["a","b","a","a","b","c"], "value" : range(6)})

right1 = pd.DataFrame({"group_val" : [3.5,7]}, index=["a","b"])

 

pd.merge(left1,right1,left_on = "key",right_index=True)

pd.merge(right1,left1,left_index = True, right_on = "key")

pd.merge(left2, right2, how="outer", left_index = True, right_index = True)

 

 

 

2. 데이터베이스처럼 DataFrame 합치기

- concatenating : 연결, 이어붙이기

s1 = pd.Series([0,1], index = ["a","b"])

s2 = pd.Series([2,3,4],index=["c","d","e"])

s3 = pd.Series([5,6],index=["f","g"]

 

pd.concat([s1,s2,s3]) : Series로 출력

pd.concat([s1,s2,s3],axis=1) : DataFrame으로 출력

 

s4 = pd.concat([s1*5,s3])

 

- 컬럼의 이름을 지정 할 때

pd.concat([s1,s2,s3],axis=1,keys=["one","two"three"])

 

- 데이터프레임일 경우

df1 = pd.DataFrame(np.arange(6),reshape(3,2),index=["a","b","c"],columns=["one","two"])

df2 = pd.DataFrame(5+np.arange(4),reshape(2,2),index=["a","c"],columns=["three","four"])

 

pd.concat([df1,df2],axis=1)

 

df3 = pd.DataFrame(np.random.randn(3,4),columns=["a","b","c","d"])

df4 = pd.DataFrame(np.random.randn(2,3),columns=["b","d","a"])

 

pd.concat([df3,df4], ignore_index=True) : 인덱스 무시하고 인덱스 다시 부여해준다.

 

- 그 밖의 인자

join = "inner" : 공통된 인덱스만 남긴다

join_axes = [df1.index] : df1의 인덱스에 맞춘다.

 

 

 

 

 

3. 계층적 인덱싱 이해하기

- 시리즈

s = pd.Series(np.random.randn(10), index =[["a","a","a","b","b","b","c","c","d","d"],[1,2,3,1,2,3,1,2,2,3]])

s.index

s["b"]

s["b":"c"]

s[("b",3)] : b계층의 3번째 값

s[:,2] : 모든 계층의 2번째 값

 

- 데이터프레임

df = pd.DataFrame(np.arange(12).reshape((4,3)),index=[["a","a","b","b"],[1,2,1,2]],columns=[["Seoul","Seoul","Busan"],["Green","Red","Green"]]) => 인덱스와 칼럼 모두 2차원 설정으로 계층 표현

 

df.index.names = ["key1","key2"]

df.columns.names=["city","color"]

 

df["Seoul"] : 서울에 해당하는 하위계층만 나온다.

df[("Seoul","Green")] : 시리즈형태로 하위계층 표현

df.loc["a"]

df.loc[("a",1)] : 행을 2차원으로 표현

df.loc["b",("Seoul","Red")] : 열을 2차원으로 표현

df.loc[("b",2),"Busan"]

df.loc[("b",1),("Seoul","Green")]

 

- 데이터프레임 정렬

df.sort_index(axis = 0, level =0) : 행방향으로 key1기준으로 정렬

df.sort_index(axis = 0, level = 1) : 행방향으로 key2기준으로 정렬

df.sort_index(axis = 0, level = "key2") : 행방향으로 key2 기준으로 정렬

 

df.sort_index(axis=1,level=0)

df.sort_index(axis=1,level=1)

 

df.sort_values(by=("Busan","Green")) : 부산의 그린 값 기준

 

 

- 데이터프레임 계산

df.sum(axis=0, level=0) : ab로 나누어 합을 구한다.

df.sum(axis=0, level=1) : 1,2로 나누어 합을 구한다.

df.mean(axis=1,level="color") : color 열로 나누어 열방향으로 평균 구한다.

 

- 계층으로 변환

df2 = pd.DataFrame({"a" : range(7), "b" : range(7,0,-1), "c" : ["one","one","one","two","two","two","two"],"d":[0,1,2,0,1,2,3]})

 

df3 = df2.set_index(["c","d"]) : c,d가 계층적 인덱스가 된다.

df2.set_index(["c","d"],drop=False) : c,d 열 그대로 있는다.

df3

df3.reset_index() : 원위치

 

 

 

4. 계층적 색인으로 재형성하기

stack : 데이터의 칼럼을 로우로 피벗 또는 회전시킨다.

unstack : 로우를 칼럼으로 피벗시킨다.

 

df4 = pd.DataFrame(np.arange(6),reshape((2,3)).index=["Seoul","Busan"],columns=["one","two","three"])

df4.index.name = "city"

df4.columns.name = "number"

 

df5 = df4.stack() : 컬럼을 열의 하위계층 인덱스로 변환

df5.unstack() : 최하위 인덱스를 컬럼으로 올려준다.

 

df5.unstack(level=0) : 0번 인덱스에 해당하는 최상위계층 인덱스를 컬럼으로 올려준다.

df5.unstack(level="city")

 

-

a1 = pd.Series([0,1,2,3],index = ["a","b","c","d"])

a2 = pd.Series([4,5,6], index = ["c","d","e"])

a3 = pd.concat([a1,a2],keys=["one","two"])

=> 계층적

 

a3.unstack()

 

df6 = pd.DataFrame({"left":df5, "right" : df5+5},columns=["left","right"])

df6.columns.name = "side"

df6

 

df6.unstack() : 최하위에서 최하위로 간다.

df6.unstack(level="city")

df6.unstack(level="city").stack(level="side")

 

- stack은 누락된 데이터 자동으로 걸러낸다.

s1 = Series([0, 1, 2, 3], index=['a', 'b', 'c', 'd'])

s2 = Series([4, 5, 6], index=['c', 'd', 'e'])

data2 = pd.concat([s1, s2], keys=['one', 'two'])

data2.unstack()

data2.unstack().stack() : 자동으로 걸러낸다.

data2.unstack().stack(dropna=False) : na를 삭제하지 않는다.

 

 

 

 

5. 데이터프레임 데이터 변형하기 - 중복 제거하기

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

df.duplicated() : 중복된 행들을 마스크로 표현해준다.

df.drop_duplicates() : 중복된 행들을 제거해준 데이터프레임 도출

 

df["v1"] = np.arange(7)

df.drop_duplicates() : 아무것도 삭제되지 않는다. , v1으로 인하여 다 독립적이기 때문에

df.drop_duplicates(["k1"])

df.drop_duplicates(["k1","k2"],keep = "last") : 남길 때 맨 처음 것을 남길지 맨 마지막 것을 남길지 선택이 keep

df.drop_duplicates(["k1","k2"])

 

 

 

 

6. 데이터프레임 데이터 변형하기 - 맵핑해서 새로운 열 추가

- 함수 적용과 맵핑, NumPy의 유니버설 함수처럼 적용

apply : 각 로우나 칼럼의 1차원 배열에 함수를 적용

applymap : 배열의 각 원소에 함수를 적용

map : Series가 각 원소에 함수를 적용

 

1. apply

frame = DataFrame(np.random.randn(4, 3), columns=list('bde'), index=['Utah', 'Ohio', 'Texas', 'Oregon'])

 

f = lambda x: x.max() - x.min()

frame.apply(f)

frame.apply(f, axis=1)

 

def f(x):

return Series([x.min(), x.max()], index=['min', 'max'])

 

frame.apply(f)

 

2. applymap

format = lambda x: '[%.2f]' % x

frame.applymap(format)

 

3. map

frame['e'].map(format)

 

 

- 새로운 열 추가

df2 = pd.DataFrame({"food" : ["bacon","pulled pork","bacon","Pastrami","corned beef","Bacon","pastrami","honey ham","nava lox"], "ounces" : [4,3,12,6,7.5,8,3,5,6]})

 

=> 대소문자 차이 존재

meat_to_animal = { "bacon" : "pig", "pulled pork" : "pig", "pastremi" : "cow" , "corned beef" : "cow" , "honey ham" : "pig", "nava loc" : "salmon"}

 

df2["animal"] = df2["food"].apply(lambda x: meat_to_animal[x.lower()]) : lower은 소문자로 치환

 

 

 

 

7. 데이터프레임 데이터 변형하기 - 값 치환하기

data = pd.Series([1.,-999.,2.,-999.,-1000.,3.])

data2 = data.replace(-999,np.nan)

data2.replace(np.nan, 0)

data2.fillna(0)

 

data.replace([-999, -1000], np.nan) : -999, -1000 모두 np.nan으로 치환

 

- -999를 np.nan로 치환, -1000을 0으로 치환

data.replace([-999, -1000], [np.nan, 0])

data.replace({-999: np.nan, -1000: 0})

 

 

 

 

8. 데이터프레임 데이터 변형하기

- 개별화와 양자화(카테고리, 범주형 데이터)

-> 카테고리 자료형 : 사회과학 서베이 데이터셋에서 자주 보인다

df3 = pd.DataFrame({"id" : [1,2,3,4,5,6], "raw_grade":["a","b","c","a","a","a","e"]})

df3["grade"] = df3["raw_grade"].astype("category")

df3["grade"] : 확인할 수 있다.

 

- 카테고리 값 변경

df3["grade"].cat.categories

df3["grade"].cat.categories = ["very good","good","very bad"]

 

- 카테고리 값 추가

df3["grade] = df3["grade"].cat.set_categories(["very bad","bad","medium","good","very good"])

 

- 정렬

df3.sort_values(by = "grade") : 카테고리화에서 정의된 순서대로 오름차순으로 정렬된다.

 

- 숫자데이터를 카테고리화 : 조건을 부여하여 카테고리화 x -> 판다스에서는 더 편리한 방법

ages= [20, 22, 25, 27, 21, 23, 37, 31, 61, 45, 41, 32]

bins = [18,25,35,60,100]

 

cats = pd.cut(ages, bins)

cats = pd.cut(ages, bins, right=False) : 괄호와 대괄호 위치 변경

group_names = ["Youth","YoungAdult","MiddleAged","Senior"]

cats = pd.cut(ages, bins, labels=group_names) : 그룹의 이름 직접 넘겨 줄 수 있다.

 

cats.categories : 객체, 그룹 이름이 담긴 배열

cats.codes : 속성,

cats.value_counts() : 개수 확인

 

 

- 숫자데이터를 카테고리화 : 그룹의 경계값을 넘기지 않고 그룹의 개수를 넘겨준다

=> 최소 값과 최대 값을 기준으로 균등한 길이의 그룹을 자동으로 계산한다.

data = np.random.rand(20)

pd.cut(data,4, precision = 2) :

 

- 숫자데이터를 카테고리화 : 그룹의 경계값을 넘기지 않고 그룹의 개수를 넘겨준다

=> 분위수로 나눈다.

data2 = np.random.randn(1000)

cats = pd.qcut(data2, 4)

pd.qcut(data, [0, 0.1, 0.5, 0.9, 1.]) : 분위수를 직접 지정할 수도 있다.

 

 

 

 

 

9. 데이터프레임 데이터 변형하기 - 특이값 찾아내고 제외하기

np.random.seed(12345)

data = DataFrame(np.random.randn(1000, 4))

data.describe()

 

col = data[3]

col[np.abs(col) > 3]

 

data[(np.abs(data) > 3).any(1)] : 3을 초과하는 값이 들어있는 모든 로우 선택한다. any메소드 사용

 

data[np.abs(data) > 3] = np.sign(data) * 3

data.describe()

 

-> -3이나 3을 초과하는 값을 -3 혹은 3으로 지정할 수 있다.

np.sign은 유니버설 함수, 주어진 값이 부호에 따라 1이나 -1이 담긴 배열을 반환한다.