본문 바로가기

순이코딩/Python

[Python] 파이썬 라이브러리 - pandas library(2) : DataFrame

728x90
반응형

 


 

1. pandas library

 

저번의 Sereies에 이어서 DataFrame에 대해서 알아보겠습니다.

 

3) DataFrame

 

DataFrame은 2차원 데이터에서 사용되는 자료구조입니다. 엑셀, csv, DB, ApI 등등 불러올 수 있으나 다시 재구성해야 합니다. 이 DataFrame은 쉽게 말해 Series의 모임이라고 할 수 있습니다. 

 

■ DataFrame 생성

 

DataFrame을 생성하는 방법 첫 번째는 딕셔너리를 통해 컬럼단위로 생성하는 것 입니다.

data = {'ITPM':[463,9543,57],
        '업무분석가':[544,11226,68],
       'IT아키텍트':[518,10672,64],
       'UIUX개발자':[291,6003,36]}

위와 같은 딕셔너리가 있을 때, pd.DataFrame(data)를 통해 DataFrame화 할 수 있습니다. pandas에서 제공하는 DataFrame으로 변환하겠다는 것입니다.

 

이렇게 자동으로 key값은 컬럼으로 들어가고 value가 값에 들어갔으며 인데스 번호가 자동으로 생성되어 표 형태로 나타난 것을 볼 수 있습니다. Series와 마찬가지로 인덱스 명을 부여할 수 있습니다. 당연히 Series처럼 DataFrame화 하면서 부여할 수도 있고 이후에 수정할 수도 있습니다.

df.index = ['일평균임금','월평균임금', '시간평균임금']

# DataFrame화와 인덱스명 부여를 동시에
df = pd.DataFrame(data, index = ['일평균임금','월평균임금','시간평균임금'])

 

두 번째 방법입니다. list를 활용한 방법입니다.

data2 = [[463,9543,57],
         [544,11226,68],
         [518,10672,64],
         [291,6003,36]]

columns = ['일평균임금','월평균임금','시간평균임금']
row = ['ITPM','업무분석가','IT아키텍트','UIUX개발자']
df = pd.DataFrame(data2, index=row, columns=columns)
df

위의 코드를 보면 data2라는 데이터 값을 담은 2차원 리스트가 있고, 컬럼명을 담은 columns리스트, 인덱스명을 담은 row리스트가 있습니다.

그리고 DataFrame화를 하면서 순서대로 (데이터 값, index=인덱스명 리스트, columns=컬럼명 리스트)를 넣었습니다. 위와 같은 DataFrame 형의 표가 나타난 것을 볼 수 있습니다.

 

두 번째 방법으로 DataFrame화를 하면서 눈치채셨겠지만 DataFrame은 values값과 index값, columns값을 가지고 있기 때문에 각자 추출도 가능하고 index와 columns의 위치를 바꾸는 것도 가능합니다.

컬럼과 인덱스를 전치
values,index, columns에 각각 접근

 

■ DataFrame 인덱싱, 슬라이싱

 

① 열접근(컬럼 선택)

DataFrame명['컬럼명']

열접근 방법입니다. 기본적으로 DataFrame은 열에 접근합니다. 그렇기 때문에 위와 같은 문법으로 작성할 경우 컬럼명을 적어줘야 합니다. 그러나 DataFrame은 2차원 데이터에서 사용되는 데이터 구조이기 때문에 DataFrame형으로 뽑으려면 대괄호를 이중으로 해주어야 합니다.

 

DataFrame에 추가할 때는 다음과 같이 추가합니다. 값을 수정할 때도 수정할 컬럼명을 입력하고 데이터값을 수정해 주면 됩니다.

DataFrame명['추가할 컬럼명']=[데이터값]

#
df['정보보안전문가']=[362,7426,45]

 

DataFrame은 기본적으로 열 접근을 하기 때문에 바로 열(컬럼)에 접근해 슬라이싱은 불가능합니다.

df[0:2]

이렇게 슬라이싱을 했을 때, 아래의 그림에서 보듯 결과는 행이 슬라이싱 되었습니다.

 

그렇다고 컬럼(열)은 인덱싱으로 접근하고 인덱스(행)는 슬라이싱으로만 접근가능한 것은 아닙니다. 이때 사용하는 것이 인덱서입니다.

인덱서(indexer)란 DataFrame 객체에 대해서 "함수"가 아닌 "속성"으로써 행과 열을 한 번에 인덱싱/슬라이싱 할 수 있는 기능입니다. "속성"이기 때문에 [] 대괄호를 사용합니다.

여기서 저번 Series 글에서 언급했던 loc와 iloc를 사용합니다.


▶ loc[] 인덱서 : "인덱스 명"과 "컬럼 명"을 가지고 값을 인덱싱/슬라이싱

▶ iloc[] 인덱서 : "인덱스 번호(행 번호)"과 "컬럼 번호(열 번호)"를 가지고 값을 인덱싱/슬라이싱


인덱서를 사용하지 않고 바로 인덱스에 접근하게 되면 에러가 생깁니다. 길게 쓰여있지만 결국 젤 마지막 줄에 보면 KeyError라고 쓰여있습니다.

'너 컬럼(열)으로 접근해야지 왜 이상하게 접근하냐' 하면서 에러가 발생하는 것입니다.

 

이때 인덱서를 사용합니다. 아래와 같이 행 인덱싱이 잘되고 있는 것을 확인할 수 있습니다.

df.loc['시간평균임금']

보기 편하게 대괄호로 한번 더 감쌌습니다.

 

loc와 iloc를 통한 인덱싱 기본 형은 다음과 같습니다.

# loc 인덱서
DataFrame명.loc['인덱스 명'{,'컬럼 명'}]

# iloc 인덱서
DataFrame명.iloc['행 번호'{,'열 번호'}]

##  { }는 생략가능!!

 

loc와 iloc는 한 번에 행과 열에 접근하기 때문에 기본적으로 DataFrame을 인덱싱, 슬라이싱 할 때는 사용하는 것이 오히려 헷갈리지 않고 더 좋습니다.

loc와 iloc를 통한 슬라이싱 기본 형은 다음과 같습니다.

# loc → 끝값 포함 (문자이기 때문에 포함)
DataFrame명.loc[행의 시작값:행의 끝값{,열의 시작값:열의 끝값}]

# iloc → 끝값 미포함
DataFrame명.iloc[행의 시작값:행의 끝값{,열의 시작값:열의 끝값}]

 

기본 형을 보면서 왜 열 접근이 기본인데 열이 생략되는지 헷갈리실 수도 있겠지만 당연히 열 접근이 기본이기 때문에 생략이 가능합니다. 열은 기본적으로 다 접근하게 돼있으므로 굳이 전체 열에 접근한다면 생략해도 됩니다. 그러나 행은 기본이 아니기 때문에 접근할 값을 지정해 주는 것입니다. 

 

df.loc['월평균임금':'시간평균임금','업무분석가':'UIUX개발자']

 

이렇게 '월평균임금'부터 '시간평균임금'까지 행을 슬라이싱 하고, 열에서는 '업무분석가'부터 'UIUX개발자'까지 슬라이싱해 출력이 됩니다.

 

■ DataFrame Boolean 인덱싱

 

Boolean 인덱싱은 마찬가지로 mask를 활용합니다. 예를 들어 일평균임금이 400 이상인 컬럼만 출력하고 싶다고 하겠습니다. 먼저 DataFrame을 전치시킨 후 진행하도록 하겠습니다. DataFrame은 기본적으로 열 접근이 우선이기 때문입니다. boolean값은 뽑아낼 수 있으나 다시 DataFrame자료로 보기 위해서는 조건을 걸고자 하는 것이 열에 있어야 합니다.

# 전치
df = df.T

# 조건으로 Boolean 인덱싱 (일평균임금이 400이상)
mask = df.loc[:,'일평균임금'] >= 400

# 해당하는 값 출력
diplay(df[maks])

 

■ DataFrame 값의 카운팅, 정렬

 

 

pandas.read_csv('경로&파일명.확장자',encoding='방식', index_col='컬럼명')

데이터 파일을 불러올 때, 위의 코드와 같이 불러올 수 있습니다.

encoding 방식(한글로 불러오는 방법)은 3가지로 euc-kr, utf-8, cp949 이 중에 하나를 입력하면 됩니다. encoding방식과 index_col은 생략가능합니다.

 

저는 위와 같은 데이터를 불러왔습니다.

 

먼저 각각의 값이 나온 횟수를 세어주는 기능이 있는 함수입니다. 다음과 같은 코드를 사용하면 '지역' 컬럼에서 값이 나온 횟수를 세어줍니다.

NaN은 데이터 값이 아예 없다는 의미이므로 count 되지 않습니다. 

pop['지역'].value_counts()

 

sort_index()를 사용하면 설정한 기준에 따라 정렬할 수 있습니다. 기본값은 오름차순으로 설정되어 있습니다. 아래의 그림에서 소괄호 안에 있는 ascending=True 가 그 의미입니다. 현재 True값인 것을 False 값을 주면 내림차순으로 정렬됩니다.

pop.sort_index()

 

인덱스 기준이 아닌 컬럼을 기준으로 정렬할 수도 있습니다. 이렇게 결과가 다르게 출력되기 때문에 본인이 필요한 것에 맞추어 정렬을 하면 됩니다.

# 열접근을 통해 접근
pop['2015'].sort_values()

# DataFrame에서 기준을 정해서 정렬
pop.sort_values('2015')

 

이중 정렬(기준 1에 맞추어 정렬 후, 기준 1이 같은 값일 때 기준 2에 맞추어 정렬)을 하고 싶은 경우에는 컬럼명을 컴마(,)로 구분해 주어 작성하면 됩니다.

 

 

■ DataFrame 연산

 

axis는 축의 방향을 뜻 합니다.  axis=0은 행방향, axis=1은 열 방향을 의미합니다.

 

sum()이라는 함수가 있습니다. 합계를 구하는 함수입니다. 아래와 같은 DataFrame이 있을 때, 아래의 코드를 실행하면 코드 다음의 그림처럼 각 반별 점수 총합이 구해지게 됩니다.

score.sum(axis=0)

 

axis=1로 바꾸어 실행을 하면 이번에는 과목별 반의 점수 총합이 연산되는 것을 볼 수 있습니다.

 

■ DataFrame 행/열 삭제

 

DataFrame에서 행을 삭제할 때는 drop()을 사용합니다. 소괄호 안에 지우고 싶은 행의 인덱스명/인덱스번호를 넣게 되는데 drop을 실행해도 삭제가 되지 않는 것을 볼 수 있습니다. 그 이유는 inplace='False'가 기본값으로 설정되어 있기 때문입니다. 그렇기 때문에 inplace=True를 적어주어야 확실하게 삭제가 됩니다.

score.drop('DB', inplace=True)

 

열을 삭제할 때는 del 객체를 사용합니다. del 객체는 inplace 없이 바로 반영이 됩니다.

 

■ apply() 함수

 

apply() 함수는 pandas 객체(Series, DataFrame)에 "열" 혹은 "행"에 대해 함수를 적용하게 해주는 메소드 입니다. 또 pandas 라이브러리에 다른 라이브러리의 함수를 적용하는 방법으로 사용되며 numpy의 라이브러리를 엮을 때 사용합니다.

data = {
    'Name': ['John', 'Anna', 'Peter', 'Linda'],
    'Email': ['john@gmail.com', 'anna@yahoo.com', 'peter@gmail.com', 'linda@outlook.com']
}
df = pd.DataFrame(data)
df

 

위와 같은 DataFrame이 있을 때 만약 Email주소의 도메인만 추출하려고 한다면 Email컬럼의 각 요소에 접근해야 합니다. 이때 apply() 함수를 사용합니다. 아래와 같이 도메인만 추출되어 컬럼으로 추가된 것을 확인할 수 있습니다.

# email주소에서 도메인만 추출하는 함수 생성
def extract_domain(email) :
    return email.split('@')[1]
    
# apply함수를 사용해 DataFrame의 'Email'컬럼에 접근 / 새 컬럼 생성해 넣기
df['Domain']= df['Email'].apply(extract_domain)

 

applymap() 함수를 사용하면 요소 전체에 접근해 함수를 적용시킵니다.

# 변수에 10을 더하는 함수 생성
def plus(num):
    return num+10
    
# applymap() 함수 사용
score.applymap(plus)

 

■ 데이터 병합

 

데이터를 병합하는 함수에는 2가지가 있습니다. merge()concat()입니다.

Merge()는 병합이라는 뜻으로 두 개의 pandas 객체를 합칠 때 특정 '컬럼'의 값을 기준으로 합치는 함수 입니다. 

DataFrame명.merge(left_table,right_table, on = '기준 컬럼', how = 'join 방식')

# how는 inner, outer, left, right 등등

 

아래와 같은 pandas 객체가 2개 있습니다. 여기에 merge()함수를 적용하겠습니다. 

pd.merge(H_info,R_info, on='이름', how='inner')

 

'이름'칼럼을 기준으로 inner조인 방식으로 병합을 진행하니 아래와 같이 병합이 실행된 것을 볼 수 있습니다.

 

concat() 함수는 이어 붙이다는 뜻으로 축(axis)을 기준으로 병합합니다. 

pd.concat([df1, df2,...],axis=0, join='outer', ignore_index=False)

axis는 축의 방향을 설정하고, join은 merge에서 how와 같은 역할입니다. ignore_index는 True값을 주면 인덱스를 새로 부여하게 됩니다. 주로 똑같은 컬럼 또는 똑같은 인덱스의 다른 테이블을 하나의 테이블로 합치고자 할 때 활용합니다.

data3 ={
    '이름' : ['홍길동','이순신'],
    '나이' : ['23','55'],
    '성별' : ['남','남']    
}
data4 = {
    '이름' : ['신사임당','장보고'],
    '나이' : ['48','22'],
    '성별' : ['여','남']   
}

pd.concat([df1,df2])

 

axis값과 join방식과 ignore_index값을 따로 설정하지 않았는데 기본값인 axis=0, outer조인방식으로 병합이 되었고 index를 새로 부여하지 않았기 때문에 인덱스 번호가 0,1,0,1로 설정되었습니다.

이렇게 병합을 진행할 때, 컬럼 또는 인덱스가 완전히 동일하지 않으면 결측치가 발생합니다. 이런 경우 결측치를 채우는 함수가 있습니다.

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

fillna() 함수는 소괄호 안에 결측치를 채울 값을 넣고 병합을 진행하면 결측치가 자동으로 입력한 값으로 모두 바뀌어 들어갑니다.

728x90
반응형