Learn & Record

Python (pandas, 날짜자동생성, DataFrame 데이터프레임, 연산, 파일읽기, 파일쓰기, 데이터확인, 데이터선택, 무료웹호스팅, 결측데이터, 데이터가공) 본문

Dev/Python

Python (pandas, 날짜자동생성, DataFrame 데이터프레임, 연산, 파일읽기, 파일쓰기, 데이터확인, 데이터선택, 무료웹호스팅, 결측데이터, 데이터가공)

Walker_ 2024. 3. 12. 17:05

1. Pandas

 - numpy의 경우 배열의 모든 원소가 데이터 타입이 같아야 했지만,

 - pandas의 경우에는 원소의 데이터 타입이 달라도 저장 가능

import pandas as pd
import numpy as np

s2 = pd.Series(['a','b','c',5,6,7,8]) # 넘파이 였다면 모두를 문자열로 변경
print(s2)

# 데이터가 없으면 numpy를 임포트한 후에 np.nan으로 데이터가 없음을 표시할 수 있음
# 데이터를 위한 자리 index는 있지만 실제 값이 없음
s3 = pd.Series([np.nan, 10, 30])
print(s3)

# Series 데이터를 생성할 때 다음과 같이 인자로 index 추가 가능
# s = pd.Series(seq_data, index = index_seq)
# 인자로 index를 명시적으로 입력하면 Series 변수(s)의 index에는 자동생성되는 index 대신 index_seq가 들어가게 됨
# index_seq도 리스트와 튜플 타입의 데이터를 모두 사용가능하지만 주로 리스트를 사용
# 주의할 점은 seq_data의 항목 개수와 index_seq의 항목개수가 같아야 함

# 어느 가게의 날짜별 판매량을 pandas의 Series형식으로 입력. 하루는 데이터가 없어서 np.nan을 입력
index_data = ['2018-10-07', '2018-10-08', '2018-10-09', '2018-10-10']
s4 = pd.Series([200, 195, np.nan, 205], index=index_data)
print(s4)
# 2018-10-07    200.0
# 2018-10-08    195.0
# 2018-10-09      NaN
# 2018-10-10    205.0
# dtype: float64


print(s4.index)
# Index(['2018-10-07', '2018-10-08', '2018-10-09', '2018-10-10'], dtype='object')

# 파이썬의 딕셔너리를 사용하면 데이터와 index를 함께 입력할 수 있음
# s = pd.Series(dict_data)
# 입력 인자로 딕셔너리 데이터를 입력하면 딕셔너리 데이터의 키 key와 값 value이 각각
# Series 데이터의 index와 value로 들어감
s5 = pd.Series({'국어' : 100, '영어':95, '수학':90})
print(s5)
# 국어    100
# 영어     95
# 수학     90
# dtype: int64

 

2. 날짜 자동 생성 : date_range

 - 입력해야 할 날짜가 많으면 pandas에서 날짜를 자동생성하는 date_range() 사용.

 - 몇 가지 설정만 하면 원하는 날짜를 자동으로 생성하므로 날짜 데이터를 입력할 때 편리

# pd.date_range(start=None, end=None, periods=None, freq='0')
# start는 시작날짜
# end는 끝날짜
# periods는 날짜 데이터 생성 기간 -> 생성 갯수
# freq는 날짜 데이터 생성 주기
# start는 필수이고, end나 periods는 둘 중 하나만 있어도 됨
# freq는 입력하지 않으면 'D' 옵션이 설정돼 달력날짜 기준으로 하루씩 증가.

 

# * pandas date_range() 함수의 freq 옵션.
# 약어    설명 사용 예
# D : 달력 날짜 기준 하루 주기 ex) 하루 주기: freq = 'D', 이틀 주기: freq = '2D'
# B : 업무 날짜 기준 하루 주기 ex) 업무일(월~금) 기준으로 생성, freq = 'B', freq = '3B'
# W : 일요일 시작 기준 일주일 주기 ex) 월요일: W-MON, 화요일: W-TUE, freq = 'W', freq = 'W-MON'
# M : 월말 날짜 기준 주기 ex) 한 달 주기: freq = 'M', 네 달 주기: freq = '4M'
# BM : 업무 월말 날짜 기준 주기   ex) freq = 'BM' , freq = '2BM'
# MS : 월초 날짜 기준 주기 ex) freq = 'MS' , freq = '2MS'
# BMS : 업무 월초 날짜 기준 주기  ex) freq = 'BMS' , freq = '2BMS'
# Q : 분기 끝 날짜 기준 주기     ex) freq = 'Q' , freq = '2Q'
# BQ : 업무 분기 끝 날짜 기준 주기 ex) freq = 'BQ' , freq = '2BQ'
# QS : 분기 시작 날짜 기준 주기   ex) freq = 'QS' , freq = '2QS'
# BQS : 업무 분기 시작 날짜 기준 주기 ex) freq = 'BQS' , freq = '2BQS'
# A : 일년 끝 날짜 기준 주기    ex) freq = 'A' , freq = '2A'
# BA : 업무 일년 끝 날짜 기준 주기 ex) freq = 'BA' , freq = '2BA'
# AS : 일년 시작 날짜 기준 주기 ex) freq = 'AS' , freq = '2AS'
# BAS : 업무 일년 시작 날짜 기준 주기 ex) freq = 'BAS' , freq = '2BAS'
# H : 시간 기준 주기 ex) 1시간 주기: freq = 'H' , 2시간 주기: freq = '2H'
# BH : 업무 시간 기준 주기 ex) 업무 시간(09:00 ~ 17:00) 기준으로 생성
# T, min : 분 주기 ex) 10분 주기: freq = '10T' , 30분 주기: freq = '30min'
# S : 초 주기 ex) 1초 주기: freq = 'S' , 10초 주기: freq = '10S'

 

import pandas as pd

# 시작 날짜와 끝 날짜를 지정해 날짜 데이터를 생성. 하루씩 증가한 날짜 데이터가 생성
print(pd.date_range(start='2019-01-01', end='2019-01-07'))
# DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
#                '2019-01-05', '2019-01-06', '2019-01-07'],
#               dtype='datetime64[ns]', freq='D')


# 날짜 데이터를 입력할 때 yyyy-mm-dd 형식이 아니라
# yyyy/mm/dd, yyyy.mm.dd, mm-dd-yyyy, mm/dd/yyyy, mm.dd.yyyy 같은 형식도 사용가능하고
# 대신 출력은 yyyy-mm-dd 형식으로 생성

print(pd.date_range(start='2019/01/01', end='2019.01.07'))
# DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
#                '2019-01-05', '2019-01-06', '2019-01-07'],
#               dtype='datetime64[ns]', freq='D')

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

print(pd.date_range(start='2019-01-01', end='01.07.2019'))
# DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
#                '2019-01-05', '2019-01-06', '2019-01-07'],
#               dtype='datetime64[ns]', freq='D')

# 끝 날짜를 지정하지 않고 periods만 입력해서 날짜 생성
print(pd.date_range(start='2019-01-01', periods=7))
# DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
#                '2019-01-05', '2019-01-06', '2019-01-07'],
#               dtype='datetime64[ns]', freq='D')

# 2일씩 증가하는 날짜를 생성
print(pd.date_range(start='2019-01-01', periods=4, freq='2D'))
# DatetimeIndex(['2019-01-01', '2019-01-03', '2019-01-05', '2019-01-07'], dtype='datetime64[ns]', freq='2D')

#달력의 요일을 기준으로 일주일씩 증가하는 날짜를 생성
print(pd.date_range(start='2019-01-01', periods=4, freq='W'))
# DatetimeIndex(['2019-01-06', '2019-01-13', '2019-01-20', '2019-01-27'], dtype='datetime64[ns]', freq='W-SUN')

# 업무일 기준 2개월 월말 주기로 12개 날짜를 생성
print(pd.date_range(start='2019-01-01', periods=12, freq='2BM'))
# DatetimeIndex(['2019-01-31', '2019-03-29', '2019-05-31', '2019-07-31',
#                '2019-09-30', '2019-11-29', '2020-01-31', '2020-03-31',
#                '2020-05-29', '2020-07-31', '2020-09-30', '2020-11-30'],
#               dtype='datetime64[ns]', freq='2BM')

# 분기 시작일을 기준으로 4개의 날짜를 생성
print(pd.date_range(start='2019-01-01', periods=4, freq='QS'))
# DatetimeIndex(['2019-01-01', '2019-04-01', '2019-07-01', '2019-10-01'], dtype='datetime64[ns]', freq='QS-JAN')

 

 - 날짜뿐 아니라 시간을 생성하는 방법

# 1시간 주기로 10개의 시간을 생성한 예
print(pd.date_range(start='2019-01-01 08:00', periods=10, freq='H'))
# DatetimeIndex(['2019-01-01 08:00:00', '2019-01-01 09:00:00',
#                '2019-01-01 10:00:00', '2019-01-01 11:00:00',
#                '2019-01-01 12:00:00', '2019-01-01 13:00:00',
#                '2019-01-01 14:00:00', '2019-01-01 15:00:00',
#                '2019-01-01 16:00:00', '2019-01-01 17:00:00'],
#               dtype='datetime64[ns]', freq='H')

# 업무 시간을 기준으로 1시간 주기로 10개의 시간을 생성하는 예
# 업무 시간은 9시 부터 17시까지이므로 start시간을 9시 이전으로 설정해도 9시부터 표시
print(pd.date_range(start='2019-01-01 08:00', periods=10, freq='BH'))
# DatetimeIndex(['2019-01-01 09:00:00', '2019-01-01 10:00:00',
#                '2019-01-01 11:00:00', '2019-01-01 12:00:00',
#                '2019-01-01 13:00:00', '2019-01-01 14:00:00',
#                '2019-01-01 15:00:00', '2019-01-01 16:00:00',
#                '2019-01-02 09:00:00', '2019-01-02 10:00:00'],
#               dtype='datetime64[ns]', freq='BH')

# date_range()를 이용해 Series의 index를 지정한 예.
index_date = pd.date_range(start='2019-03-01', periods=5, freq='D')
s = pd.Series([51, 62, 55, 49, 58], index=index_date)
print(s)
# 2019-03-01    51
# 2019-03-02    62
# 2019-03-03    55
# 2019-03-04    49
# 2019-03-05    58
# Freq: D, dtype: int64

 

 

3. 데이터프레임 DateFrame

 - 표 Table와 2차원 데이터 처리를 위해 DataFrame을 제공

 - 데이터 Data를 담는 틀 Frame 이라는 뜻

# DataFrame을 이용해 데이터를 생성하는 방법
# df = pd.DataFrame(data [, index = index_data, columns = columns_data])
# data 인자에는 리스트와 형태가 유사한 데이터 타입은 모두 사용 가능
# 즉 리스트, 딕셔너리, numpy의 배열 데이터, Series나 DataFrame 타입의 데이터 입력 가능
# 세로축 라벨ㅇ르 index라 하고, 가로축 라벨을 columns라고 함
# index와 columns를 제외한 부분을 values라고 하고 values가 관심있는 데이터

 

import pandas as pd

d1 = pd.DataFrame([[1,2,3], [4,5,6], [7,8,9]])
print(d1)
#    0  1  2
# 0  1  2  3
# 1  4  5  6
# 2  7  8  9


# values 부분에는 입력한 data가 순서대로 입력돼 있고
# 가장 좌측의 열과 가장 윗줄의 행에는 각각 숫자가 자동으로 생성되어 index, columns를 구성
# 명시적으로 index와 columns를 입력하지 않더라도 자동으로 index, columns가 생성

# numpy의 배열 데이터를 입력해 생성한 DataFrame 데이터의 예
import numpy as np
data_list = np.array([[10,20,30], [40,50,60], [70,80,90]])
print(data_list)
# [[10 20 30]
#  [40 50 60]
#  [70 80 90]]

d2 = pd.DataFrame(data_list)
print(d2)
#     0   1   2
# 0  10  20  30
# 1  40  50  60
# 2  70  80  90

# data뿐만 아니라 index와 columns도 지정한 예
data = np.array([[1,2,3], [4,5,6], [7,8,9], [10,11,12]]) # values
index_data = pd.date_range('2019-09-01', periods=4)
columns_list = ['A', 'B', 'C']
d3 = pd.DataFrame(data=data, index=index_data, columns=columns_list)
print(d3)
#              A   B   C
# 2019-09-01   1   2   3
# 2019-09-02   4   5   6
# 2019-09-03   7   8   9
# 2019-09-04  10  11  12

# 딕셔너리 타입으로 2차원 데이터를 입력한 예
table_data = {'연도': [2015, 2016, 2016, 2017, 2017],
              '지사': ['한국', '한국', '미국', '한국','미국'],
              '고객 수': [200, 250, 450, 300, 500]}
d4 = pd.DataFrame(table_data)
print(d4)
#      연도  지사  고객 수
# 0  2015  한국   200
# 1  2016  한국   250
# 2  2016  미국   450
# 3  2017  한국   300
# 4  2017  미국   500

# 리스트나 넘파이 배열은 행 단위로 입력이 되고, 딕셔너리는 열 단위로 입력됨

# 입력시 키의 순서를 지정할 수도 있음
d5 = pd.DataFrame(table_data, columns=['지사', '고객 수', '연도'])
print(d5)
#    지사  고객 수    연도
# 0  한국   200  2015
# 1  한국   250  2016
# 2  미국   450  2016
# 3  한국   300  2017
# 4  미국   500  2017

# DataFrame 데이터에서 index, columns, values을 각각 구한 예
print(d5.index) # RangeIndex(start=0, stop=5, step=1)
print(d5.columns) # Index(['지사', '고객 수', '연도'], dtype='object')
print(d5.values)
# [['한국' 200 2015]
#  ['한국' 250 2016]
#  ['미국' 450 2016]
#  ['한국' 300 2017]
#  ['미국' 500 2017]]

 

4. 데이터 연산

# pandas의 Series()와 DataFrame()으로 생성된 데이터 끼리는 사칙연산이 가능
# Series()로 생성한 데이터의 예
import pandas as pd

s1 = pd.Series([1,2,3,4,5])
s2 = pd.Series([10, 20, 30, 40, 50])
print(s1 + s2)
# 0    11
# 1    22
# 2    33
# 3    44
# 4    55
# dtype: int64

print(s2-s1)
# 0     9
# 1    18
# 2    27
# 3    36
# 4    45
# dtype: int64

print(s1 * s2)
# 0     10
# 1     40
# 2     90
# 3    160
# 4    250
# dtype: int64

print(s2/s1)
# 0    10.0
# 1    10.0
# 2    10.0
# 3    10.0
# 4    10.0
# dtype: float64

# 파이썬의 리스트와 numpy의 배열과 달리 pandas의 데이터 끼리는 서로 크기가 달라도 연산이 가능
# 이 경우 연산을 할 수 있는 항목과 연산을 수행
s3 = pd.Series([1,2,3,4])
s4 = pd.Series([10, 20, 30, 40, 50])
print(s3 + s4)
# 0    11.0
# 1    22.0
# 2    33.0
# 3    44.0
# 4     NaN
# dtype: float64

print(s4-s3)
# 0     9.0
# 1    18.0
# 2    27.0
# 3    36.0
# 4     NaN
# dtype: float64

print(s3 * s4)
# 0     10.0
# 1     40.0
# 2     90.0
# 3    160.0
# 4      NaN
# dtype: float64

print(s4/s3)
# 0    10.0
# 1    10.0
# 2    10.0
# 3    10.0
# 4     NaN
# dtype: float64

# s3와 s4의 데이터 크기가 달라서, 연산할 수 있는 부분만 연산한 결과를 보여주고 연산할 수 없는 부분은 NaN으로 표시

# DataFrame()으로 생성한 데이터의 예
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)
print(df1)
#    A   B    C
# 0  1  10  100
# 1  2  20  200
# 2  3  30  300
# 3  4  40  400
# 4  5  50  500

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

# 두 개의 DataFrame 데이터 df1과 df2는 길이가 같지 않음
# 길이가 같지 않더라도 연산이 가능
print(df1 + df2)
#       A      B       C
# 0   7.0   70.0   700.0
# 1   9.0   90.0   900.0
# 2  11.0  110.0  1100.0
# 3   NaN    NaN     NaN
# 4   NaN    NaN     NaN

# Series와 마찬가지로 DataFrame도 연산할 수 있는 항목 끼리만 연산하고 그렇지 못한 항목은 NaN으로 표시
# 공간은 차지하되 데이터는 없는 상태

# pandas에는 데이터의 통계 분석을 위한 다양한 메서드가 있어서 데이터의 총합, 평균, 표준 편차들을 쉽게 구할 수 있음
# 2012년 부터 2016년 까지 우리나라의 계절별 강수량(단위 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 = ['2012', '2013', '2014','2015','2016']
df3 = pd.DataFrame(index = index_list, columns=columns_list, data = table_data3)
print(df3)
#           봄     여름     가을     겨울
# 2012  256.5  770.6  363.5  139.3
# 2013  264.3  567.5  231.2   59.9
# 2014  215.9  599.8  293.1   76.9
# 2015  223.2  387.1  247.7  109.1
# 2016  312.8  446.2  381.6  108.1

# pandas에서 제공하는 통계 메서드는 원소의 합을 구하는 sum(), 평균을 구하는 mean(),
# 표준편차를 구하는 std(), 분산을 구하는 var(), 최솟값을 구하는 min(), 최댓값을 구하는 max(),
# 각 원소의 누적 합을 구하는 cumsum(), 각 원소의 누적 곱을 구하는 cumprod() 등이 있음
# -> numpy의 메서드 이름이 동일

print(df3.std()) # 계절별 강수량 표준편차
# 봄      38.628267
# 여름    148.888895
# 가을     67.358496
# 겨울     30.925523
# dtype: float64

# 연도별로 평균 강수량과 표준 편차를 구할 경우엔 연산의 방향 설정을 위해 axis 인자를 추가
# 인자 axis가 0이면 DataFrame의 values에서 열별로 연산을 수행하고
# 1이면 행별로 연산. axis 인자를 설정하지 ㅇ낳으면 기본값을 0으로 설정
print(df3.mean(axis=1))
# 2012    382.475
# 2013    280.725
# 2014    296.425
# 2015    241.775
# 2016    312.175
# dtype: float64

print(df3.std(axis=1))
# 2012    274.472128
# 2013    211.128782
# 2014    221.150739
# 2015    114.166760
# 2016    146.548658
# dtype: float64

# 평균과 표준편차를 개별적으로 구했으나 describe()을 이용하면
# 평균, 표준편차, 최솟값과 최댓값 등을 한 번에 구할 수 있음
# 25% / 50% / 75% : 백분위수의 각 지정으로, 분포를 반영해 평균을 보완하는 목적으로 사용
print(df3.describe())
#                 봄          여름          가을          겨울
# count    5.000000    5.000000    5.000000    5.000000
# mean   254.540000  554.240000  303.420000   98.660000
# std     38.628267  148.888895   67.358496   30.925523
# min    215.900000  387.100000  231.200000   59.900000
# 25%    223.200000  446.200000  247.700000   76.900000
# 50%    256.500000  567.500000  293.100000  108.100000
# 75%    264.300000  599.800000  363.500000  109.100000
# max    312.800000  770.600000  381.600000  139.300000

 

5. 데이터파일 읽기

import pandas as pd

# 1) 표 형식의 데이터 파일을 읽기
# 판다스에서 csv파일을 읽을 때는 read_csv() 메서드 이용
# DataFrame_data = pd.read_csv(file_name [, options])
df1 = pd.read_csv('./input/sea_rain1.csv')
print(df1)
#      연도       동해       남해       서해       전체
# 0  1996  17.4629  17.2288  14.4360  15.9067
# 1  1997  17.4116  17.4092  14.8248  16.1526
# 2  1998  17.5944  18.0110  15.2512  16.6044
# 3  1999  18.1495  18.3175  14.8979  16.6284
# 4  2000  17.9288  18.1766  15.0504  16.6178

print(df1.dtypes)
# 연도      int64
# 동해    float64
# 남해    float64
# 서해    float64
# 전체    float64
# dtype: object

# 파이썬에서 텍스트파일을 생성하면 기본 문자 인코딩이 'utf-8'이고, 메모장의 경우 기본 문자 인코딩이 'cp949'.
# sea_rain1_from_notepad.csv 파일을 경우 메모장으로 생성해서, 인코딩이 'cp949'이므로 에러가 남

d2 = pd.read_csv('./input/sea_rain1_from_notepad.csv', encoding='cp949')
print(d2)
#      연도       동해       남해       서해       전체
# 0  1996  17.4629  17.2288  14.4360  15.9067
# 1  1997  17.4116  17.4092  14.8248  16.1526
# 2  1998  17.5944  18.0110  15.2512  16.6044
# 3  1999  18.1495  18.3175  14.8979  16.6284
# 4  2000  17.9288  18.1766  15.0504  16.6178

# seq_rain1_space.txt 파일의 경우 콤마가 아니라 공백(빈칸)으로 구분된 경우
# sep 옵션을 이용해서 구분차가 콤마가 아니라 공백임을 지정
# 아래 처럼 확장자가 txt라도 read_csv()로 읽을 수 있음
d3 = pd.read_csv('./input/sea_rain1_space.txt', sep=' ')
print(d3)
#      연도       동해       남해       서해       전체
# 0  1996  17.4629  17.2288  14.4360  15.9067
# 1  1997  17.4116  17.4092  14.8248  16.1526
# 2  1998  17.5944  18.0110  15.2512  16.6044
# 3  1999  18.1495  18.3175  14.8979  16.6284
# 4  2000  17.9288  18.1766  15.0504  16.6178

# read_csv()로 텍스트 파일을 읽어오면 index가 자동으로 지정
# 이 때 자동으로 생성된 index 말고 데이터 파일에서 특정 열 column을 index로 선택하려면 'index_col=열_이름'을 추가
c4 = pd.read_csv('./input/sea_rain1.csv', index_col='연도')
print(c4)
#            동해       남해       서해       전체
# 연도
# 1996  17.4629  17.2288  14.4360  15.9067
# 1997  17.4116  17.4092  14.8248  16.1526
# 1998  17.5944  18.0110  15.2512  16.6044
# 1999  18.1495  18.3175  14.8979  16.6284
# 2000  17.9288  18.1766  15.0504  16.6178

 

6. 데이터 파일 쓰기

# to_csv()을 이용하면 DataFrame 형식의 데이터를 텍스트 파일로 저장
# DataFrame_data.to_csv(file_name [, options])
# file_name은 텍스트 파일 이름으로 경로를 포함할 수 있음
# 선택사항인 options에는 구분자와 문자의 인코딩 방식 등을 지정할 수 있고, 지정하지 않으면 구분자는 콤마가 되고, 문자의 인코딩 방식은 'utf-8'이 됨

 

import pandas as pd

# to_csv()을 이용하면 DataFrame 형식의 데이터를 텍스트 파일로 저장
# DataFrame_data.to_csv(file_name [, options])
# file_name은 텍스트 파일 이름으로 경로를 포함할 수 있음
# 선택사항인 options에는 구분자와 문자의 인코딩 방식 등을 지정할 수 있고, 지정하지 않으면 구분자는 콤마가 되고, 문자의 인코딩 방식은 'utf-8'이 됨

# 네 명의 몸무게 Weight와 키 Height 데이터를 DataFrame 형식으로 생성
df_WH = pd.DataFrame({'Weight': [62, 67, 55, 74],
                      'Height': [165, 177, 160, 180]},
                     index=['ID_1', 'ID_2', 'ID_3', 'ID_4'])
print(df_WH)
#       Weight  Height
# ID_1      62     165
# ID_2      67     177
# ID_3      55     160
# ID_4      74     180

df_WH.index.name = 'User'
print(df_WH)
#       Weight  Height
# User
# ID_1      62     165
# ID_2      67     177
# ID_3      55     160
# ID_4      74     180

# 파일로 저장하기 전에 몸무게와 키를 이용해 체질량 지수 BMI를 구해서 추가
# 체질량 지수 Body Mass Index는 몸무게 Kg
# BMI = W / H의 제곱

# 키의 경우 데이터가 cm단위여서 m 단위로 변경
bmi =df_WH['Weight'] / (df_WH['Height']/100) ** 2
print(bmi)
# User
# ID_1    22.773186
# ID_2    21.385936
# ID_3    21.484375
# ID_4    22.839506
# dtype: float64

# 체질량 지수를 df_WH에 추가.
df_WH['BMI'] = bmi
print(df_WH)
#       Weight  Height        BMI
# User
# ID_1      62     165  22.773186
# ID_2      67     177  21.385936
# ID_3      55     160  21.484375
# ID_4      74     180  22.839506

# csv 파일 저장
df_WH.to_csv('./output/save_dataFrame.csv')

# DataFrame 데이터를 파일로 저장할 때 옵션을 지정하는 예
# 한 회사의 제품별 판매 가격과 판매량 정보가 있는 DataFrame 데이터를 생성
df_pr = pd.DataFrame({'판매가격' : [2000, 3000, 5000, 10000],
                      '판매량' : [32, 53, 40, 25]},
                     index=['P1001', 'P1002', 'P1003', 'P1004'])
df_pr.index.name = '제품번호'
print(df_pr)
#         판매가격  판매량
# 제품번호
# P1001   2000   32
# P1002   3000   53
# P1003   5000   40
# P1004  10000   25

file_name = './output/save_DataFrame_cp949.txt'
df_pr.to_csv(file_name, sep=' ', encoding='cp949')

 

7. 판다스 데이터 확인하기

 - 판다스에는 데이터 분석에 유용한 여러 가지 메서드와 속성이 미리 정의되어 있음

import pandas as pd

# 1) DataFrame 만들기
# csv 파일 불러오기
# csv 파일을 불러와서 데이터프레임을 생성

df = pd.read_csv('./input/weather.csv')
print(df) # 주피터 노트북에서 df만 기입 시 데이터를 모두 읽음

#             date  temp  max_wind  mean_wind
# 0     2010-08-01  28.7       8.3        3.4
# 1     2010-08-02  25.2       8.7        3.8
# 2     2010-08-03  22.1       6.3        2.9
# 3     2010-08-04  25.3       6.6        4.2
# 4     2010-08-05  27.2       9.1        5.6
# ...          ...   ...       ...        ...
# 3648  2020-07-27  22.1       4.2        1.7
# 3649  2020-07-28  21.9       4.5        1.6
# 3650  2020-07-29  21.6       3.2        1.0
# 3651  2020-07-30  22.9       9.7        2.4
# 3652  2020-07-31  25.7       4.8        2.5
#
# [3653 rows x 4 columns]


# 2) df.shape
# shape 속성을 이용하면 데이터의 (행, 열) 크기를 확인할 수 있음
# 행, 열 크기 확인하기
print(df.shape) # (3653, 4)
print(df.shape[0]) # 3653


# 3) df.info()
# info()메서드는 데이터에 대한 전반적인 정보를 나타냄
# df를 구성하는 행과 열의 크기, 컬럼명, 컬럼을 구성한느 값의 자료형을 출력해줌
df.info()

# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 3653 entries, 0 to 3652
# Data columns (total 4 columns):
#  #   Column     Non-Null Count  Dtype
# ---  ------     --------------  -----
#  0   date       3653 non-null   object
#  1   temp       3653 non-null   float64
#  2   max_wind   3649 non-null   float64
#  3   mean_wind  3647 non-null   float64
# dtypes: float64(3), object(1)
# memory usage: 114.3+ KB

# -> 데이터 개수 n=3653 entry, 행 인덱스 번호 0 to 3652
# 열 변수 출력 형식 : 실수 float, 문자열 object
# 결측치 개수가 나타남 : max_wind, mean_wind 변수에 결측치가 있음


# 4) df.head(), df.tail()
# 데이터를 잘 불러 왔는지 확인하기 위해 앞 부분과 마지막 부분을 확인
# 상위 n행 살펴보기
print(df.head()) # 숫자 기입 시, 개수 행 출력. 기본 = 5
#          date  temp  max_wind  mean_wind
# 0  2010-08-01  28.7       8.3        3.4
# 1  2010-08-02  25.2       8.7        3.8
# 2  2010-08-03  22.1       6.3        2.9
# 3  2010-08-04  25.3       6.6        4.2
# 4  2010-08-05  27.2       9.1        5.6

# 하위 n행 살펴보기
print(df.tail())
#             date  temp  max_wind  mean_wind
# 3648  2020-07-27  22.1       4.2        1.7
# 3649  2020-07-28  21.9       4.5        1.6
# 3650  2020-07-29  21.6       3.2        1.0
# 3651  2020-07-30  22.9       9.7        2.4
# 3652  2020-07-31  25.7       4.8        2.5

# head()는 상위 5개 행을 출력하고, tail()은 하위 5개 행을 출력함
# 괄호() 안에 원하는 숫자를 넣으면 그 숫자만큼 행을 출력


# 5) df.index, df.columns
# 인덱스(행 이름)과 열의 레이블(칼럼 이름)을 출력할 때 사용
# 인덱스 출력
print(df.index) # RangeIndex(start=0, stop=3653, step=1)
# 데이터프레임의 인덱스(행 이름)을 반환. 인덱스를 따로 지정하지 않았기 때문에 0부터 시작하는 인덱스가 부여.

# 칼럼 출력
print(df.columns)
# Index(['date', 'temp', 'max_wind', 'mean_wind'], dtype='object')

# 해당 데이터프레임을 구성하는 컬럼명을 확인할 수 있음
# 컬럼명을 변경할 때도 유용하게 사용


# 6) df.describe()
# 데이터의 컬럼별 요약 통계량을 나타냄
# 또한 mean(), max() 등 개별 함수를 사용하여 통계량을 계산 할 수 있음
# 요약 통계량 확인하기
print(df.describe())
#               temp     max_wind    mean_wind
# count  3653.000000  3649.000000  3647.000000
# mean     12.942102     7.911099     3.936441
# std       8.538507     3.029862     1.888473
# min      -9.000000     2.000000     0.200000
# 25%       5.400000     5.700000     2.500000
# 50%      13.800000     7.600000     3.600000
# 75%      20.100000     9.700000     5.000000
# max      31.300000    26.000000    14.900000


# 7) df.sort_values()
# 데이터를 크기 순으로 정렬
# 형식
# DataFrame.sort_values(by=['정렬변수1', '정렬변수2'...], ascending=True, inplace=False)
# by=[] : by=을 사용하지 않아도 됨
# ascending=True : True가 기본 값이고 오름차순 정렬. 내림차순 정렬일 경우에는 False 사용.
# inplace=False : True 이면 정렬 결과가 동일 데이터프레임 이름으로 저장. 기본 값을 False.

# 최대 풍속 max_wind 컬럼의 값의 크기에 따라 오름차순 정렬
# 값이 같을 경우 인덱스값이 큰 순서대로 정렬
print(df.sort_values(['max_wind']))

#             date  temp  max_wind  mean_wind
# 1514  2014-09-23  20.7       2.0        1.0
# 1134  2013-09-08  20.4       2.1        0.8
# 421   2011-09-26  18.7       2.1        0.3
# 1512  2014-09-21  20.4       2.2        1.2
# 1005  2013-05-02   7.1       2.2        0.8
# ...          ...   ...       ...        ...
# 2988  2018-10-06  19.4      26.0        7.0
# 559   2012-02-11  -0.7       NaN        NaN
# 560   2012-02-12   0.4       NaN        NaN
# 561   2012-02-13   4.0       NaN        NaN
# 3183  2019-04-19   7.8       NaN        2.3
# 
# [3653 rows x 4 columns]


# 최대 풍속 max wind 컬럼의 값의 크기에 따라 내림차순 정렬
print(df.sort_values(by=['max_wind'], ascending=False))
#             date  temp  max_wind  mean_wind
# 2988  2018-10-06  19.4      26.0        7.0
# 3340  2019-09-23  15.0      25.8       11.0
# 1850  2015-08-25  20.1      25.3       14.9
# 3339  2019-09-22  15.7      23.1       11.9
# 1851  2015-08-26  17.4      22.6        8.1
# ...          ...   ...       ...        ...
# 1514  2014-09-23  20.7       2.0        1.0
# 559   2012-02-11  -0.7       NaN        NaN
# 560   2012-02-12   0.4       NaN        NaN
# 561   2012-02-13   4.0       NaN        NaN
# 3183  2019-04-19   7.8       NaN        2.3
#
# [3653 rows x 4 columns]


# 8) df.value_count()
# 범주형 변수의 빈도분석 결과를 출력. 즉 어떤 컬럼의 unique value(고유값)들의 개수를 구함
bank = pd.read_csv('./input/bank.csv')
print(bank.head())
#            job  education  balance  duration   y
# 0   management   tertiary     2143       261  no
# 1   technician  secondary      265       348  no
# 2  blue-collar  secondary       -7       365  no
# 3   technician  secondary       -3      1666  no
# 4   technician  secondary     -103       145  no

# 빈도 분석 출력하기
print(bank['job'].value_counts())
# job
# management       1560
# blue-collar      1499
# technician       1206
# admin.            834
# services          661
# retired           351
# self-employed     256
# entrepreneur      239
# unemployed        223
# housemaid         208
# student           153
# Name: count, dtype: int64

print(bank['education'].value_counts())
# education
# secondary    3745
# tertiary     2178
# primary      1038
# Name: count, dtype: int64

print(bank['job'].value_counts(ascending=True)) # 오름차순 정렬
# job
# student           153
# housemaid         208
# unemployed        223
# entrepreneur      239
# self-employed     256
# retired           351
# services          661
# admin.            834
# technician       1206
# blue-collar      1499
# management       1560
# Name: count, dtype: int64


# 9) df.unique()
# 데이터가 무엇으로 구성되어 있는지 보고싶을 때 사용. 열의 고유값을 볼 수 있음
# column의 고유값 출력하기
print(bank['job'].unique())
# ['management' 'technician' 'blue-collar' 'retired' 'services' 'admin.'
#  'entrepreneur' 'self-employed' 'unemployed' 'student' nan 'housemaid']


# 음식적이 많은 음식골목명을 순서대로 출력
daegu_food = pd.read_csv('./input/daegufood_street.csv')
daegu_food_summary = daegu_food['음식골목명'].value_counts()
daegu_food_summary.to_csv('./output/daegufood_steet_summary.csv')

sangga_info_kb = pd.read_csv('./input/소상공인시장진흥공단_상가(상권)정보/소상공인시장진흥공단_상가(상권)정보_경북_202312.csv')
sangga_info_kb['시군구명'].value_counts().to_csv('./output/gk_store_01.csv')
sangga_info_kb['시군구명'].value_counts(ascending=True).head().to_csv('./output/gk_store_02.csv')
sangga_info_kb['상권업종대분류명'].value_counts(ascending=True).head(3).to_csv('./output/gk_store_03.csv')

 

8. 판다스 데이터 선택하기

# Pandas DataFrame으로 부터 데이터를 선택하는 다양한 방법

import pandas as pd

# 1) 열 선택하기
# DataFrame의 하나의 열을 선택하면 하나의 Series를 만듬
# df['컬럼명']는 df.컬럼명과 같음. 단, 이 방법을 사용하려면 열 이름이 숫자로 시작하지 않고 공백이나 특수 문자 등을 포함하지 않는 등의
# 조건을 만족해야함
# iloc() 및 loc() 메서드를 사용하여 려러 열을 선택할 수도 있음

# 단일 컬럼 선택하기
df = pd.read_csv('./input/weather.csv')
print(df['temp'])
# 0       28.7
# 1       25.2
# 2       22.1
# 3       25.3
# 4       27.2
#         ...
# 3648    22.1
# 3649    21.9
# 3650    21.6
# 3651    22.9
# 3652    25.7
# Name: temp, Length: 3653, dtype: float64

print(df.temp)
# 0       28.7
# 1       25.2
# 2       22.1
# 3       25.3
# 4       27.2
#         ...
# 3648    22.1
# 3649    21.9
# 3650    21.6
# 3651    22.9
# 3652    25.7
# Name: temp, Length: 3653, dtype: float64

# 여러 컬럼 선택하기
# 추출할 때 열 이름을 리스트에 저장한 다음 []에 전달하면 여러 열을 선택할 수 있음
print(df[['date', 'temp']])
#             date  temp
# 0     2010-08-01  28.7
# 1     2010-08-02  25.2
# 2     2010-08-03  22.1
# 3     2010-08-04  25.3
# 4     2010-08-05  27.2
# ...          ...   ...
# 3648  2020-07-27  22.1
# 3649  2020-07-28  21.9
# 3650  2020-07-29  21.6
# 3651  2020-07-30  22.9
# 3652  2020-07-31  25.7
#
# [3653 rows x 2 columns]

# 여러 컬럼 선택하기 : loc
# 열 이름을 사용하여 열을 선택하려는 경우 loc를 사용
# df.loc[행 인덱싱 값, 열 인덱싱 값]
df.loc[:, ['date', 'temp']]
#             date  temp
# 0     2010-08-01  28.7
# 1     2010-08-02  25.2
# 2     2010-08-03  22.1
# 3     2010-08-04  25.3
# 4     2010-08-05  27.2
# ...          ...   ...
# 3648  2020-07-27  22.1
# 3649  2020-07-28  21.9
# 3650  2020-07-29  21.6
# 3651  2020-07-30  22.9
# 3652  2020-07-31  25.7
#
# [3653 rows x 2 columns]


# 여러 컬럼 선택하기 : iloc

# 열 인덱스를 사용하여 추출
# df.iloc[행 인덱스, 열 인덱스]
print(df.iloc[:, [0,1]])
# date  temp
# 0     2010-08-01  28.7
# 1     2010-08-02  25.2
# 2     2010-08-03  22.1
# 3     2010-08-04  25.3
# 4     2010-08-05  27.2
# ...          ...   ...
# 3648  2020-07-27  22.1
# 3649  2020-07-28  21.9
# 3650  2020-07-29  21.6
# 3651  2020-07-30  22.9
# 3652  2020-07-31  25.7
#
# [3653 rows x 2 columns]


# 2) 행 선택하기
# 특정 행 범위 선택하기
# 인덱스 숫자를 사용하면 행을 슬라이싱할 수 있음
print(df[0:3])
#          date  temp  max_wind  mean_wind
# 0  2010-08-01  28.7       8.3        3.4
# 1  2010-08-02  25.2       8.7        3.8
# 2  2010-08-03  22.1       6.3        2.9


# 3) 레이블로 선택하기 df.loc
# 특정 날짜에 해당하는 열 선택
df.index = df['date'] # 인덱스 값으로 df['date']을 설정
print(df)
#  date  temp  max_wind  mean_wind
# date
# 2010-08-01  2010-08-01  28.7       8.3        3.4
# 2010-08-02  2010-08-02  25.2       8.7        3.8
# 2010-08-03  2010-08-03  22.1       6.3        2.9
# 2010-08-04  2010-08-04  25.3       6.6        4.2
# 2010-08-05  2010-08-05  27.2       9.1        5.6
# ...                ...   ...       ...        ...
# 2020-07-27  2020-07-27  22.1       4.2        1.7
# 2020-07-28  2020-07-28  21.9       4.5        1.6
# 2020-07-29  2020-07-29  21.6       3.2        1.0
# 2020-07-30  2020-07-30  22.9       9.7        2.4
# 2020-07-31  2020-07-31  25.7       4.8        2.5
#
# [3653 rows x 4 columns]


print(df.loc['2010-08-01', ['temp', 'mean_wind']])
# temp         28.7
# mean_wind     3.4
# Name: 2010-08-01, dtype: object

# 4) 위치로 선택하기 df.iloc
# iloc[n]과 같이 정수를 입력하면 해당 행을 선택. iloc 이후에 붙은 숫자 3은
# (위에서 0부터 시작) 4번째 행이라는 뜻

# 특정 행 선택
print(df.iloc[3])
# date         2010-08-04
# temp               25.3
# max_wind            6.6
# mean_wind           4.2
# Name: 2010-08-04, dtype: object

# 특정 행과 열 선택 : 슬라이싱
print(df.iloc[1:3, 0:2])
#               date  temp
# date
# 2010-08-02  2010-08-02  25.2
# 2010-08-03  2010-08-03  22.1


# 5) 불 인덱싱
# 하나의 열의 값을 기준으로 데이터를 선택할 수 있음
# df[df.A > 0]은 df로 부터 A열이 0보다 큰 데이터를 보여줌.

# 조건에 맞는 데이터를 추출
w = df['temp'] > 30
print(w)
# date
# 2010-08-01    False
# 2010-08-02    False
# 2010-08-03    False
# 2010-08-04    False
# 2010-08-05    False
#               ...
# 2020-07-27    False
# 2020-07-28    False
# 2020-07-29    False
# 2020-07-30    False
# 2020-07-31    False
# Name: temp, Length: 3653, dtype: bool

print(df[w])
#                   date  temp  max_wind  mean_wind
# date
# 2013-08-08  2013-08-08  31.3       7.8        4.6
# 2013-08-09  2013-08-09  30.6       9.9        6.4
# 2013-08-10  2013-08-10  30.6       7.4        3.8
# 2018-07-23  2018-07-23  30.5       6.5        1.6
# 2018-08-04  2018-08-04  30.3       5.8        3.0

# 기온 temp이 30도 이상인 모든 데이터를 추출. 넘파이의 불 인덱싱과 동일한 문법
print(df[df['temp']>30])
#                   date  temp  max_wind  mean_wind
# date
# 2013-08-08  2013-08-08  31.3       7.8        4.6
# 2013-08-09  2013-08-09  30.6       9.9        6.4
# 2013-08-10  2013-08-10  30.6       7.4        3.8
# 2018-07-23  2018-07-23  30.5       6.5        1.6
# 2018-08-04  2018-08-04  30.3       5.8        3.0

# 최고로 더웠던 날의 모든 정보를 추출
w = df['temp'] == df['temp'].max()
print(df[w])
#                   date  temp  max_wind  mean_wind
# date
# 2013-08-08  2013-08-08  31.3       7.8        4.6

# 조건이 2개 이상인 겨우
# 기온이 30도 이상이고, 최대 풍속이 9이상인 데이터
w = (df['temp']>= 30) & (df['max_wind'] >= 9)
print(df[w])
#                   date  temp  max_wind  mean_wind
# date
# 2013-08-09  2013-08-09  30.6       9.9        6.4

9. 무료 웹 호스팅

https://www.dothome.co.kr/

 

무료홈페이지 | 무료호스팅 | 닷홈

닷홈은 도메인, 무료호스팅, 무료홈페이지, 웹호스팅, 웹메일, SSL보안인증서, 서버호스팅 등 호스팅 서비스를 제공하고 있습니다.

www.dothome.co.kr

 - 닷홈 접속 > 회원가입

 

 - 웹 호스팅 > 무료호스팅 클릭

 - 기본사양 신청하기

 - FTP 아이디 변경 나중에 힘들 수 있음

 

- 이메일 인증까지 하면 호스팅 세팅 완료

 

10. 판다스 결측 데이터 처리하기

# pandas는 누락된 데이터를 표시할 때 NaN(Not a Number)으로 표기하며, 연산에는 포함되지 않음
import pandas as pd
df = pd.read_csv('./input/weather.csv')
print(df.head())
#          date  temp  max_wind  mean_wind
# 0  2010-08-01  28.7       8.3        3.4
# 1  2010-08-02  25.2       8.7        3.8
# 2  2010-08-03  22.1       6.3        2.9
# 3  2010-08-04  25.3       6.6        4.2
# 4  2010-08-05  27.2       9.1        5.6

df.info()
# <class 'pandas.core.frame.DataFrame'>
# RangeIndex: 3653 entries, 0 to 3652
# Data columns (total 4 columns):
#  #   Column     Non-Null Count  Dtype
# ---  ------     --------------  -----
#  0   date       3653 non-null   object
#  1   temp       3653 non-null   float64
#  2   max_wind   3649 non-null   float64
#  3   mean_wind  3647 non-null   float64
# dtypes: float64(3), object(1)
# memory usage: 114.3+ KB


#isnull은 결측 데이터라면 True 반환. 유효한 데이터가 존재한다면 False반환
# ina(), isnumm()은 기능적으로 동일

# 결측 에이터

# 2) 결측 데이터 삭제하기
# 결측 데이터를 다루는 가장 간단한 방법은 결측 데이터를 가진 해잉나 열을 삭제
# DataFrame.dropna(axis, how, thresh, subset, inplace)
# axis : 축을 행 또는 열로 결정
# 0 또는 'index'이면 누락된 값이 포함된 행을 삭제
# 1 또는 'columns'이면 누락된 값이 포함된 열을 삭제
# 기본적으로 값은 0
# how : any는 null 값이 있는 경우 행 또는 열을 삭제
# all은 모든 값이 누락된 경우 행 또는 열을 삭제
# 기본값은 any
# inplace : 데이터프레임에 나온 값을 저장할 것인지를 설정하는 변수로 기본적으로 값은 False

# 결측 데이터가 있는 행 삭제 후 확인
df2 = df.dropna() # 옵션을 지정하지 않아서 행기준, NoN가 하나라도 있은 경우에 삭제
print(df2.isnull().sum())
# temp         0
# max_wind     0
# mean_wind    0
# dtype: int64

# 행 데이터 중 어느 한 변수에도 결측치가 있는 경우 삭제되므로
# 향후 제거한 데이터프레임을 사용하려면 다른 이름으로 저장해야 함
print(df.isnull().sum())
# temp         0
# max_wind     4
# mean_wind    6
# dtype: int64

# 3) 결측 데이터 대체하기
# 결측 데이터 대체하기 : 평균값으로 대체

df['max_wind'].fillna(df['max_wind'].mean(), inplace=True)
df['mean_wind'].fillna(df['mean_wind'].mean(), inplace=True)
# fillna() 같은 데이터를 특정 값으로 채움. inplace를 True로 설정해 원본 데이터를 수정

# 결측 데이터 대체 후 확인
print(df.isna().sum())
# temp         0
# max_wind     0
# mean_wind    0
# dtype: int64

 

11. 판다스 데이터 가공하기

 - EXCEL 파일을 읽기 위해 'openpyxl' 라이브러리 추가 설치 ( 세팅 > py 인터프리터 > + )

# 엑셀 파일 dust1.xlxs 파일을 불러와서 데이터프레임을 생성
import datetime

import pandas as pd

dust = pd.read_excel('./input/dust1.xlsx')
print(dust.head())
#        지역     망   측정소코드 측정소명  ...    NO2  PM10  PM25                주소
# 0  서울 송파구  도시대기  111273  송파구  ...  0.066    50    18  서울 송파구 백제고분로 236
# 1  서울 송파구  도시대기  111273  송파구  ...  0.058    48    20  서울 송파구 백제고분로 236
# 2  서울 송파구  도시대기  111273  송파구  ...  0.055    44    20  서울 송파구 백제고분로 236
# 3  서울 송파구  도시대기  111273  송파구  ...  0.055    40    20  서울 송파구 백제고분로 236
# 4  서울 송파구  도시대기  111273  송파구  ...  0.053    38    17  서울 송파구 백제고분로 236
#
# [5 rows x 12 columns]

# 1) 컬럼(변수) 삭제/생성하기
# 데이터 분석에 필요없는 '지역', '망', '측정소코드' 컬럼을 삭제하고 특정값으로 새로운 컬럼을 생성

dust = dust.drop(['지역', '망', '측정소코드'], axis=1)
# axis의 기본값이 axis=0으로 행 삭제가 됨. 컬럼을 삭제하기 위해서는 axis=1을 반드시 사용
print(dust.head())
#   측정소명        측정일시    SO2   CO     O3    NO2  PM10  PM25                주소
# 0  송파구  2021040101  0.004  1.0  0.002  0.066    50    18  서울 송파구 백제고분로 236
# 1  송파구  2021040102  0.004  0.8  0.002  0.058    48    20  서울 송파구 백제고분로 236
# 2  송파구  2021040103  0.004  0.8  0.002  0.055    44    20  서울 송파구 백제고분로 236
# 3  송파구  2021040104  0.003  0.8  0.002  0.055    40    20  서울 송파구 백제고분로 236
# 4  송파구  2021040105  0.004  0.8  0.002  0.053    38    17  서울 송파구 백제고분로 236

# 새로운 칼럼 생성
dust['city'] = '서울'
print(dust.head())
#   측정소명        측정일시    SO2   CO     O3    NO2  PM10  PM25                주소 city
# 0  송파구  2021040101  0.004  1.0  0.002  0.066    50    18  서울 송파구 백제고분로 236   서울
# 1  송파구  2021040102  0.004  0.8  0.002  0.058    48    20  서울 송파구 백제고분로 236   서울
# 2  송파구  2021040103  0.004  0.8  0.002  0.055    44    20  서울 송파구 백제고분로 236   서울
# 3  송파구  2021040104  0.003  0.8  0.002  0.055    40    20  서울 송파구 백제고분로 236   서울
# 4  송파구  2021040105  0.004  0.8  0.002  0.053    38    17  서울 송파구 백제고분로 236   서울

# 2) 컬럼 이름 변경
# 컬럼 이름 변경 방법
# 1) DataFrame.columns=['새이름1', '새이름2', ...]
# 전체 변수 이름을 재설정
# 변수명을 차례대로 재설정. 변수가 많은 경우 적절하지 않음.
# 2) DataFrame.rename(columns={'기존이름':'새이름'}, inplace=True)
# 원하는 변수이름만 수정
# 딕셔너리 구조로 정의. 즉 이전 열이름을 키로 지정하고 새 이름으로 값으로 지정

dust.rename(columns={'측정소명':'name','측정일시':'date','주소':'addr'}, inplace=True)
print(dust.columns)
# Index(['name', 'date', 'SO2', 'CO', 'O3', 'NO2', 'PM10', 'PM25', 'addr',
#        'city'],
#       dtype='object')


# 3) 데이터 형변환
print(dust.dtypes)
# name     object
# date      int64
# SO2     float64
# CO      float64
# O3      float64
# NO2     float64
# PM10      int64
# PM25      int64
# addr     object
# city     object
# dtype: object

# date 칼럼이 숫자형(int)로 저장되어 있음
# 숫자 형식은 문자 형식으로 변환
# astype(str)으로 문자열 형식으로 변환하고 데이터 길이를 날짜 형식 8자리에 적합하도록 str.slice()를 사용하여 첫 8자리만 저장
# (문자열 데이터를 숫자 형식으로 바꾸는 경우는 .astype(int) 사용.)

# 숫자 int형을 문자열로 변환
dust['date'] = dust['date'].astype(str)
dust['date'] = dust['date'].str.slice(0, 8)
print(dust.head())
#   name      date    SO2   CO     O3    NO2  PM10  PM25              addr city
# 0  송파구  20210401  0.004  1.0  0.002  0.066    50    18  서울 송파구 백제고분로 236   서울
# 1  송파구  20210401  0.004  0.8  0.002  0.058    48    20  서울 송파구 백제고분로 236   서울
# 2  송파구  20210401  0.004  0.8  0.002  0.055    44    20  서울 송파구 백제고분로 236   서울
# 3  송파구  20210401  0.003  0.8  0.002  0.055    40    20  서울 송파구 백제고분로 236   서울
# 4  송파구  20210401  0.004  0.8  0.002  0.053    38    17  서울 송파구 백제고분로 236   서울

print(dust.dtypes)
# name     object
# date     object
# SO2     float64
# CO      float64
# O3      float64
# NO2     float64
# PM10      int64
# PM25      int64
# addr     object
# city     object
# dtype: object

# 날짜 형식 활용 : Series.dt.형식

# dust['year'] = dust['date'].dt.year
# dust['month'] = dust['date'].dt.year
# dust['day'] = dust['date'].dt.day
# print(dust.head())


# 4) 데이터 병합하기
# merge() 함수는 두 데이터프레임을 각 데이터에 존재하는 고유값(key)을 기준으로 병합할 때 사용

# pd.merge(df_left, df_right, how='inner', on=None)
# 아무 옵션을 적용하지 않으면, on=None이므로 두 데이터의 공동 열이름(id)을 기준으로 inner(교집합) 조인을 하게 됨
# outer 옵션을 줘서 id를 기준으로 합치되, 어느 한쪽이라는 없는 데이터가 있는 경우 Nan 값이 지정

# 병합할 원본 데이터 확인하기
s1 = pd.read_excel('./input/nation.xlsx')
print(s1.head())
#   국적코드  성별    입국객수    증가수
# 0  A01  남성  125000   8000
# 1  A01  여성  130000  10000
# 2  A05  남성     300     10
# 3  A05  여성     200     50
# 4  A06  남성  158912  24486

s2 = pd.read_excel('./input/code.xlsx')
print(s2.head())
#   국적코드  국적명
# 0  A01  필리핀
# 1  A02   일본
# 2  A03   미국
# 3  A04   중국
# 4  A05   호주

# 데이터 병합하기 : 공통 컬럼을 기준
print(pd.merge(s1, s2, on='국적코드'))
#   국적코드  성별    입국객수    증가수  국적명
# 0  A01  남성  125000   8000  필리핀
# 1  A01  여성  130000  10000  필리핀
# 2  A05  남성     300     10   호주
# 3  A05  여성     200     50   호주
# 4  A06  남성  158912  24486  베트남
# 5  A06  여성  325000  63466  베트남

공부 과정을 정리한 것이라 내용이 부족할 수 있습니다.

부족한 내용은 추가 자료들로 보충해주시면 좋을 것 같습니다.

읽어주셔서 감사합니다 :)