본문 바로가기
카테고리 없음

Python Pandas 반드시 알아야할 기본 개념

by 뷰티풀스택 2023. 4. 30.
반응형

최근 ChatGPT로 인해 자연어처리에 대한 관심이 높아지고 있는데 이를 잘 하기 위해서는 지저분한 데이터들이 들어왔을때에 깨끗하게 정리하기 위한 Regular Expression이 중요하고, 다양한 형태로 가공하기 위해 Pandas가 매우 매우 중요하다. 오늘은 Pandas에 대해 핵심적인 내용들을 정리해보도록 하겠다.

 

 

 

1. 판다스 개념 잡기

판다스는 가로 행이 아닌, 세로 열을 기준으로 만든 데이터구조이다. 가로가 아닌 세로 열의 관점에서 모든 데이터를 바라보아야 한다.이 개념이 머리속에 확실하게 와닿지 않는다면 판다스를 쓸데마다 항상 헷갈리고 오히려 불편함을 느낄 것이다. 예를들면, 주로 우리는 일상 업무속에서 어제까지 데이터 모아서 보자 등의 Row, 가로 행 기준에서 데이터를 인식하는 경향이 있기 때문이다. Row는 어떤 데이터의 기준이 아니라 세로 열들을 담아야하는 처리 기준으로 바라보아야 한다. 판다스에서는 이것을 Bucket 개념으로 다룬다. 즉, 아래의 경우 날짜별 데이터를 모은 것이 아니라, 상품명/색상/가격별 데이터를 모은 것인데 2022~2023년 내용들만 담는것이다. 그말이 그말같지만 정말 미묘한 개념적 차이를 뼈속까지 확실히 느껴야 앞으로 다양한 데이터 사이언스 작업들을 할때에 혼선되지 않을 것이다. 부디 꼭 이 개념이 중요함을 인지하기 바란다.

 

 

  • 시리즈 개념

우리는 무의식중에 가로행을 기준으로 생각할때가 많다. 1시에 한일들, 2시에 한일들... 하지만 판다스는 세로열이 중심이다. 판다스는 이러한 많은 열들을 모아서 다양한 처리를 도와주는 라이브러리라고 생각하면 된다. 여기서 말하는 세로열은 Series이고, Series를 모은 것이 DataFrame이다. 예를 들어, 아래의 화면은 순위 / 제목 / 스튜디오 / 매출 / 년도 총 5개의 시리즈가 모인 데이터프레임이다.

No index

시리즈 개념이 명확하게 와닿지 않으면 판다스를 쓰면 안될정도로 반드시 몸으로 느껴야한다. 안그러면 데이터를 뽑고 추가하고 병합하고 나누고 등등... 할때마다 계~~~속 헷갈리고 자신을 괴롭히게 된다. 꼭! 꼭! 기억하기를 간절히 바란다. 이후에는 세로 열이나 컬럼이라고 하지 않고 시리즈(Series)라고 지칭하겠다.

 

  • 인덱스
    인덱스도 마찬가지로 또하나의 시리즈로 인식을 해야한다. 인덱싱을 위한 인덱스 시리즈를  추가할 수도 있고 기존 시리지를 인덱스로 사용할 수도 있다. 참고로, 인덱스는 별도 분리된 공간에 존재한다고 생각하여야 한다. 그래서 인덱스를 "Title"로 잡았다고 기존 "Title"과 중복되는 것이 아니다. 방법은 csv 불러올때 미리 지정이 가능하고 이후에 별도로 지정도 가능하다. 참고로, 인덱스로 사용하려면 가장 하위레벨 정보를 사용해야한다. 그룹화할 수 있는 시리즈로 인덱스를 잡으면 통계형태로 재정리되니 주의해야한다.  No index 그림과 , Title Index, Studio Index 그림을 비교해보길 바란다.

pd.read_csv("movies.csv", index_col = "Title")

Title Index

 

df = df.set_index('Studio')

Studio Index

  • 기타: 여러가지 정보를 얻을 수 있는 함수들은 특별한 설명이 필요없어서 다음을 참조바란다
import pandas as pd

df = pd.read_csv('data/movies.csv')
print('head() ---------------------------')
print(df.head())

print('\n\ntail() ---------------------------')
print(df.tail())

print('\n\ninfo() ---------------------------')
print(df.info())

print('\n\ndescribe() ---------------------------')
print(df.describe())

print('\n\nshape & size ---------------------------')
print(df.shape)
print(df.size)

print('\n\ndtypes() ---------------------------')
print(df.dtypes)
head() ---------------------------
   Rank                         Title       Studio       Gross  Year
0     1             Avengers: Endgame  Buena Vista  $2,796.30   2019
1     2                        Avatar          Fox  $2,789.70   2009
2     3                       Titanic    Paramount  $2,187.50   1997
3     4  Star Wars: The Force Awakens  Buena Vista  $2,068.20   2015
4     5        Avengers: Infinity War  Buena Vista  $2,048.40   2018


tail() ---------------------------
     Rank                     Title           Studio     Gross  Year
777   778                 Yogi Bear  Warner Brothers  $201.60   2010
778   779       Garfield: The Movie              Fox  $200.80   2004
779   780               Cats & Dogs  Warner Brothers  $200.70   2001
780   781  The Hunt for Red October        Paramount  $200.50   1990
781   782                  Valkyrie              MGM  $200.30   2008


info() ---------------------------
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 782 entries, 0 to 781
Data columns (total 5 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   Rank    782 non-null    int64
 1   Title   782 non-null    object
 2   Studio  782 non-null    object
 3   Gross   782 non-null    object
 4   Year    782 non-null    int64
dtypes: int64(2), object(3)
memory usage: 30.7+ KB
None


describe() ---------------------------
             Rank         Year
count  782.000000   782.000000
mean   391.500000  2006.620205
std    225.888247    10.026227
min      1.000000  1939.000000
25%    196.250000  2001.000000
50%    391.500000  2009.000000
75%    586.750000  2014.000000
max    782.000000  2019.000000


shape & size ---------------------------
(782, 5)
3910

dtypes() ---------------------------
Rank       int64
Title     object
Studio    object
Gross     object
Year       int64
dtype: object

 

2. DataFrame 조작

  • iloc[ ]: 숫자 인덱스로 모든 시리즈의 값들을 추출할때 (주의!: ( )괄호가 아닌 [  ] 이다.)
df = pd.read_csv('data/movies.csv', index_col="Title")

print(df.iloc[2])

------------
Rank               3
Studio     Paramount
Gross     $2,187.50
Year            1997
Name: Titanic, dtype: object

 

  • loc[ ]: 이름 인덱스로 시리즈 값 추출 (주의!: ( )괄호가 아닌 [  ] 이다.)
df = pd.read_csv('data/movies.csv', index_col="Title")

print(df.loc['The Godfather'])


----------------
Rank            604
Studio    Paramount
Gross      $245.10
Year           1972
Name: The Godfather, dtype: object

 

  • sort_index(): 예를들어 인덱스를 Title로 했을때 이러한 경우 영화제목을 알파벳 순서로 정렬하는 경우에 유용하다.
df = pd.read_csv('data/movies.csv', index_col="Title")
sorted_df = df.sort_index()
print(sorted_df)


---------------
                                Rank           Studio       Gross  Year
Title
10,000 B.C.                      536  Warner Brothers    $269.80   2008
101 Dalmatians                   708      Buena Vista    $215.90   1961
101 Dalmatians                   425      Buena Vista    $320.70   1996
2 Fast 2 Furious                 632        Universal    $236.40   2003
2012                              93             Sony    $769.70   2009
...                              ...              ...         ...   ...
Yogi Bear                        778  Warner Brothers    $201.60   2010
You've Got Mail                  582  Warner Brothers    $250.80   1998
Your Name.                       356              FUN    $358.00   2017
Zootopia                          37      Buena Vista  $1,023.80   2016
xXx: The Return of Xander Cage   385        Paramount    $346.10   2017
sorted_df = df.sort_index(ascending=False)

 

  • sort_values(by=["...", "...", ...]: 여러 기준으로 정렬
# 최신 영화 기준으로, 알파벳 영화 제목으로 정렬할때

sorted_df = df.sort_values(by=['Year', 'Title'], ascending=[False, True])
print(sorted_df)


--------------
                     Rank       Studio       Gross  Year
Title
Aladdin                59  Buena Vista    $880.20   2019
Alita: Battle Angel   286          Fox    $404.90   2019
Avengers: Endgame       1  Buena Vista  $2,796.30   2019
Captain Marvel         22  Buena Vista  $1,128.30   2019
Dark Phoenix          603          Fox    $245.10   2019
...                   ...          ...         ...   ...
The Godfather         604    Paramount    $245.10   1972
The Jungle Book       755  Buena Vista    $205.80   1967
101 Dalmatians        708  Buena Vista    $215.90   1961
Bambi                 540          RKO    $267.40   1942
Gone with the Wind    288          MGM    $402.40   1939

[782 rows x 4 columns]

 

참고로, Title이 있는데도 4 columns로 나온다. 이것은 Title Series를 Index로 삼는순간 데이터가 아닌 index로 여기는 것이다. minor해 보일수 있지만 매우 중요한 개념이다. 즉, 데이터를 다룰때에 어떤 것을 데이터로 삼을지, 어떤 것을 인덱스로 삼을지 잘 고려해야 한다.

 

  • 필터링: 조건문을 활용해서 필터링할 수 있다. 여러가지 조건들을 and(&)와 or(|)로 결합할 수 있다.
filter = df['Year'] == 2000
df[filter]
------------------
                                Rank           Studio     Gross  Year
Title
Mission: Impossible II           175        Paramount  $546.40   2000
Gladiator                        237       Dreamworks  $460.60   2000
Cast Away                        261              Fox  $429.60   2000
What Women Want                  321        Paramount  $374.10   2000
Dinosaur                         375      Buena Vista  $349.80   2000


filter = df['Year'].between(2000, 2005)
df[filter]
------------------
                                               Rank           Studio       Gross  Year
Title
The Lord of the Rings: The Return of the King    24         New Line  $1,119.90   2003
Harry Potter and the Sorcerer's Stone            40  Warner Brothers    $975.10   2001
Finding Nemo                                     49      Buena Vista    $940.30   2003
The Lord of the Rings: The Two Towers            52         New Line    $926.00   2002
Shrek 2                                          53       Dreamworks    $919.80   2004
...                                             ...              ...         ...   ...
King Arthur                                     765      Buena Vista    $203.60   2004
Vanilla Sky                                     767        Paramount    $203.40   2001
Fun with Dick and Jane                          773             Sony    $202.00   2005
Garfield: The Movie                             779              Fox    $200.80   2004
Cats & Dogs                                     780  Warner Brothers    $200.70   2001
filter1 = df['Studio'] == 'Sony'
filter2 = df['Year'] == 2000
print(df[filter1 & filter2])

----------------
                                Rank Studio     Gross  Year
Title
Charlie's Angels                 548   Sony  $264.10   2000
Vertical Limit                   710   Sony  $215.70   2000
The Patriot                      712   Sony  $215.30   2000
Crouching Tiger, Hidden Dragon   724   Sony  $213.50   2000

 

  • 인덱스 필터링: 특별히 인덱스는 index 파라미터를 통해 다룰 수 있다.

예) 영화 제목을 소문자로 바꾸고 제목에 'dark'라는 단어가 있는 모든 영화를 찾을 경우

filter = df.index.str.lower().str.contains('dark')
df[filter]

------------------
                                Rank           Studio       Gross  Year
Title
Transformers: Dark of the Moon    23        Paramount  $1,123.80   2011
The Dark Knight Rises             27  Warner Brothers  $1,084.90   2012
The Dark Knight                   39  Warner Brothers  $1,004.90   2008
Thor: The Dark World             132      Buena Vista    $644.60   2013
Star Trek Into Darkness          232        Paramount    $467.40   2013
Fifty Shades Darker              309        Universal    $381.50   2017
Dark Shadows                     600  Warner Brothers    $245.50   2012
Dark Phoenix                     603              Fox    $245.10   2019

 

 

3. 그룹화 : Bucket

제일 처음에 Bucket 개념을 간단히 소개하였는데 Bucket은 다시한번 강조한다면 세로 열들의 데이터들이 모여진 데이터프레임안에서 특정 조건 또는 범위의 가로 줄의 값들을 담아내는 과정이라고 보면된다. 

예를들어, 영화사별로 그룹핑을 한다는 것은 영화사라는 컬럼을 그룹핑하는 것이 아니라 영화사라는 컬럼이 갖고 있는 값들이 있을때 그 값별로 그룹을 짓는 것이다. 미묘한 관점의 차이인데 꼭 이해하기를 바란다.

 

studio = df.groupby('Studio')
print(studio['Year'].count())

----------------------------
Studio
Artisan                     1
Buena Vista               125
CL                          1
China Film Corporation      1
Columbia                    5

 

  • 그룹 정렬
studio = df.groupby('Studio')
sorted_studio = studio['Year'].count().sort_values(ascending=False)

print(sorted_studio)
---------------------------
Studio
Warner Brothers           132
Buena Vista               125
Fox                       117
Universal                 109
Sony                       86
Paramount                  76
Dreamworks                 27
Lionsgate                  21
New Line                   16
...

 

  • Tip! 가격 등의 텍스트를 숫자로 바꾸는 방법: 판다스는 숫자안에 콤마, 달러 등의 기호가 들어가면 텍스트로 저장하게 되기 때문에 계산을 시도하면 오류가 발생된다. 그렇기 때문에 아래와 같이 변경해주어야 한다.
df["Gross"] = (df["Gross"]
               .str.replace("$", "")
               .str.replace(",", "")
               .astype(float)
)

print(df)
--------------------------------
                              Rank           Studio   Gross  Year
Title
Avengers: Endgame                1      Buena Vista  2796.3  2019
Avatar                           2              Fox  2789.7  2009
Titanic                          3        Paramount  2187.5  1997
Star Wars: The Force Awakens     4      Buena Vista  2068.2  2015
Avengers: Infinity War           5      Buena Vista  2048.4  2018
...                            ...              ...     ...   ...

 

Gross 시리즈가 숫자로 변경되었기 때문에 이제 그룹화하여 다양한 계산이 가능해진다.

df["Gross"] = (df["Gross"]
               .str.replace("$", "")
               .str.replace(",", "")
               .astype(float)
)

studio = df.groupby('Studio')
studio['Gross'].sum().sort_values(ascending=False)

------------------------------
Studio
Buena Vista               73585.0
Warner Brothers           58643.8
Fox                       50420.8
Universal                 44302.3
Sony                      32822.5
Paramount                 32486.0
Dreamworks                12260.4
Lionsgate                 10033.2
New Line                   6584.8


------------------------------
studio['Gross'].mean().sort_values(ascending=False)

Studio
HC                        870.300000
China Film Corporation    699.800000
Newmarket                 611.900000
Buena Vista               588.680000
Lionsgate                 477.771429
Dreamworks                454.088889

 

오늘은 가장 기본적이지만 중요한 개념과 기본 오퍼레이션에 대해 정리하였다. 다음시간에는 Series 객체에 대해서 더 자세히 알아보자.

반응형

댓글