[10일차] 구조적 데이터 표시와 처리에 강한 pandas

2023. 1. 3. 16:50데이터 엔지니어링 과정/python

목차
1. 구조적 데이터 생성하기
2. 데이터 연산
3. 데이터를 원하는 대로 선택하기
4. 데이터 통합하기
5. 데이터 파일을 읽고 쓰기

1. 구조적 데이터 생성하기

1. Series를 활용한 데이터 생성

: s=pd.Series(seq_data)

(0) pandas 호출

import pandas as pd

(1) Series 생성하기

: 세로축 라벨을 라벨을 index, 입력한 시퀀스 데이터를 values라고 한다.

s1 = pd.Series([10,20,30,40,50])
s1

>>> 0    10
    1    20
    2    30
    3    40
    4    50
    dtype: int64

(2) index와 values 분리해서 가져오기

  • index 분리
s1.index
print(s1.index)

>>> RangeIndex(start=0, stop=5, step=1)
  • values 분리
s1.values

>>> array([10, 20, 30, 40, 50], dtype=int64)

(3) 혼합된 리스트 생성

s2 = pd.Series(['a','b','c',1,2,3])
s2

>>> 0    a
    1    b
    2    c
    3    1
    4    2
    5    3
    dtype: object

(4) 데이터가 없을 경우 Numpy를 import 하여 데이터 없음 표기 가능

import numpy as np

s3 = pd.Series([np.nan, 10, 30])
s3

>>> 0     NaN
    1    10.0
    2    30.0
    dtype: float64

(5) 인자로 index 추가 s = pd.series (seq_data, index = index_seq)

seq_data와 index_seq의 갯수와 일치해야 함

index_data = ['2022-02-23', '2022-02-24','2022-02-25', '2022-02-26']
s4 = pd.Series([200, 195, np.nan, 205], index= index_data)
s4

>>> 2022-02-23    200.0
    2022-02-24    195.0
    2022-02-25      NaN
    2022-02-26    205.0
    dtype: float64

(6) 딕셔너리를 이용하면 데이터와 index를 함께 입력 가능

s5 = pd.Series({'국어':100, '영어': 95, '수학':90})
s5

>>> 국어    100
    영어     95
    수학     90
    dtype: int64

2. 날짜 자동 생성 date_range

(0) date_range 구조

pd.date_range(start=None, end=None, periodes=None, freq='D')

  • start     시작 날짜
  • end       끝 날짜
  • periods 날짜 데이터 생성 기간
  • freq       날짜 데이터 생성 주기

(1) 시작 날짜와 끝 날짜 지정

import pandas as pd

pd.date_range(start='2023-01-01', end='2023-01-07')

>>> DatetimeIndex(['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04',
                   '2023-01-05', '2023-01-06', '2023-01-07'],
                  dtype='datetime64[ns]', freq='D')

 

pd.date_range(start='2023/01/01',end='2023.01.07')
>>> DatetimeIndex(['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04',
                   '2023-01-05', '2023-01-06', '2023-01-07'],
                  dtype='datetime64[ns]', freq='D')
    
    
pd.date_range(start='01-01-2023',end='01/07/2023')
>>> DatetimeIndex(['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04',
                   '2023-01-05', '2023-01-06', '2023-01-07'],
                  dtype='datetime64[ns]', freq='D')


pd.date_range(start='2023-01-01',end='01.07.2023')
>>> DatetimeIndex(['2023-01-01', '2023-01-02', '2023-01-03', '2023-01-04',
                   '2023-01-05', '2023-01-06', '2023-01-07'],
                  dtype='datetime64[ns]', freq='D')

➡ 다양한 형식으로 연도, 월, 일을 입력할 수 있지만!! 생성된 날짜 데이터 형식은 모두 yyyy-mm-dd

(2) periods 사용하기

pd.date_range(start='2022-01-01',periods = 7)

>>> DatetimeIndex(['2022-01-01', '2022-01-02', '2022-01-03', '2022-01-04',
                   '2022-01-05', '2022-01-06', '2022-01-07'],
                  dtype='datetime64[ns]', freq='D')

(3) freq 사용하기

pd.date_range(start='2023-01-01', periods = 4, freq = '2D')
>>> DatetimeIndex(['2023-01-01', '2023-01-03', '2023-01-05', '2023-01-07'], dtype='datetime64[ns]', freq='2D')

(4) freq 옵션 사용 예시

  • 요일 시작 기준 일주일 주기
    freq = 'W', freq = 'W-mon'
pd.date_range(start = '2023-01-01', periods = 5, freq = 'W-mon')
>>> DatetimeIndex(['2023-01-02', '2023-01-09', '2023-01-16', '2023-01-23',
                   '2023-01-30'],
                  dtype='datetime64[ns]', freq='W-MON')
  • 업무 월말 날짜 기준 주기
    freq= 'BM', freq = '2BM'
pd.date_range(start= '2023-01-01', periods = 12, freq= '2BM')

>>> DatetimeIndex(['2023-01-31', '2023-03-31', '2023-05-31', '2023-07-31',
                   '2023-09-29', '2023-11-30', '2024-01-31', '2024-03-29',
                   '2024-05-31', '2024-07-31', '2024-09-30', '2024-11-29'],
                  dtype='datetime64[ns]', freq='2BM')
  • 분기 시작 기준 날짜 주기
    freq= 'QS', freq = '2QS'
pd.date_range(start= '2023-01-01', periods = 4 , freq= 'QS')

>>> DatetimeIndex(['2023-01-01', '2023-04-01', '2023-07-01', '2023-10-01'], dtype='datetime64[ns]', freq='QS-JAN')
  • 연도 기준 날짜 주기
    freq = 'AS', freq = '2AS'
pd.date_range(start= '2023-01-01', periods = 3, freq= 'AS')

>>> DatetimeIndex(['2023-01-01', '2024-01-01', '2025-01-01'], dtype='datetime64[ns]', freq='AS-JAN')
  • 시간 기준 주기
    freq='H'
pd.date_range(start= '2023-01-03 09:00', periods = 10, freq= 'H')

>>> DatetimeIndex(['2023-01-03 09:00:00', '2023-01-03 10:00:00',
                   '2023-01-03 11:00:00', '2023-01-03 12:00:00',
                   '2023-01-03 13:00:00', '2023-01-03 14:00:00',
                   '2023-01-03 15:00:00', '2023-01-03 16:00:00',
                   '2023-01-03 17:00:00', '2023-01-03 18:00:00'],
                  dtype='datetime64[ns]', freq='H')
  • 업무 시간 기준 주기
    freq = 'BH'
pd.date_range(start = '2023-01-03 07:00', periods = 10, freq = 'BH')

>>> DatetimeIndex(['2023-01-03 09:00:00', '2023-01-03 10:00:00',
                   '2023-01-03 11:00:00', '2023-01-03 12:00:00',
                   '2023-01-03 13:00:00', '2023-01-03 14:00:00',
                   '2023-01-03 15:00:00', '2023-01-03 16:00:00',
                   '2023-01-04 09:00:00', '2023-01-04 10:00:00'],
                  dtype='datetime64[ns]', freq='BH')
  • 30분 단위로 시간 생성하기
pd.date_range(start = '2023-01-03 10:00', periods = 4, freq = '30min')

>>> DatetimeIndex(['2023-01-03 10:00:00', '2023-01-03 10:30:00',
                   '2023-01-03 11:00:00', '2023-01-03 11:30:00'],
                  dtype='datetime64[ns]', freq='30T')
pd.date_range(start = '2023-01-03 10:00', periods = 4, freq = '30T')

>>> DatetimeIndex(['2023-01-03 10:00:00', '2023-01-03 10:30:00',
                   '2023-01-03 11:00:00', '2023-01-03 11:30:00'],
                  dtype='datetime64[ns]', freq='30T')
  • 초 단위로 생성하기
pd.date_range(start = '2023-01-03 10:00', periods = 4, freq = '10s')

>>> DatetimeIndex(['2023-01-03 10:00:00', '2023-01-03 10:00:10',
                   '2023-01-03 10:00:20', '2023-01-03 10:00:30'],
                  dtype='datetime64[ns]', freq='10S')

3. DataFrame을 활용한 데이터 생성

(0) Dataframe 구조 엿보기

import pandas as pd

pd.DataFrame([[1,2,3], [4, 5, 6], [7, 8, 9]])

(1) Numpy의 배열 데이터를 활용한 DataFrame 생성

import numpy as np
import pandas as pd

data_list = np.array([[10, 20, 30], [40, 50, 60], [70, 80, 90]])
pd.DataFrame(data_list)

(2) index와 columns 지정

import numpy as np
import pandas as pd

data = np.array([[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12]])
index_date = pd.date_range('2023-04-12', periods = 4)
columns_list = ['A', 'B', 'C']
pd.DataFrame(data, index = index_date, columns = columns_list)

(3) 딕셔너리 타입으로 2차원 데이터를 입력했을 경우

table_data = {'연도':[2015, 2016, 2016, 2017, 2017],
             '지사': ['한국', '한국', '미국','한국','미국'],
             '고객 수': [200, 250, 450, 300, 500]}

pd.DataFrame(table_data)

  • 지정한 순서대로 출력하기
df = pd.DataFrame(table_data, columns=['연도','고객 수', '지사'])
df

  • DataFrame 데이터에서 index, columns, values 각각 구하기
# index 구하기
df.index
>>> RangeIndex(start=0, stop=5, step=1)

# columns 구하기
df.columns
>>> Index(['연도', '고객 수', '지사'], dtype='object')

# values 구하기
df.values
>>> array([[2015, 200, '한국'],
           [2016, 250, '한국'],
           [2016, 450, '미국'],
           [2017, 300, '한국'],
           [2017, 500, '미국']], dtype=object)

 

2. 데이터 연산

1. pandas의 Series와 DateFrame 생성한 데이터끼리의 사칙연산

s1 = pd.Series([1, 2, 3, 4, 5])
s2 = pd.Series([10, 20, 30, 40, 50])
# 덧셈
s1 + s2
>>> 0    11
    1    22
    2    33
    3    44
    4    55
    dtype: int64
    
# 뺄셈
s2- s1
>>> 0     9
    1    18
    2    27
    3    36
    4    45
    dtype: int64
    
# 나눗셈
s2/s1
>>> 0    10.0
    1    10.0
    2    10.0
    3    10.0
    4    10.0
    dtype: float64
    
# 곱셈
>>> 0     10
    1     40
    2     90
    3    160
    4    250
    dtype: int64

2. 데이터끼리 크기가 달라도 연산이 가능하나, 연산을 할 수 있는 항목만 연산 수행

s3 = pd .Series([1, 2, 3, 4])
s4 = pd .Series([10, 20, 30, 40, 50])

s3 + s4
>>> 0    11.0
    1    22.0
    2    33.0
    3    44.0
    4     NaN
    dtype: float64

3. DataFrame 데이터끼리 사칙 연산

(1) 크기가 다른 DataFrame 2개 생성

table_data1 = {"A":[1, 2, 3, 4, 5],
              'B': [10, 20, 30, 40, 50],
              'C' : [100, 200, 300, 400, 500]}
df1 = pd.DataFrame(table_data1)

df1

table_data2 = {"A":[6, 7, 8],
              'B': [60, 70, 80],
              'C' : [600, 700, 800]}
df2 = pd.DataFrame(table_data2)

df2

(2) 사칙연산 가능

df1 + df2

➡ Series 데이터의 경우와 마찬가지로,

     DataFrame 데이터의 경우도 연산할 수 있는 항목끼리만 연산하고,

     그렇지 못한 항목은 NaN으로 표시한다.

 

 

 

 

(3) 데이터의 총합, 평균, 표준 편차 구하기

  • 예시 자료 생성 : 2018년부터 2022년까지 우리나라의 계절별 강수량( 단위 mm)
table_data3 = {'봄': [256.5, 264.3, 215.9, 223.2, 312.8],
              '여름': [770.6, 567.5, 599.8, 387.1, 446.2],
              '가을': [363.5, 231.2, 293.1, 247.7, 381.6],
              '겨울': [139.3, 59.9, 76.9, 109.1, 108.1]}
columns_list = ['봄' ,'여름' ,'가을', '겨울']
index_list = ['2018', '2019', '2020', '2021', '2022']

df3 = pd.DataFrame(table_data3, columns= columns_list, index = index_list)
df3

  • 평균 구하기
df3.mean()

>>> 봄      254.54
    여름    554.24
    가을    303.42
    겨울     98.66
    dtype: float64
  • 표준편차 구하기
df3.std()

>>> 봄       38.628267
    여름    148.888895
    가을     67.358496
    겨울     30.925523
    dtype: float64
  • 연도별 평균 강수량과 표준 편차 구하기
    axis=0이면 열별로, 1이면 행별로 연산을 수행 (설정하지 않으면 0)
# 연도별 평균 강수량
df3.mean(axis=1)
>>> 2018    382.475
    2019    280.725
    2020    296.425
    2021    241.775
    2022    312.175
    dtype: float64
  
# 연도별 평균 표준 편차  
df3.std(axis=1)
>>> 2018    274.472128
    2019    211.128782
    2020    221.150739
    2021    114.166760
    2022    146.548658
    dtype: float64
  • describe() 평균, 표준편차, 최솟값, 최댓값 등 한 번에 구하기
df3.describe()

 

3. 데이터를 원하는 대로 선택하기

0. 2011년부터 2017년까지의 노선별 KTX 이용자 관련 DataFrame 데이터 생성

import pandas as pd
import numpy as np

KTX_data = {'경부선 KTX': [39060, 39896, 42005, 43621, 41702, 41266, 32427],
           '호남선 KTX': [7313, 6967, 6873, 6626, 8675, 10622, 9228],
           '경전선 KTX': [3627, 4168, 4088, 4424, 4606, 4984, 5570],
           '전라선 KTX': [309, 1771, 1954, 2244, 3146, 3945, 5766],
           '동해선 KTX': [np.nan, np.nan, np.nan, np.nan, 2395, 3786, 6667]}
col_list = ['경부선 KTX', '호남선 KTX', '경전선 KTX', '전라선 KTX', '동해선 KTX']
index_list=[2011, 2012, 2013, 2014, 2015, 2016, 2017]

df_KTX = pd.DataFrame(KTX_data, columns = col_list, index = index_list)
df_KTX

1. 데이터의 index, columns, values 확인

df_KTX.index
>>> Int64Index([2011, 2012, 2013, 2014, 2015, 2016, 2017], dtype='int64')

df_KTX.columns
>>> Index(['경부선 KTX', '호남선 KTX', '경전선 KTX', '전라선 KTX', '동해선 KTX'], dtype='object')

df_KTX.values
>>> array([[39060.,  7313.,  3627.,   309.,    nan],
           [39896.,  6967.,  4168.,  1771.,    nan],
           [42005.,  6873.,  4088.,  1954.,    nan],
           [43621.,  6626.,  4424.,  2244.,    nan],
           [41702.,  8675.,  4606.,  3146.,  2395.],
           [41266., 10622.,  4984.,  3945.,  3786.],
           [32427.,  9228.,  5570.,  5766.,  6667.]])

2. 데이터 일부만 보기

  • head(n) 처음 n개의 행의 데이터 반환, n 미입력 시 기본값으로 5 지정 
df_KTX.head()

df_KTX.head(3)

  • tail(n) 마지막 n개의 행 데이터 반환, n 미입력 시 기본값으로 5 지정
df_KTX.tail()

df_KTX.tail(10)

➡ n의 개수를 실제보다 많게 지정한다면,

     갖고 있는 것들을 다 출력한다.

 

 

 

 

 

 

3. DataFrame에서 연속된 구간의 행 데이터를 선택하기

(1) DataFrame_data[행_시작 : 행_끝]

df_KTX[1:2]

df_KTX[2:5]

(2) index를 지정하기
      DataFrame_data.loc[index_name]

df_KTX.loc['2011']
>>> 경부선 KTX    41266.0
    호남선 KTX    10622.0
    경전선 KTX     4984.0
    전라선 KTX     3945.0
    동해선 KTX     3786.0
    Name: 2016, dtype: float64

(3) 구간을 지정해서 출력하기

df_KTX.loc['2013':'2016']

(4) 하나의 열 데이터 출력

df_KTX['경부선 KTX']
>>> 2011    39060
    2012    39896
    2013    42005
    2014    43621
    2015    41702
    2016    41266
    2017    32427
    Name: 경부선 KTX, dtype: int64

(5) 하나의 열 데이터에서 index 범위 지정하기

DataFrame_data [column_name][start_index_name:end_index_name]
DataFrame_data [column_name][start_index_pos:end_index_pos]

df_KTX['경부선 KTX']['2012' : '2014']
>>> 2012    39896
    2013    42005
    2014    43621
    Name: 경부선 KTX, dtype: int64
    
df_KTX['경부선 KTX'][2:5]
>>> 2013    42005
    2014    43621
    2015    41702
    Name: 경부선 KTX, dtype: int64

(6) DataFrame 중 하나의 원소만 선택하기

df_KTX.loc['2016','호남선 KTX']

df_KTX['호남선 KTX']['2016']

df_KTX['호남선 KTX'][5]

df_KTX['호남선 KTX'].loc['2016']

>>> 10622

4. 행과 열 바꾸기

df_KTX.T

df_KTX

➡ T를 사용했다고 해서 아예 df_KTX의 값이 바뀐 건 아님을 확인할 수 있다. 따라서 행과 열을 바꾼 값을 갖고 싶다면 따로 저장해야 한다!

 

 

 

 

 

5. 열의 순서를 지정하여 변경하기

df_KTX[['동해선 KTX', '전라선 KTX', '경전선 KTX', '호남선 KTX', '경부선 KTX']]

 

4. 데이터 통합하기

1. 세로 방향으로 통합하기

: DataFrame_data1.append(DataFrame_data2[mignore_index=True])

(0) 두 개의 데이터 생성

import pandas as pd
import numpy as np


df1 = pd.DataFrame({'Class1': [95, 92,98,100],
                   'Class2': [91, 93, 97, 99]})
df1

df2 = pd.DataFrame({'Class1':[87, 89],
                   'Class2':[85, 90]})
df2

(1) append()를 통해 합치기

df1.append(df2)

(2) index 예쁘게 정렬하기

df1.append(df2, ignore_index = True)

(3) columns가 같지 않은 데이터를 연결한 경우

  • 새로운 데이터 생성
df3 = pd.DataFrame({'Class1':[96,83]})
df3
  • columns가 같지 않은 데이터 연결
df2.append(df3, ignore_index=True)

2. 가로 방향으로 통합하기

: DataFrame_data1.join(DataFrame_data2)

(0) 새로운 데이터 생성

df4 = pd.DataFrame({"Class3": [93, 91, 95, 98]})
df4

(1) join() 이용하여 연결

df1.join(df4)

(2) index의 라벨을 지정한 경우에도 index가 맞다면 join이 가능

index_label = ['a', 'b', 'c', 'd']
df1a = pd.DataFrame({'Class1': [95, 92,98,100],
                   'Class2': [91, 93, 97, 99]}, index = index_label)
df4a = pd.DataFrame({"Class3": [93, 91, 95, 98]},index = index_label)

df1a.join(df4a)

(3) 크기가 다른 경우

df5 = pd.DataFrame({'Class4': [82, 92]})
df5

df1.join(df5)

3. 특정 열을 기준으로 통합하기

: 두 개의 데이터에 공통된 키(key)가 있을 때, 이 키를 기준으로 두 데이터를 통합한다.

DataFrame_left_data.merge(DataFrame_right_data)

(0) 데이터 생성

df_A_B = pd.DataFrame({'판매월': ['1월', '2월', '3월', '4월'],
                      '제품A': [100, 150, 200,130],
                      '제품B' : [90, 110, 140, 170]})
df_A_B

df_C_D = pd.DataFrame({'판매월': ['1월', '2월', '3월', '4월'],
                      '제품C': [112, 141, 203, 134],
                      '제품D' : [90, 110, 140, 170]})
df_C_D

(1) 통합시키기

df_A_B.merge(df_C_D)

(2) 일부만 공통된 값을 갖는 경우

  • 두 개의 데이터 생성
df_left = pd.DataFrame({'key':['A','B','C'], 'left' : [1, 2, 3]})
df_left

df_right = pd.DataFrame({'key': ['A','B','D'], 'right': [4, 5, 6]})
df_right

  • how 선택인자

df_left.merge(df_right, how = 'left', on = 'key')

df_left.merge(df_right, how = 'right', on = 'key')

df_left.merge(df_right, how = 'outer', on = 'key')

df_left.merge(df_right, how = 'inner', on = 'key')

 

5. 데이터 파일의 읽고 쓰기

1. 표 형식의 데이터 파일을 읽기

: DataFrame_data = pd.read_csv(file_name [,option])

(0)  csv 데이터 파일 생성

%%writefile C:\myPyCode\data\sea_rain1.csv
연도,동해,남해,서해,전체
1996,17.4629,17.2288,14.436,15.9067
1997,17.4116,17.4092,14.8248,16.1526
1998,17.5944,18.011,15.2512,16.6044
1999,18.1495,18.3175,14.8979,16.6284
2000,17.9288,18.1766,15.0504,16.6178

>>> Writing C:\myPyCode\data\sea_rain1.csv

(1) pandas의 read_csv 통해서 csv파일 읽기

import pandas as pd

pd.read_csv('C:/myPyCode/data/sea_rain1.csv')

(2) 윈도우 메모장에 동일 내용 저장 후 sea_rain1_from_notepad.csv 로 저장

(3) 윈도우 메모장으로 저장한 csv 파일 읽어오기

pd.read_csv('C:/myPyCode/data/sea_rain1_from_notepad.csv', encoding = "UTF-8")

(4) 필드를 공백으로 csv 저장하기

%%writefile C:/myPyCode/data/sea_rain_space.txt
연도 동해 남해 서해 전체
1996 17.4629 17.2288 14.436 15.9067
1997 17.4116 17.4092 14.8248 16.1526
1998 17.5944 18.011 15.2512 16.6044
1999 18.1495 18.3175 14.8979 16.6284
2000 17.9288 18.1766 15.0504 16.6178

>>> Writing C:/myPyCode/data/sea_rain_space.txt
  • sep=" " 통해 읽어들이기
pd.read_csv('C:/myPyCode/data/sea_rain_space.txt',sep=" ")

(5) 자동으로 설정된 index가 아닌 특정 열(column)을 지정하고 싶을 때

2. 표 형식의 데이터를 파일로 쓰기

(0) 데이터 생성

df_WH = pd.DataFrame({'Weight': [62, 67, 55, 74],
                     'Height': [165, 177, 160, 180]},
                    index=['ID_1', 'ID_2', 'ID_3', 'ID_4'])
df_WH.index.name = 'User'
df_WH

  • 체질량 지수 구하기
bmi = df_WH['Weight']/(df_WH['Height']/100)**2
bmi

>>> User
    ID_1    22.773186
    ID_2    21.385936
    ID_3    21.484375
    ID_4    22.839506
    dtype: float64

(1) 새로운 열 추가

df['column_name'] = column_data

df_WH['BMI'] = bmi
df_WH

(2) CSV 파일로 저장하기

df_WH.to_csv('C:/myPyCode/data/save_DataFrame.csv')

#저장 후 확인
!type C:\myPyCode\data\save_DataFrame.csv

(3) 저장할 떄 옵션 지정

df_pr = pd.DataFrame({'판매가격':[2000, 3000, 5000, 10000],
                     '판매량':[32,53,40,25]},
                     index=['P1001', 'P1002', 'P1003', 'P1004'])
df_pr.index.name='제품번호'
df_pr

  • 필드는 공백문자 인코딩은 'cp949'로 저장
file_name = 'C:\myPyCode\data\save_DataFrame_cp949.txt'
df_pr.to_csv(file_name, sep=" ", encoding = "cp949")