프로그래밍/Pandas

Pandas - 판다스 연산

LeeSeunghyuk 2020. 12. 30. 12:16
반응형

안녕하세요

이승혁입니다.

 

오늘은 지난번 공부했던 시리즈와 데이터프레임에 대한 연산입니다.

 

# 판다스 객체의 산술 연산 3단계 프로세스

 

행/ 열 인덱스를 기준으로 모든 원소정렬

동일 위치 원소끼리 1:1 대응

대응 되는 원소끼리 연산 진행

( 대응 원소가 없다면 NaN 처리 )

 

### Series 연산

 

시리즈 객체에 숫자를 더하면 각 원소에 같은 숫자를 더합니다.

결과는 시리즈 객체로 반환됩니다.

사칙연산 모두 가능합니다.

 

1) 시리즈와 숫자 연산

 

 시리즈 객체   연산자( +,-,*,/  )  숫자

 

import pandas as pd
data=[1,2,3,4,5]
data=pd.Series(data,index=['A','B','C','D','E'])

print(data)
print('\n\n')
print(data+10)

 

2) 시리즈와 시리즈 연산

import pandas as pd
data=[1,2,3,4,5]
data=pd.Series(data,index=['A','B','C','D','E'])
data2=[11,12,13,14,15]
data2=pd.Series(data2,index=['C','B','A','E','D'])

add=data+data2
sub=data-data2
mul=data*data2
div=data/data2

df=pd.DataFrame([add,sub,mul,div],index=['덧셈','뺄셈','곱셈','나눗셈'])
print(df)

 

각각의 연산 결과를 저장하여, 그 시리즈들을 사용해 데이터 프레임으로 결과를 확인했습니다.

 

인덱스로 주어진 알파벳의 순서가 다르지만, 같은 알파벳끼리 연산이 진행되었습니다.

이는 3단계 프로세스의 정렬, 대응, 연산 과정을 통해 이루어졌습니다.

 

두 시리즈의 원소 개수가 다르거나, 개수는 같지만 인덱스가 다를 수 있습니다.

이때 연산은 NaN 처리를 하는데 이는 유효한 값을 가지지 않는다는 의미입니다.

 

또는 개수도 같고, 인덱스도 같지만 하나 혹은 모두 NaN을 갖는 경우

결과도 NaN 처리됩니다.

 

3) NaN

 

 

# 원소의 개수, 인덱스가 다른경우
import pandas as pd
import numpy as np
data=[np.nan,np.nan,10,20,np.nan]
fruit=['사과','배','포도','바나나','오렌지']
s1=pd.Series(data[0:1],index=fruit[0:1])
print(s1,'\n\n')
s2=pd.Series(data[1:5],index=fruit[1:5])
print(s2,'\n\n')
print(s1+s2)

series1 : 인덱스 - 사과                               값 - NaN

series2 : 인덱스 - 배,포도,바나나,오렌지        값 - NaN, 10, 20, NaN

 

s1 + s2 : 인덱스 - 바나나,배,사과,오렌지,포도      값 - NaN, NaN, NaN, NaN, NaN

 

인덱스가 합집합의 개념으로 모두 사용되었습니다.

또한 포도, 바나나는 10, 20의 값을 가졌지만 다른 시리즈에 값이 존재하지않아

최종적으로는 NaN 처리가 되었습니다.

 

4) 연산 메소드

 

NaN 처리를 피하기 위해 fill_value 옵션을 사용할 수 있습니다.

fill_value 연산을 사용해 NaN 대신 사용할 값을 지정할 수 있습니다.

 

import pandas as pd
import numpy as np

score=pd.Series({'국어':np.nan,'수학':50,'영어':100})
score2=pd.Series({'국어':80,'영어':20,'체육':50})

add=score.add(score2,fill_value=0)
sub=score.sub(score2,fill_value=0)
mul=score.mul(score2,fill_value=0)
div=score.div(score2,fill_value=0)

df=pd.DataFrame([add,sub,mul,div],index=['덧셈','뺄셈','곱셈','나눗셈'])
print(df)

 

 

### 다른 시리즈에 인덱스가 존재하지 않는경우는 fill_value를 사용해도 NaN처리

import pandas as pd
import numpy as np

score=pd.Series({'국어':np.nan,'수학':np.nan,'영어':100})
score2=pd.Series({'국어':80,'영어':20,'체육':50})

add=score.add(score2,fill_value=0)
sub=score.sub(score2,fill_value=0)
mul=score.mul(score2,fill_value=0)
div=score.div(score2,fill_value=0)

df=pd.DataFrame([add,sub,mul,div],index=['덧셈','뺄셈','곱셈','나눗셈'])
df

score2 에는 수학 인덱스 x

 

제 생각에는 정렬 -> 대응 -> 연산 의 과정 후 처리된

NaN만을 fill_value 사용해 처리하는 것 같습니다.

 

다른 시리즈에 '수학' 인덱스가 없어 대응 되는 것이 없어

바로 NaN 처리를 해버리는 것 같습니다.

 

자세하게는 잘 모르겠습니다.

 

결론으로 fill_value를 사용하기 위해서는 양쪽 모두 인덱스가 존재,

둘 중 하나만 NaN값을 가져야 한다는 것입니다.

 


 

### 데이터 프레임 연산

 

여러개 시리즈의 집합이므로 시리즈 연산의 확장으로 생각하시면 됩니다.

 

행/열 인덱스 기준 정렬

일대응 대응 원소

대응 원소 연산 처리

 

1) 데이터프레임과 숫자 연산

 

어떤 숫자를 더하면 모든 원소에 숫자를 더합니다.

사칙연산 모두 가능하며 기존 데이터 프레임은 유지됩니다.

새로운 계산값은 데이터 프레임 객체로 반환됩니다.

 

예제로 사용할 데이터는 seaborn 라이브러리에서 제공하는 데이터셋입니다.

타이타닉 데이터로 승객의 생존 여부를 나타내는 데이터 입니다.

 

타이타닉 데이터)

 

인덱스는 각 탑승객의 정보입니다.

 

import pandas as pd
import seaborn as sns

titanic=sns.load_dataset('titanic')
df=titanic[['age','fare']].head() # 첫 다섯개 행만 표시

print(df,'\n')

print(df+10)

 

2) 데이터프레임과 데이터프레임 연산

 

같은 행, 같은 열에 위치한 원소끼리 계산합니다.

동일 위치의 원소끼리 계산한 결과값을 원래 위치에 다시 입력합니다.

시리즈와 마찬가지로 한쪽에 존재하지 않거나 NaN이면 NaN처리합니다.

import pandas as pd
import seaborn as sns

titanic=sns.load_dataset('titanic')
df=titanic[['age','fare']][5:10]
df2=df+10

print(df,'\n')
print(df2,'\n')
print(df2-df)

 

 

판다스 데이터 프레임과 시리즈 객체에 대한 연산을 간단하게 알아보았습니다.

 

다음 실습도 기대해 주세요

 

 

감사합니다!!!!

 

 

 

반응형