[Python] Pandas 라이브러리 (Series 와 DataFrame)

    Pandas

    Pandas란?

    출처: elice

    Pandas는 구조화된 데이터를 효과적으로 처리하고 저장하는 Python 라이브러리 중 하나입니다.
    Panal Data System의 약자이며, Panal Data란 행과 열로된 엑셀과 유사한 Data를 의미해요.
    자료 정제 및 분석을 빠르고 쉽게 할 수 있는 자료구조와 관리 도구들을 가지고 있어요.
    또한 Array 계산에 특화된 Numpy, for 문없이 계산하는 벡터화 계산을 기반으로 설계되었어요.
    수치해석 도구인 SciPy, 자료분석 라이브러리인 statsmodels, scikit-learn, 시각화 도구인 matplotlib 등과 같이 사용해요.

    배열을 다루는 Numpy 와 Pandas 에는 큰 차이점이 있어요.
    Numpy는 같은 자료형에 대한 배열을 주로 다루고, Panda는 서로 다른 자료형을 다루는 것에 적합하다는 점입니다.

    잠깐! Pandas 공식 문서를 추천해드릴게요.

    - 10 minites to pandas: https://pandas.pydata.org/docs/user_guide/10min.html(링크)
    - Pandas cheetsheet: https://pandas.pydata.org/Pandas_Cheat_Sheet.pdf(링크)

    혹시 Jupyter Notebook 을 사용하신다면?
    아래 두 방법으로 도움말을 확인할 수 있어요.
    - pd.DataFrame?
    - pd.DataFrame(shift + tab + tab)

    이제 Pandas 의 자료형 중 Series와 DataFrame에 대해 알아보죠!!


    Series

    Series 란?

    Series 는 연속적인 값들로 이루어진 일차원 배열과 인덱스로 불리는 자료 라벨(label) 배열로 이루어진 객체입니다.
    Numpy의 array 가 보강된 형태이며 Value와 Index를 가지고 있어요.
    Series는 DataFrame과 비교하면서 1차원, Vector 로 표현해요.

    직접 확인해보죠. (pandas 는 별칭으로 pd를 사용해요.)

    import pandas as pd

    예시로 list를 사용해 Series 를 선언하겠습니다.

    import pandas as pd
    
    data = pd.Series([11,12,13,14])
    
    print(data)                    # 0    11
                                   # 1    12
                                   # 2    13
                                   # 3    14
                                   # dtype: int64

    Series는 몇 가지 특징이 있어요.

    • Value를 ndarray 형태로 가지고 있다.
    • dtype 매개변수로 데이터 타입을 지정할 수 있다.
    • index 매개변수로 인덱스를 지정할 수 있다.
    • 인덱스를 이용해 Value에 접근할 수 있다.
    • list와 dictionary를 사용해 Series를 생성할 수 있다
      • dictionary를 사용하면 index는 key를 사용하게 돼요.

    코드를 통해 하나씩 살펴볼게요.

    import pandas as pd
    
    # Value 의 type
    data = pd.Series([11,12,13,14])
    print(type(data))                  # <class 'pandas.core.series.Series'>
    print(type(data.values))           # <class 'numpy.ndarray'>
    print(data.values)                 # [11 12 13 14]
    
    # dtype 사용
    data = pd.Series([11, 12, 13, 14], dtype="float")
    print(data)                        # 0    11.0
                                       # 1    12.0
                                       # 2    13.0
                                       # 3    14.0
                                       # dtype: float64
                                       
    # index 사용                       
    data = pd.Series([11, 12, 13, 14], index=['a','b','c','d'])
    print(data)                        # a    11
                                       # b    12
                                       # c    13
                                       # d    14
                                       # dtype: int64
                                       
    # dictionary 사용
    score_dict = {
        'kay': 100,
        'kim': 90,
        'park': 80,
        'lee': 70
    }
    score = pd.Series(score_dict)
    print(score)                       # kay     100
                                       # kim      90
                                       # park     80
                                       # lee      70
                                       # dtype: int64

     


    DataFrame

    DataFrame이란?

    위에서 Series 를 알아봤죠? 이제 Series를 활용할 시간입니다.
    DataFrame 은 여러 개의 Series 가 모여서 행과 열을 이룬 데이터입니다.

    같은 크기의 자료들로 이루어진 열들을 차례로 모아 놓은 직사각현 모양의 자료형이죠.
    DataFrame의 열과 행은 각각 인덱스를 가지고 있어요.
    DataFrame는 Series와 비교하면서 2차원, Matrix로 표현해요.

    DataFrame 사용하기

    DataFrame 만들기

    DataFrame 은 아래와 같은 형식으로 선언합니다.

    import pandas as pd
    
    DataFrame = pd.DataFrame( )

    실제 DataFrame 을 만들어 볼게요. 여러 방법으로 만들 수 있어요.
    그중 가장 간단한 방법은 List 또는 Numpy array를 Value로 갖는 Dictionary를 사용하는 방법입니다.

    비교를 위해 Series 를 이용한 예시를 살펴볼까요?
    맨 마지막 결과를 살펴보시면 맨 왼편의 key는 index 가 되고, value는 column을 이루는 것을 알 수 있습니다.

    import pandas as pd
    
    gdp_dict = {
       'china': 1409250000,
       'japan': 516700000,
       'korea': 169320000,
       'usa': 2041280000,
    }
    gdp = pd.Series(gdp_dict)
    
    population_dict = {
       'china': 141500,
       'japan': 12718,
       'korea': 5180,
       'usa': 32676,
    }
    population = pd.Sreies(population_dict)
    
    country = pd.DataFrame({
       'gdp': gdp,
       'population': population,
    })
    
    print(country)
    ''' print결과
                  gdp  population
    china  1409250000      141500
    japan   516700000       12718
    korea   169320000        5180
    usa    2041280000       32676
    '''

    이제 간단하다고 소개한 방법을 살펴볼게요.
    List 를 Value로 같은 Dictionary를 활용하는 방법입니다.

    그럼 어떤 부분이 간단해진걸까요?
    하나의 Dictionary에 모든 값들을 담아서 각의 Dictionary 들을 Series로 선언해주는 과정을 생략할 수 있어요.

    아래 코드 중 set_index 함수를 사용하는 부분이 있습니다. DataFrame의 index를 data 안의 value로 대체하는 함수죠.
    이 함수를 사용하지 않으면 index는 0부터 부여된 숫자로 설정되고 country는 하나의 data column 이 됩니다.
    * print 결과 1과 print 결과 2를 비교하면 쉽게 이해할 수 있어요.

    import pandas as pd
    
    data = {
        'country': ['china', 'japan', 'korea', 'usa'],
        'gpd': [1409250000, 516700000, 169320000, 2041280000],
        'population': [141500, 12718, 5180, 32676]
    }
    country = pd.DataFrame(data)
    print(type(country))                                    #<class 'pandas.core.frame.DataFrame'>
    
    print(country)
    ''' print 결과 1
       country             gdp      population
     
    0    china       1409250000         141500
    1    japan        516700000          12718
    2    korea        169320000           5180
    3      usa       2041280000          32676
    '''
    
    country = country.set_index('country')                  # index 의 제목 설정하기
    print(country)
    ''' print 결과 2
                        gdp      population
    country 
    china        1409250000         141500
    japan         516700000          12718
    korea         169320000           5180
    usa          2041280000          32676
    '''

    DataFrame 속성

    DataFrame의 속성 중 아래 4가지 속성을 확인해볼게요.

    • .shape: 모양에 대한 함수
    • .size: 요소의 수에 대한 함수
    • .ndim: 차원에 대한 함수 (column과 달라요!)
    • .values: frame을 제외한 실제 data에 대한 함수

    위 4가지 속성을 보기 전에 주의할 점!
    DataFrame의 속성은 "Data" 에 대해서만 조회해요. 즉, "Index" 는 Frame 의 일부이기 때문에 조회 대상이 아닙니다.
    예시를 살펴보면서 이해하기로 해요. (앞서 만든 country라는 DataFrame을 활용할게요.)

    import pandas as pd
    
    print(country)
    ''' print 결과
                        gdp      population
    country 
    china        1409250000         141500
    japan         516700000          12718
    korea         169320000           5180
    usa          2041280000          32676
    '''
    
    print(country.shape)                                    # (4, 2)
    print(country.size)                                     # 8
    print(country.ndim)                                     # 2
    print(country.values)
    '''
     [[1409250000         141500]
      [516700000          12718]
      [169320000           5180]
      [2041280000          32676]]
    '''

    Index, Column의 이름 지정

    DataFrame의 Index와 column의 이름을 설정(재설정)하는 방법은 간단해요.
    바로 예시로 들어가죠. (앞서 만든 country라는 DataFrame을 활용할게요.)

    import pandas as pd
    
    print(country)
    ''' print 결과 1
                        gdp      population
    country 
    china        1409250000         141500
    japan         516700000          12718
    korea         169320000           5180
    usa          2041280000          32676
    '''
    
    country.index.name = "Country"                         # index 이름 재설정
    country.columns.name = "Info"                          # column 이름 설정
    
    print(country.index)
    # Index(['china', 'japan', 'korea', 'usa'], dtypr='object', name='Country')
    print(country.column)
    # Index(['gdp', 'population'], dtypr='object', name='Info')
    
    print(country)
    ''' print 결과 2
    Info                gdp      population
    Country 
    china        1409250000         141500
    japan         516700000          12718
    korea         169320000           5180
    usa          2041280000          32676
    '''

    그렇다면 set_index를 사용하지 않은 DataFrame의 indxe는 어떻게 조회될까요?

    RangeIndex(start=0, stop=4, step=1)

    저장 & 불러오기

    마지막으로 DataFrame을 저장하고 불러는 방법을 알아봐요. (앞서 만든 country 라는 DataFrame 을 활용할게요.)

    • .to_csv: csv 파일로 저장 (csv: comma separated value)
    • .to_excel: excel 파일로 저장
    • pd.read_csv("~.csv"): csv 파일 불러오기
    • pd.read_excel("~.xlsx"): excel 파일 불러오기
    import pandas as pd
    
    country.to_csv("./country.csv")
    country.to_excel("country.xlsx")
    
    country = pd.read_csv("./country.csv")
    country = pd.read_excel("country.xlsx")


    DataFrame 수정하기

    Data 선택

    Indexing & Slicing

    "Indexing과 Slicing" 계속 나오는 용어들이네요.
    가장 기본이면서 활용을 많이 하는 방법들이기 때문이죠.
    DataFrame을 Indexing 하거나 Slicing 하려면 어떻게 해야 할까요? 2가지 함수를 사용합니다.

    • .loc[ ] - DataFrame의 Index로 설정한 값을 참조하는 함수 (명시적)
    • .iloc[ ] - 파이썬의 정수 인덱스를 참조하는 함수 (암묵적)

    .loc[] 의 예시부터 볼게요.
    단, 이전의 Indexing, Slicing과 차이가 있으니 주의하세요.

    import pandas as pd
    
    data = {
        'country': ['china', 'japan', 'korea', 'usa'],
        'gdp': [1409250000, 516700000, 169320000, 2041280000],
        'population': [141500, 12718, 5180, 32676],
    }
    
    country = pd.DataFrame(data)
    country = country.set_index('country')
    
    print(country.loc['china'])                             # Indexing
    '''
    gdp           1409250000
    population        141500
    Name: china, dtype: int64
    '''
    
    print(country.loc['japan':'korea', :'population'])      # Slicing
    '''
                   gdp  population
    country                       
    japan    516700000       12718
    korea    169320000        5180
    '''

    차이를 찾으셨나요??

    print(country.loc['japan':'korea', :'population'])

    첫 번째 조건은 row의 자리이며 Slicing 하기 위해'japan':'korea'를 사용했고,
    두 번째 조건은 column의 자리이고 Slicing 하기 위해:'population'을 사용했죠.
    그런데 앞서 본 Slicing끝자리를 포함하지 않았지만 이번에는 포함한 결과를 출력하고 있어요.

    이번엔 .iloc[] 의 예시를 볼게요. (위에서 만든 country라는 DataFrame을 활용할게요.)
    위에서 처럼 구체적인 Index 명이나 Coulmn을 모를 때 사용하기 좋아요.
    그리고 .loc[] 과 다르게 일반적인 Indexing과 Slicing 규칙을 따르기 때문에 익숙한 결과를 볼 수 있어요.

    import pandas as pd
    
    country = pd.DataFrame(data)
    country = country.set_index('country')
    
    print(country.iloc[0])
    '''
    gdp           1409250000
    population        141500
    Name: china, dtype: int64
    '''
    
    print(country.iloc[1:3, :2])
    '''
                   gdp  population
    country                       
    japan    516700000       12718
    korea    169320000        5180
    '''

    Column 선택

    Column 이름을 알고 있다면 DataFrame에서 Data를 직접 선택할 수도 있어요.
    예시를 먼저 보고 설명할게요.

    import pandas as pd
    
    country = pd.DataFrame(data)
    country = country.set_index('country')
    
    print(country)
    '''
                    gdp  population
    country                        
    china    1409250000      141500
    japan     516700000       12718
    korea     169320000        5180
    usa      2041280000       32676
    '''
    print(type(country))                        # <class 'pandas.core.frame.DataFrame'>
    
    print(country['gdp'])
    '''
    country
    china    1409250000
    japan     516700000
    korea     169320000
    usa      2041280000
    Name: gdp, dtype: int64
    '''
    print(type(country['gdp']))                 # <class 'pandas.core.series.Series'>
    
    print(country[['gdp']])
    '''
                    gdp
    country            
    china    1409250000
    japan     516700000
    korea     169320000
    usa      2041280000
    '''
    print(type(country[['gdp']]))               # <class 'pandas.core.frame.DataFrame'>

    Column 명을 사용한 두 print 문을 살펴볼게요.

    print(country['gdp'])
    print(country[['gdp']])

    첫 print 문에 사용된 country['gdp']Series type이네요.
    DataFrame 소개할 때 언급한 적이 있는데요.
    "DateFrame 은 여러 개의 Series 가 모여서 행과 열을 이룬 데이터"이라는 점이 여기서 확인된 거죠.

    그렇다면 특정 Column을 DataFrame 형태로 출력하려면 어떻게 할까요?
    그때 두 번째 print 문처럼 country[['gdp']] 사용하면 됩니다.

     

    조건 활용

    만약 Column 뿐만 아니라 Value까지 정확히 알고 있다면 조건을 활용해 Data를 추출할 수 있어요.
    Masking 연산이나 Query 함수를 이용하는 방법이죠.
    이 때, Qurey 함수에 사용하는 조건은 if 조건문과 비슷하다고 생각하면 편해요.
    예시를 보죠. (위에서 만든 country라는 DataFrame을 활용할게요.)

    import pandas as pd
    
    country = pd.DataFrame(data)
    country = country.set_index('country')
    
    print(country[country['population'] < 10000])
    '''
                    gdp  population
    country                        
    china    1409250000      141500
    '''
    
    print(country.query('population > 100000'))
    '''
                   gdp  population
    country                       
    korea    169320000        5180
    '''

     

    Data 수정

    Column 추가

    Series 도 Numpy array처럼 연산자를 활용할 수 있어요.
    Series를 연산한 새로운 Data를 DataFrame에 추가해볼게요. (위에서 만든 country라는 DataFrame을 활용할게요.)

    import pandas as pd
    
    country = pd.DataFrame(data)
    country = country.set_index('country')
    
    gdp_per_capita = country['gdp'] / country['population']        # Series 연산
    country['gdp_per_capita'] = gdp_per_capita                     # Column 추가
    
    print(gdp_per_capita)
    '''
    country
    china     9959.363958
    japan    40627.457147
    korea    32687.258687
    usa      62470.314604
    dtype: float64
    '''
    
    print(country)
    '''
                    gdp  population  gdp_per_capita
    country                                        
    china    1409250000      141500     9959.363958
    japan     516700000       12718    40627.457147
    korea     169320000        5180    32687.258687
    usa      2041280000       32676    62470.314604
    '''

    Data 추가 & 수정

    Data는 List로 추가하거나 Dictionary로 추가할 수 있어요.
    DataFrame을 생성하는 방식과 유사하죠.
    그리고 Data를 추가할 때 .loc[ ] 함수가 다시 등장해요.
    빈 DataFrame 생성 ➡️ Data 추가 (list, dict) ➡️ Data 수정 차례로 볼게요.

    import pandas as pd
    
    df = pd.DataFrame(columns = ['name', 'age', 'address'])        # 빈 DataFrame 생성
    print(df)
    '''
    Empty DataFrame
    Columns: [name, age, address]
    Index: [] 
    '''
    
    df.loc[0] = ['Kay', '33', 'Korea']                             # List 로 Data 추가
    print(df)
    '''
      name age address
    0  Kay  33   Korea 
    '''
    
    df.loc[1] = {'name':'Rin', 'age':'29', 'address':'Seoul'}      # Dictionary 로 Data 추가
    print(df)
    '''
      name age address
    0  Kay  33   Korea
    1  Rin  29   Seoul 
    '''
    
    df.loc[0, 'address'] = 'Seoul'                                 # 명시적 Index 를 사용해 Data 수정
    print(df)
    '''
      name age address
    0  Kay  33   Seoul
    1  Rin  29   Seoul 
    '''

    NaN Column 추가

    DataFrame에 빈 Column을 추가하는 방법도 있어요.
    이때 Numpy 가 사용되고 NaN 이 등장합니다.
    NaN 은 Not a Number의 약자로 비어있는 Data를 의미해요.

    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame(columns = ['name', 'age', 'address'])
    df.loc[0] = ['Kay', '33', 'Korea']
    df.loc[1] = {'name':'Rin', 'age':'29', 'address':'Seoul'}
    df.loc[0, 'address'] = 'Seoul'
    
    df.loc['phone'] = np.nan                        # 새로운 Column 추가 후 초기화
    print(df)
    '''
      name age address  phone
    0  Kay  33   Seoul    NaN
    1  Rin  29   Seoul    NaN 
    '''
    
    df.loc[0, 'phone'] = '01012341234'               # 명시적 Index 를 활용해 Data 수정
    print(df)
    '''
      name age address        phone
    0  Kay  33   Seoul  01012341234
    1  Rin  29   Seoul          NaN
    '''

    Column 삭제

    마지막으로는 Column의 삭제를 알아봐요.
    Column 의 삭제는 .drop() 함수를 사용해요.

    df.drop('Column_name', axis = , inplace = )
    # axis = 1 열방향  // axis = 0 행방향
    # inplace = True 원본 변경 // inplcae = False 원본 유지

    예시로 마무리할게요.

    import pandas as pd
    import numpy as np
    
    df = pd.DataFrame(columns = ['name', 'age', 'address'])
    df.loc[0] = ['Kay', '33', 'Korea']
    df.loc[1] = {'name':'Rin', 'age':'29', 'address':'Seoul'}
    df.loc[0, 'address'] = 'Seoul'
    df.loc['Phone'] = np.nan
    df.loc[0, 'phone'] = '01012341234'
    
    df.drop('phone', axis=1, inplace=True)                     # Column 삭제
    print(df)
    '''
          name  age address
    0      Kay   33   Seoul
    1      Rin   29   Seoul
    Phone  NaN  NaN     NaN
    '''

    여기까지 "Pandas"에 대해 알아봤어요.
    글이 도움이 되셨다면 공감 버튼 눌러주세요. 😊

    댓글

    Designed by JB FACTORY