[Python, 데이터분석] 파이썬 판다스(Python Pandas), 시리즈(Series), 데이터프레임(Python Dataframe)

2021. 3. 27. 03:05 Python/파이썬 데이터 분석

 

| 파이선 판다스(Python Pandas)

 

파이썬 판다스(Python Pandas)는 파이썬 언어로 데이터를 분석하기 위한 쉽게하기 위한 자료구조 및 기능들을 제공하는 패키지입니다. 판다스가 제공하는 여러 기능들을 통해서 데이터 분석 과정 중 가장 까다로운 작업 중 하나인 데이터 전처리를 보다 쉽게할 수 처리할 수 있습니다.

 

 

| 파이썬 시리즈(Python Series)

 

파이썬 시리즈(Python Series)는 판다스의 중요 자료구조 중 하나입니다. 시리즈는 인덱스와 그와 짝지어진 데이터로 이루어져 있습니다. 

 

< 출처 : https://www.coursera.org/learn/python-data-analysis >

 

다음은 시리즈 자료구조를 이용한 예시들입니다. 

 

import pandas as pd

animals = ['Tigers', 'Bears', 'Moose'] 
p = pd.Series(animals) # 자동적으로 각 데이터에 인덱스를 부여
print(p)
'''
0    Tigers
1     Bears
2     Moose
dtype: object
'''

numbers = [1,2,3]
nums = pd.Series(numbers);
print(nums)
'''
0    1
1    2
2    3
dtype: int64
'''

animals = ['Tiger', 'Bear', None] # None값을 줘도 그 값이 인덱스에 매핑되서 표현
p = pd.Series(animals)
print(p)
'''
0    Tiger
1     Bear
2     None
dtype: object
'''

import numpy as np
print(np.nan == None) # numpy에는 값이 없는 것을 의미하는 nan값이 있다. 이것은 None과는 다르다.
# False
print(np.nan == np.nan) # nan끼리는 비교할 수 없다.
# False
print(np.isnan(np.nan)) # nan값인지를 확인하려면 isnan 메서드를 사용해야한다.
# True

samsung = {
    'SDS' : 'IT',
    'Electronic' : 'IT',
    'Display' : 'Hardware'
}
s = pd.Series(samsung) # 딕셔너리 구조도 시리즈 자료구조로 변환할 수 있음. 이때 딕셔너리의 키가 인덱스값이 됨.
print(s)
'''
SDS                 IT
Electronic          IT
Display       Hardware
dtype: object
'''
print(s.index) # 인덱스값을 엑세스
# Index(['SDS', 'Electronic', 'Display'], dtype='object')

s = pd.Series(['Tiger','Bear','Moose'], index=['India','America','Canada']) # 리스트 자료형을 통한 인덱스 지정
print(s)
'''
India      Tiger
America     Bear
Canada     Moose
dtype: object
'''
m = pd.Series(['SDS', 'Electronic', 'Display'], index=['Software', 'Software+Hardware', 'Hardware'])
print(m)
'''
Software                    SDS
Software+Hardware    Electronic
Hardware                Display
dtype: object
'''

sports = {'Archery' : 'Bhutan',
          'Golf':'Scotland',
          'Sumo':'Japan',
          'Taekwondo':'South Korea'}
s = pd.Series(sports, index=['Golf', 'Sumo', 'Hockey']) # 딕셔너리의 key가 하나의 인덱스처럼 동작한다.
print(s)                                                # 그리고 인덱스를 선택해 원하는 데이터를 추출할 수 있다.
'''
Golf      Scotland
Sumo         Japan
Hockey         NaN
dtype: object
'''

 

| 파이썬 시리즈 질의하기(Python Quering a Series)

 

파이썬 시리즈에서 다양한 방법으로 데이터에 접근할 수 있고 관련 정보를 질의할 수 있습니다. 다음은 그에 관련된 예제들입니다.

import pandas as pd
sports = {'Archery': 'Bhutan',
          'Golf': 'Scotland',
          'Sumo': 'Japan',
          'Taekwondo': 'South Korea'}
s = pd.Series(sports)
print(s)
'''
Archery           Bhutan
Golf            Scotland
Sumo               Japan
Taekwondo    South Korea
dtype: object
'''
game = {
    'Battle' :'FPS',
    'Overwatch' : 'FPS',
    'LOL' : 'AOS',
    'Lineage' : 'RPG'
}
m = pd.Series(game)
print(m)
'''
Battle       FPS
Overwatch    FPS
LOL          AOS
Lineage      RPG
dtype: object
'''

m.iloc[2] # 인덱스 위치를 통해 엑세스
# RPG
m.loc['LOL'] # 인덱스명을 통해 엑세스, 딕셔너리의 key를 통한 엑세스 방식과 유사
# AOS
m[3] # iloc[3]과 같음
# FPS
m['Overwatch'] # 인덱스명을 통한 엑세스, loc와 같음
# FPS
m.iloc[0]
# FPS

sports = {99: 'Bhutan',
          100: 'Scotland',
          101: 'Japan',
          102: 'South Korea'}
s = pd.Series(sports)
s = pd.Series([100.00, 120.00, 101.00, 3.00]) # 시리즈 데이터 갱신
print(s)
'''
0    100.0
1    120.0
2    101.0
3      3.0
dtype: float64
'''

total = 0
for item in s:  # 시리즈 데이터 순회하며 데이터 총합 구하기
    total += item
print(total)
# 324.0

from functools import reduce    # reduce를 이용하여 데이터 총합 구하기
total = reduce(lambda x,y: x + y, s.values)
print(total)
# 324.0

import numpy as np
total = np.sum(s) # numpy를 통해서 매우 간단하게 시리즈 데이터의 총합을 구할 수 있음
print(total)
# 324.0

import pandas as pd
import numpy as np
s = pd.Series(np.random.randint(0,1000,10000))
print(s.head()) # 시리즈 데이터의 앞 네자리만 보기
a = pd.Series(np.random.randint(0,10000,40))
print(a.head(10)) # 시리즈 데이터의 앞 10자리만 보기

len(s) # 시리즈 데이터 크기
# 10000

import timeit # ipython의 magic function인 %%timeit를 python 인터프리터에서도 사용하는 방법
mycode ='''
def example():
    s = pd.Series(np.random.randint(0,1000,10000))
    summary=0
    for item in s:
        summary+=item
'''
print(timeit.timeit(stmt=mycode, number=10000000))
# 0.56461516

s += 2 # numpy의 브로드캐스팅을 통한 연산. 다른 차원의 자료구조도 numpy의 브로드캐스팅
       # 을 통하여 쉽게 연산 가능하다. s의 차원은 (1,10000) 이지만 단일 정수를 더해도 
       # numpy 내부에서 브로드캐스팅이 일어나 2의 차원이 (1, 10000)으로 확장되어 연산이 가능해진다.
       # 이에 관한 포스팅은 후에 게시할 예정
print(s.head())
'''
0    274
1     33
2    146
3    200
4    547
dtype: int64
'''
for label, value in s.iteritems(): # 위의 s+=2 연산과 같다. 위 연산에 비해 코드량이 훨씬 더 많고 복잡하다.
    s.set_value(label, value+2)
s.head()
print(s.head())
'''
0    274
1     33
2    146
3    200
4    547
dtype: int64
'''
s = pd.Series([1, 2, 3]) # 시리즈 자료구조에 데이터를 추가할 수 있다.
s.loc['Animal'] = 'Bears'
print(s)
'''
0             1
1             2
2             3
Animal    Bears
dtype: object
'''
original_sports = pd.Series({'Archery': 'Bhutan',
                             'Golf': 'Scotland',
                             'Sumo': 'Japan',
                             'Taekwondo': 'South Korea'})
cricket_loving_countries = pd.Series(['Australia',      # 시리즈 자료구조는 딕셔너리와 다르게 index값의 중복이 허용된다.
                                      'Barbados',       # 왜냐하면 인덱스의 숫서로 값을 구분하기 때문이다.
                                      'Pakistan',
                                      'England'],
                                   index=['Cricket',
                                          'Cricket',
                                          'Cricket',
                                          'Cricket'])
all_countries = original_sports.append(cricket_loving_countries)
print(original_sports)
'''
Archery           Bhutan
Golf            Scotland
Sumo               Japan
Taekwondo    South Korea
dtype: object
'''
print(cricket_loving_countries)
'''
Cricket    Australia
Cricket     Barbados
Cricket     Pakistan
Cricket      England
dtype: object
'''
print(all_countries)
'''
Archery           Bhutan
Golf            Scotland
Sumo               Japan
Taekwondo    South Korea
Cricket        Australia
Cricket         Barbados
Cricket         Pakistan
Cricket          England
dtype: object
'''
print(all_countries.loc['Cricket'])
'''
Cricket    Australia
Cricket     Barbados
Cricket     Pakistan
Cricket      England
dtype: object
'''

 

| 파이썬 데이터프레임(Python DataFrame)

 

파이썬 데이터프레임은 판다스에서 제공하는 자료구조로 데이터 분석을 하게 될 때 가장 많이 보게되는 자료구조입니다. 판다스 자료구조의 핵심 중의 핵심이라고 할 수 있죠. 데이터 프레임은 다음과 같은 구조로 되어 있습니다.

 

< 출처 : https://www.coursera.org/learn/python-data-analysis >

 

다음은 데이터프레임과 관련된 예제입니다.

import pandas as pd
purchase_1 = pd.Series({'Name': 'Chris',                # 시리즈 데이터를 묶어서 데이터프레임 데이터 만들기
                        'Item Purchased': 'Dog Food',
                        'Cost': 22.50})
purchase_2 = pd.Series({'Name': 'Kevyn',
                        'Item Purchased': 'Kitty Litter',
                        'Cost': 2.50})
purchase_3 = pd.Series({'Name': 'Vinod',
                        'Item Purchased': 'Bird Seed',
                        'Cost': 5.00})
purchase_4 = pd.Series({ 'Name' : 'power',
                        'Item Purchased' : 'Daniel',
                        'Cost' : 9.42})
df = pd.DataFrame([purchase_1, purchase_2, purchase_3, purchase_4], index=['Store 1', 'Store 1', 'Store 2', 'Store 3'])
h = df.head()
print(h)
'''
          Name Item Purchased   Cost
Store 1  Chris       Dog Food  22.50
Store 1  Kevyn   Kitty Litter   2.50
Store 2  Vinod      Bird Seed   5.00
Store 3  power         Daniel   9.42
'''
print(df.loc['Store 2'])
'''
Cost                      5
Item Purchased    Bird Seed
Name                  Vinod
Name: Store 2, dtype: object
'''
type(df.loc['Store 2'])
# pandas.core.series.Series
print(df.loc['Store 1', 'Cost']) # Store 1인 행에 컬럼값이 'Cost'인 요소 구하기
'''
Store 1    22.5
Store 1     2.5
Name: Cost, dtype: float64
'''
T = df.T # Transpose
print(T)
'''
                 Store 1       Store 1    Store 2 Store 3
Cost                22.5           2.5          5    9.42
Item Purchased  Dog Food  Kitty Litter  Bird Seed  Daniel
Name               Chris         Kevyn      Vinod   power
'''
print(df.loc[:,['Name', 'Cost']]) # Name과 Cost의 컬럼에 해당되는 모든 행을 출력
'''
          Name   Cost
Store 1  Chris  22.50
Store 1  Kevyn   2.50
Store 2  Vinod   5.00
Store 3  power   9.42
'''
print(df.loc[['Store 1', 'Store 2'], ['Item Purchased', 'Cost']]) # Store1, Store2 행과 Item Purchased, Cost 열에 해당되는 모든 요소 출력
'''
        Item Purchased  Cost
Store 1       Dog Food  22.5
Store 1   Kitty Litter   2.5
Store 2      Bird Seed   5.0
'''
drop_df= df.drop('Store 1') # 데이터프레임 중 Store1인 행을 제거한 데이터프레임을 반환 원본 데이터프레임은 변화없음
print(drop_df)
'''
          Name Item Purchased  Cost
Store 2  Vinod      Bird Seed  5.00
Store 3  power         Daniel  9.42
'''
print(df)
'''
          Name Item Purchased   Cost
Store 1  Chris       Dog Food  22.50
Store 1  Kevyn   Kitty Litter   2.50
Store 2  Vinod      Bird Seed   5.00
Store 3  power         Daniel   9.42
'''
copy_df = df.copy()
copy_df = copy_df.drop('Store 1') # 위의 연산은 df를 복사하고 난 후 그 복사된 데이터를 드롭한 데이터 프레임을 넘겨주는 것
print(copy_df)
'''
          Name Item Purchased  Cost
Store 2  Vinod      Bird Seed  5.00
Store 3  power         Daniel  9.42
'''

del copy_df['Name'] # 컬럼을 삭제하는 방법. 원본 데이터 변화 있음 주의해야 함
print(copy_df)
'''
        Item Purchased  Cost
Store 2      Bird Seed  5.00
Store 3         Daniel  9.42
'''

df['Location'] = None  # 데이터 추가방법, Series를 이용하지 않고도 리스트로 추가 가능하다
df['Sale'] = [True, False, True, True]
print(df)
'''
          Name Item Purchased   Cost Location   Sale
Store 1  Chris       Dog Food  22.50     None   True
Store 1  Kevyn   Kitty Litter   2.50     None  False
Store 2  Vinod      Bird Seed   5.00     None   True
Store 3  power         Daniel   9.42     None   True
'''

costs = df['Cost']  # 해당 컬럼의 전체 행 추출
print(costs)
'''
Store 1    22.50
Store 1     2.50
Store 2     5.00
Store 3     9.42
Name: Cost, dtype: float64
'''
costs+=2    # 해당 컬럼의 전체행에 2를 더함. 브로드캐스팅 방식으로 연산
print(costs)
'''
Store 1    24.50
Store 1     4.50
Store 2     7.00
Store 3    11.42
Name: Cost, dtype: float64
'''

 

 

| 파이썬 데이터프레임 데이터 추출(Python DataFrame Data Access and Extraction)

 

다음은 예제 csv 파일을 가지고 진행해 보겠습니다. 이 csv 파일은 올림픽의 데이터와 관련된 csv 파일입니다.

 

olympics.csv
0.01MB

 

import pandas as pd

df = pd.read_csv('olympics.csv') # csv파일 불러오기, 데이터가 이상하게 불려들여짐
                                 # 컬럼명이 한 칸 아래에 위치, 로우명이 오른쪽으로 한 칸 밀려있음
print(df.head())
'''
                   0         1     2       ...          13    14              15
0                NaN  № Summer  01 !       ...        02 !  03 !  Combined total
1  Afghanistan (AFG)        13     0       ...           0     2               2
2      Algeria (ALG)        12     5       ...           2     8              15
3    Argentina (ARG)        23    18       ...          24    28              70
4      Armenia (ARM)         5     1       ...           2     9              12
'''

df = pd.read_csv('olympics.csv', index_col=0, skiprows=1) # 잘못 로드된 데이터를 제대로 불려들임
                                                          # index_col은 인덱스의 위치를 컬럼의 인덱스로 나타냄
                                                          # skiprows는 컬럼명을 맞추기 위해 얼마만큼의 행을 건너뛸지를 나타냄
print(df.head())
'''                      
                         № Summer  01 !       ...        03 !.2  Combined total
Afghanistan (AFG)              13     0       ...             2               2
Algeria (ALG)                  12     5       ...             8              15
Argentina (ARG)                23    18       ...            28              70
Armenia (ARM)                   5     1       ...             9              12
Australasia (ANZ) [ANZ]         2     3       ...             5              12
'''

for col in df.columns:  # 데이터프레임 데이터 전처리, 컬럼명 바꾸기
    if col[:2] == '01':
        df.rename(columns={col:'Gold' + col[4:]}, inplace=True) # inplace는 새로운 데이터프레임을 복사해서 줄 것인지
    if col[:2] == '02':                                         # 기존의 것을 대체할 것인지를 결정함
        df.rename(columns={col:'Silver' + col[4:]}, inplace=True)
    if col[:2] == '03':
        df.rename(columns={col: 'Bronze' + col[4:]}, inplace=True)
    if col[:1] == '№':
        df.rename(columns={col: '#' + col[1:]}, inplace=True)

print(df.columns)
'''
Index(['# Summer', 'Gold', 'Silver', 'Bronze', 'Total', '# Winter', 'Gold.1',
       'Silver.1', 'Bronze.1', 'Total.1', '# Games', 'Gold.2', 'Silver.2',
       'Bronze.2', 'Combined total'],
      dtype='object')

'''

print(df['Gold'] > 0)  # Gold 컬럼에서 0 보다 큰 값인지 여부 확인
'''
Afghanistan (AFG)                               False
Algeria (ALG)                                    True
Argentina (ARG)                                  True
Armenia (ARM)                                    True
Australasia (ANZ) [ANZ]                          True
Australia (AUS) [AUS] [Z]                        True
Austria (AUT)                                    True
Azerbaijan (AZE)                                 True
Bahamas (BAH)                                    True
Bahrain (BRN)                                   False
Barbados (BAR) [BAR]                            False
Belarus (BLR)                                    True
Belgium (BEL)                                    True
Bermuda (BER)                                   False
Bohemia (BOH) [BOH] [Z]                         False
Botswana (BOT)                                  False
Brazil (BRA)                                     True
British West Indies (BWI) [BWI]                 False
Bulgaria (BUL) [H]                               True
Burundi (BDI)                                    True
Cameroon (CMR)                                   True
Canada (CAN)                                     True
Chile (CHI) [I]                                  True
China (CHN) [CHN]                                True
Colombia (COL)                                   True
Costa Rica (CRC)                                 True
Ivory Coast (CIV) [CIV]                         False
Croatia (CRO)                                    True
Cuba (CUB) [Z]                                   True
Cyprus (CYP)                                    False
                                                ...  
Sri Lanka (SRI) [SRI]                           False
Sudan (SUD)                                     False
Suriname (SUR) [E]                               True
Sweden (SWE) [Z]                                 True
Switzerland (SUI)                                True
Syria (SYR)                                      True
Chinese Taipei (TPE) [TPE] [TPE2]                True
Tajikistan (TJK)                                False
Tanzania (TAN) [TAN]                            False
Thailand (THA)                                   True
Togo (TOG)                                      False
Tonga (TGA)                                     False
Trinidad and Tobago (TRI) [TRI]                  True
Tunisia (TUN)                                    True
Turkey (TUR)                                     True
Uganda (UGA)                                     True
Ukraine (UKR)                                    True
United Arab Emirates (UAE)                       True
United States (USA) [P] [Q] [R] [Z]              True
Uruguay (URU)                                    True
Uzbekistan (UZB)                                 True
Venezuela (VEN)                                  True
Vietnam (VIE)                                   False
Virgin Islands (ISV)                            False
Yugoslavia (YUG) [YUG]                           True
Independent Olympic Participants (IOP) [IOP]    False
Zambia (ZAM) [ZAM]                              False
Zimbabwe (ZIM) [ZIM]                             True
Mixed team (ZZX) [ZZX]                           True
Totals                                           True
Name: Gold, Length: 147, dtype: bool
'''
only_gold = df.where(df['Gold']>5)  # Gold 컬럼에서 5보다 큰 행들의 모음을 데이터프레임 형식으로 반환
print(only_gold.head())
'''
                         # Summer       ...        Combined total
Afghanistan (AFG)             NaN       ...                   NaN
Algeria (ALG)                 NaN       ...                   NaN
Argentina (ARG)              23.0       ...                  70.0
Armenia (ARM)                 NaN       ...                   NaN
Australasia (ANZ) [ANZ]       NaN       ...                   NaN
'''
print(only_gold['Gold'].count()) # Gold 컬럼중에서 NaN이 아닌 수를 구하기
# 62
only_gold = only_gold.dropna() # 데이터 프레임에서 NaN이 포함된 행들 다 drop하기
print(only_gold.head())
'''
                           # Summer       ...        Combined total
Argentina (ARG)                23.0       ...                  70.0
Australia (AUS) [AUS] [Z]      25.0       ...                 480.0
Austria (AUT)                  26.0       ...                 304.0
Azerbaijan (AZE)                5.0       ...                  26.0
Belarus (BLR)                   5.0       ...                  90.0
'''

only_gold = df[df['Gold'] > 0] # Gold가 0보다 큰 행들을 모아 데이터프레임으로 리턴
                               # 위의 방식보다 훨씬 간단하다
print(only_gold.head())
'''
                           # Summer       ...        Combined total
Algeria (ALG)                    12       ...                    15
Argentina (ARG)                  23       ...                    70
Armenia (ARM)                     5       ...                    12
Australasia (ANZ) [ANZ]           2       ...                    12
Australia (AUS) [AUS] [Z]        25       ...                   480

'''
gold_and_gold1 = df[(df['Gold'] > 0) & (df['Gold.1'] > 0)]  # Gold와 Gold.1값이 동시에 0이 넘는 행들을 선택
print(gold_and_gold1.head())
'''
                           # Summer       ...        Combined total
Australia (AUS) [AUS] [Z]        25       ...                   480
Austria (AUT)                    26       ...                   304
Belarus (BLR)                     5       ...                    90
Belgium (BEL)                    25       ...                   147
Bulgaria (BUL) [H]               19       ...                   220
'''

df['country'] = df.index # 인덱스로 쓰인 데이터를 'country' 컬럼의 데이터로 만들어 쓰기
df = df.set_index('Silver') # Silver라는 새로운 인덱스 만듬
print(df.head())
'''
        # Summer           ...                             country
Silver                     ...                                    
0             13           ...                   Afghanistan (AFG)
2             12           ...                       Algeria (ALG)
24            23           ...                     Argentina (ARG)
2              5           ...                       Armenia (ARM)
4              2           ...             Australasia (ANZ) [ANZ]
'''
df = df.reset_index() # 인덱스 리셋
print(df.head())
'''
   Silver           ...                             country
0       0           ...                   Afghanistan (AFG)
1       2           ...                       Algeria (ALG)
2      24           ...                     Argentina (ARG)
3       2           ...                       Armenia (ARM)
4       4           ...             Australasia (ANZ) [ANZ]
'''
df.index = df['Silver']
print(df.head())
'''
        Silver           ...                             country
Silver                   ...                                    
0            0           ...                   Afghanistan (AFG)
2            2           ...                       Algeria (ALG)
24          24           ...                     Argentina (ARG)
2            2           ...                       Armenia (ARM)
4            4           ...             Australasia (ANZ) [ANZ]
'''
df = df.sort_index() # 인덱스 정렬
print(df.head())
'''
   Silver           ...                             country
0       0           ...                   Afghanistan (AFG)
1       2           ...                       Algeria (ALG)
2      24           ...                     Argentina (ARG)
3       2           ...                       Armenia (ARM)
4       4           ...             Australasia (ANZ) [ANZ]
'''
# !cat olympics.csv

 

참고자료 : https://www.coursera.org/learn/python-data-analysis

출처: https://engkimbs.tistory.com/672?category=763908 [새로비]