파이썬

판다스를 활용한 데이터 전처리

초롱씨 2023. 11. 28. 17:29
728x90
반응형

머신러닝= 판다스, 넘파이
2차원 데이터 = 엑셀 판다스
수치  = 넘파이

자바는 jdk에 종속되어있다.
파이썬이 데이터 분석에서 널리 사용되는 이유는 다양하다. 

다양한 라이브러리와 패키지: 파이썬은 데이터 과학 및 머신 러닝에 관한 다양한 라이브러리와 패키지를 제공.

NumPy, Pandas, Matplotlib, Seaborn, Scikit-learn 등 라이브러리들은 데이터 처리, 시각화, 통계 분석, 머신 러닝 등 다양한 작업을 지원하며, 데이터 분석 작업을 효과적으로 수행할 수 있도록 도와준다.

커뮤니티와 생태계: 파이썬은 활발한 개발자 커뮤니티와 풍부한 생태계를 가지고 있다.

간결하고 가독성이 높은 문법

대화형 프로그래밍: 파이썬은 대화형 프로그래밍을 지원하여 코드를 한 줄씩 실행하고 결과를 바로 확인할 수 있다.

데이터 탐색과 실험적인 분석을 용이하다.

크로스 플랫폼 지원: 파이썬은 여러 플랫폼에서 동작하며, Windows, macOS, Linux 등에서 일관되게 사용할 수 있다.

다양한 환경에서의 일관된 데이터 분석 및 개발 가능

머신 러닝 및 딥 러닝 지원: 파이썬은 머신 러닝 및 딥 러닝 프레임워크와 라이브러리를 풍부하게 지원해서

TensorFlow, PyTorch, scikit-learn 등을 통해 머신 러닝 모델을 쉽게 개발하고 적용할 수 있다.

데이터 과학 및 분석 분야에서 널리 사용되며, 산업 및 학계에서도 표준 언어로 자리하고 있다.

+ csv는 순수 텍스트 파일이라 대용량을 넣을때 좋다.

판다스(pandas)
- 행렬 데이터를 처리하기 위한 다양한 함수를 지원하는 라이브러리
- 파일 열기 , 저장 행렬데이터 처리, 기본시각화 등 지원
- 데이터 전처리 과정에서 주로 사용

<데이터 분석 과정>
데이터 수집 > 데이터 전처리> 데이터 가공(필요시 전처리)>
데이터 분석 탐색/시각화(필요시 전처리) > 필요시 모델 훈련(머신러닝 or 딥러닝)> 웹서비스 또는 분석 보고서

*일반적으로 책에서는 : 데이터수집> 전처리> 분석 >시각화 로 설명되고 있음
*분석과정은 회사에 따라 다름
데이터 수집시 확인 사항
날짜 확인: 기준일로 사용
범주형 데이터 확인 : 예로 남자 또는 여자 와 같은 데이터

 

import pandas as pd

 

### 파일 데이터 추출하기
# 첫번째 변수: 파일위치
# 두번째 : 컬럼명으로 사용할 행의 위치(디폴트0)
# 세번째 : 행의 가장 밑에서 포함하지 않을 행의 갯수
# 네번째 가지고 올 열의 범위(A부터 C 까지의 열)
sample_1 = pd.read_excel(file_path,
                         header=1,
                         skipfooter=2,
                         usecols="A:C")

 

print(sample_1)

국적코드    성별  입국객수
0   A01 남성  106320
1   A01 여성  191436
2   A31 남성  319
3   A31 여성  42
4   A18 남성  158912
5   A18 여성  232943

 

#### 데이터프레임 정보 확인하기
# DataFrame타입 : 행렬을 저장 관리하는 타입
# - 중요 info () 함수는 데이터의 결측치(non,null) 데이터 확인가능
# - RangeIndex : 전체 행의(raw)의 갯수
# - 전체 행의 갯수와 각 칼럼의 갯수(non null)가 안맞으면 -> 결측 데이터가 존재한다는 의미
# 눈에 보이는 거 인덱스 값
# 실제 번호 : 인덱스 번호
# non_null => not null
# Dtype : object-> 문자, int-> 숫자
sample_1.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   국적코드    6 non-null      object 
 1   성별      6 non-null      object 
 2   입국객수    5 non-null      float64
dtypes: float64(1), object(2)
memory usage: 276.0+ bytes
# 데이터프레임 출력
# - - 데이터 행/열이 많은 경우 -> 기본 상위 5개 , 하위 5개를 추출해서 보여줌
# - 데이터 행/열의 개수가 작으면 모두 보여줌
sample_1.info(2)
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 6 entries, 0 to 5
Data columns (total 3 columns):
 #   Column  Non-Null Count  Dtype  
---  ------  --------------  -----  
 0   국적코드    6 non-null      object 
 1   성별      6 non-null      object 
 2   입국객수    5 non-null      float64
dtypes: float64(1), object(2)
memory usage: 276.0+ bytes

 

# - head() : 상위 데이터 조회할때
sample_1.head(1)
sample_1.head() # 상위 5개

 

 

국적코드    성별  입국객수
0   A01 남성  106320
1   A01 여성  191436
2   A31 남성  319
3   A31 여성  42
4   A18 남성  158912
5   A18 여성  232943
 
# tail(): 마지막에서 데이터확인 . 기본 5개 
sample_1.tail(1)
      국적코드    성별  입국객수
5            A18     여성  232943.0
# 기초통계 데이터
# count : 행의 갯수
# meat : 데이터 평균
# std: 표준편차
# min : 최솟값
# max: 최대값
# 25% 50% 75% : 4분위수 데이터
#-> 4분위 데이터를 이용해서 이상치 데이터 확인합니다.
sample_1.describe()

 

                   성별  입국객수
count   6.000000    6.000000
mean    0.500000    114995.333333
std 0.547723    98105.752006
min 0.000000    42.000000
25% 0.000000    26819.250000
50% 0.500000    132616.000000
75% 1.000000    183305.000000
max 1.000000    232943.000000

 

### 국적코드 데이터 조회하기
sample_1["국적코드"]
0    A01
1    A01
2    A31
3    A31
4    A18
5    A18
Name: 국적코드, dtype: object

 

### 타입 확인하기 
# Series : 튜플과 모양이 () 같습니다. 사용법도 동일합니다.
# {"국적코드" : (데이터 ,데이터 ,,,)}
type(sample_1["국적코드"])
pandas.core.series.Series

 

sample_1[["성별"]]
   성별
0   1
1   0
2   1
3   0
4   1
5   0

 

type(sample_1[["성별"]])
pandas.core.frame.DataFrame

 

 

 

sample_1[["국적코드","성별","입국객수"]]
     국적코드  성별  입국객수
0   A01 1   106320
1   A01 0   191436
2   A31 1   319
3   A31 0   42
4   A18 1   158912
5   A18 0   232943

 

 

기준년월 컬럼 추가하기

### 2019-11 값을 추가하기
sample_1["기준년월"]='2019-11'
sample_1
국적코드    성별  입국객수    기준년월
0   A01 1   106320  2019-11
1   A01 0   191436  2019-11
2   A31 1   319 2019-11
3   A31 0   42  2019-11
4   A18 1   158912  2019-11
5   A18 0   232943  2019-11

 

# 데이터 필터링 하기
### 성별 중에 여성인 데이터만 추출하기

condition= sample_1["성별"] == 0
condition

 

0    False
1     True
2    False
3     True
4    False
5     True
Name: 성별, dtype: bool

 

## 해당하는 값만 조회
sample_1[condition==False]

 

국적코드    성별  입국객수    기준년월
0   A01 1   106320  2019-11
2   A31 1   319 2019-11
4   A18 1   158912  2019-11

 

sample_1[sample_1["성별"]==0]

 

국적코드    성별  입국객수    기준년월
1   A01 0   191436  2019-11
3   A31 0   42  2019-11
5   A18 0   232943  2019-11
### 객체 주소 전달 방식
# 객체2의 값이 바뀌면 객체1의 값도 바뀜
sample_2 =sample_1
### copy() : 메모리 복제 방식(신규로 동일하게 생성된다.)
# 신규로 만들어진 메모리 주소를 받아옴(서로 영향 안받음)
sample_2 = sample_1.copy()
sample_2
국적코드    성별  입국객수    기준년월
0   A01 1   106320  2019-11
1   A01 0   191436  2019-11
2   A31 1   319 2019-11
3   A31 0   42  2019-11
4   A18 1   158912  2019-11
5   A18 0   232943  2019-11

 

 

외부 자료를 가져와 활용하기

"""
<한국 전력 거래소 시간별 전력 수요량 데이터 수집>
- 수집 위치 : data.go.kr

어떻게 관리하면 편하게 쓸 수 있을까
날짜 전력량 시간
"""

 

file_path = "./01_data/한국전력거래소_시간별 전력수요량_20211231.csv"
### 데이터 불러들이기
# 데이터 프레임 변수명 :df
# 판다스 라이브러리에서 기본적으로 인코딩 디코딩을 utf8을 쓰는데 
# 한국 행정부에서 저장해서 배포하는 데이터 타입은 euckr 한국전용
df = pd.read_csv(file_path, encoding="euc-kr" )
df

 

날짜  1시  2시  3시  4시  5시  6시  7시  8시  9시  ... 15161718192021222324
0   2021-01-01  64942   62593   60905   59889   59638   59936   60193   59982   59626   ... 56691   58299   60425   62931   64176   63645   62754   61561   61979   63055
1   2021-01-02  60658   58603   57309   56663   56733   57327   58378   59285   60669   ... 55493   57865   61407   64223   65082   64257   62981   61686   61962   64227
2   2021-01-03  61992   59723   58310   57599   57518   58073   58877   59373   59434   ... 59465   61355   63202   65426   66473   65646   64815   63289   63706   64480
3   2021-01-04  62078   60011   58936   58715   59233   61081   64908   71659   80766   ... 81315   81431   82840   81666   78838   75717   72867   69726   68460   70327
4   2021-01-05  67267   64957   63471   63136   63564   65045   68221   73685   81609   ... 81611   82647   84497   83721   81513   78460   75423   72053   70992   72838
... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ...
360 2021-12-27  66465   64473   63140   62540   63122   65025   69117   76487   86054   ... 88435   89654   90708   88653   85067   81527   78245   74696   73048   74217
361 2021-12-28  71059   68940   67701   67076   67184   68598   72033   78270   86809   ... 87226   87627   88077   85978   83052   80011   77035   73589   71856   72875
362 2021-12-29  69651   67276   65941   65136   65534   66910   70309   75972   84106   ... 82446   82500   83608   82009   79711   77646   75511   72342   70829   71882
363 2021-12-30  68581   66406   65155   64639   65121   66804   70225   75906   83494   ... 81928   83044   84564   82901   80604   78216   76176   73142   71610   72472
364 2021-12-31  69373   67187   65955   65431   65798   67226   70163   75036   81748   ... 73706   74401   75972   75798   74578   72976   71602   69383   68874   70123
365 rows × 25 columns

 

df.info()

<class 'pandas.core.frame.DataFrame'>
RangeIndex: 365 entries, 0 to 364
Data columns (total 25 columns):
 #   Column  Non-Null Count  Dtype
---  ------  --------------  -----
 0   날짜      365 non-null    object
 1   1시      365 non-null    int64
 2   2시      365 non-null    int64
 3   3시      365 non-null    int64
 4   4시      365 non-null    int64
 5   5시      365 non-null    int64
 6   6시      365 non-null    int64
 7   7시      365 non-null    int64
 8   8시      365 non-null    int64
 9   9시      365 non-null    int64
 10  10시     365 non-null    int64
 11  11시     365 non-null    int64
 12  12시     365 non-null    int64
 13  13시     365 non-null    int64
 14  14시     365 non-null    int64
 15  15시     365 non-null    int64
 16  16시     365 non-null    int64
 17  17시     365 non-null    int64
 18  18시     365 non-null    int64
 19  19시     365 non-null    int64
 20  20시     365 non-null    int64
 21  21시     365 non-null    int64
 22  22시     365 non-null    int64
 23  23시     365 non-null    int64
 24  24시     365 non-null    int64
dtypes: int64(24), object(1)
memory usage: 71.4+ KB

 

df.describe()

1시  2시  3시  4시  5시  6시  7시  8시  9시  10시 ... 15161718192021222324
count   365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  ... 365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  365.000000  365.000000
mean    59474.797260    57329.791781    56135.912329    55614.435616    55880.698630    56997.457534    59288.523288    62379.487671    66197.038356    66787.780822    ... 66633.569863    67687.975342    69304.767123    69692.643836    69767.673973    69215.060274    67728.030137    65563.463014    63563.591781    62972.369863
std 5076.825194 4947.050927 4831.958286 4760.624479 4779.037648 4923.920976 5534.842947 7134.965049 9606.642189 10473.001592    ... 10672.675088    10363.445426    10046.144681    9087.195015 7914.829493 7136.110062 6453.884842 5560.076020 4889.582544 5210.746677
min 47019.000000    45237.000000    44190.000000    43669.000000    43678.000000    44383.000000    45080.000000    45564.000000    44470.000000    43311.000000    ... 40254.000000    42320.000000    45879.000000    49395.000000    52477.000000    53075.000000    53255.000000    52494.000000    51044.000000    49540.000000
25% 56235.000000    54174.000000    53200.000000    52723.000000    52702.000000    53408.000000    55505.000000    57685.000000    59626.000000    60195.000000    ... 59350.000000    60527.000000    62533.000000    63946.000000    64834.000000    65062.000000    63946.000000    62353.000000    60829.000000    59816.000000
50% 58562.000000    56565.000000    55446.000000    54992.000000    55339.000000    56611.000000    58983.000000    62175.000000    66019.000000    66226.000000    ... 66616.000000    67663.000000    69016.000000    69252.000000    69488.000000    68551.000000    67037.000000    65034.000000    63058.000000    62179.000000
75% 63116.000000    60763.000000    59382.000000    58862.000000    59136.000000    60172.000000    62965.000000    67365.000000    73253.000000    75224.000000    ... 74602.000000    75553.000000    76725.000000    75737.000000    75068.000000    73747.000000    71616.000000    69024.000000    66954.000000    66782.000000
max 73086.000000    70960.000000    69867.000000    69143.000000    69141.000000    70433.000000    73185.000000    78406.000000    86809.000000    89506.000000    ... 89758.000000    89654.000000    90708.000000    91141.000000    90223.000000    88949.000000    86014.000000    81286.000000    75738.000000    75614.000000
8 rows × 24 columns

 

### 컬럼명의 시간을 데이터화 하기 위하여
# 컬럼명추출하기

col_list = df.columns
col_list
Index(['날짜', '1시', '2시', '3시', '4시', '5시', '6시', '7시', '8시', '9시', '10시',
       '11시', '12시', '13시', '14시', '15시', '16시', '17시', '18시', '19시', '20시',
       '21시', '22시', '23시', '24시'],
      dtype='object')

 

3개의 열(년도, 시간, 전력량)을 가지는 데이터 프레임 생성하기

result_df = pd.DataFrame(columns= ["년도", "시간", "전력량"])
result_df
년도  시간  전력량

 

result_df = pd.DataFrame(columns= ["년도", "시간", "전력량"])
### 데이터프레임 데이터 행단위 추가하기
for index, row , in df.iterrows():
    #년도 데이터
    ymd = row[col_list[0]]
    # 시간과 전력량 데이터을 각각 추출하여 데이터 프레임에 넣기
    # 넣을 값 : 날짜 , 시간 , 전력량
    data  = row[col_list[1:]]
    # print(data)

    for time , value in data.items():
        # print(ymd, "/", time, "/", value)
        ### 행단위로 데이터 프레임에 추가하기 위해서 임시로 데이터 프레임 생성
        df_temp = pd.DataFrame({"년도":[ymd],"시간":[time],"전력량":[value]})
        

        #### 데이터 프레임에 행단위로 추가하기
        # - concat() : 데이터프레임과 데이터프레임을 행단위 (axis=0)
        # 또는 칼럼단위 (axis=1)로 추가할 때 사용
        # - ignore_index = True : 행이 추가될때 행 인덱스 번호를 자동 증가 시키기 기본값 false
        result_df = pd.concat([result_df,df_temp], axis=0, ignore_index=True)   
### 최종 결과 출력하기        
result_df
년도  시간  전력량
0   2021-01-01  1시  64942
1   2021-01-01  2시  62593
2   2021-01-01  3시  60905
3   2021-01-01  4시  59889
4   2021-01-01  5시  59638
... ... ... ...
8755    2021-12-31  2072976
8756    2021-12-31  2171602
8757    2021-12-31  2269383
8758    2021-12-31  2368874
8759    2021-12-31  2470123
8760 rows × 3 columns

 

정제된 데이터 파일로 저장하기

### 저장할 경로 지정
save_path = "./01_data/new_data.csv"
## index= False : 인덱스 번호 값은 저장하지 않기 (기본값 Ture)
result_df.to_csv(save_path,index = False) ## 제일 첫번째 칼럼에 ,가 들어가서 인덱스를 없애준다.

 

file_path = "./01_data/new_data.csv"
df = pd.read_csv(file_path)
df

 

년도  시간  전력량
0   2021-01-01  1시  64942
1   2021-01-01  2시  62593
2   2021-01-01  3시  60905
3   2021-01-01  4시  59889
4   2021-01-01  5시  59638
... ... ... ...
8755    2021-12-31  2072976
8756    2021-12-31  2171602
8757    2021-12-31  2269383
8758    2021-12-31  2368874
8759    2021-12-31  2470123
8760 rows × 3 columns

 

 

"""
<테이블 설계하기>
- 테이블 명, 컬럼명, 컬럼타입, null 여부에 대한 정의가 필요함
(산출물)
 - 테이블 정의서
 -ERD 
 -스크립트 명세-> 

"""

 

 

<데이터 저장시에 유용한 라이브러리>
sqlalchemy
설치 pip install sqlalchemy
<데이터 조회시 유용한 라이브러리>
pymysql
설치 pip install pymysql
설치2 conda install -c conda-forge pymysql
from sqlalchemy import create_engine
import pymysql

DB 연결하기

# 연결정보 작성
db_connection_info= "mysql+pymysql://gjuser:dbdb@localhost:5000/gjdb"
# Database 연결하기
db_connection = create_engine(db_connection_info)
db_connection

 

데이터 프레임을 table에 저장시키기

 

### 데이터 프레임의 컬럼명을 테이블의 컬럼명과 같게 수정
## 데이터프레임의 컬럼명 전체 수정하기
df.columns = ["ymd", "time", "power"]
df
ymd time    power
0   2021-01-01  1시  64942
1   2021-01-01  2시  62593
2   2021-01-01  3시  60905
3   2021-01-01  4시  59889
4   2021-01-01  5시  59638
... ... ... ...
8755    2021-12-31  2072976
8756    2021-12-31  2171602
8757    2021-12-31  2269383
8758    2021-12-31  2368874
8759    2021-12-31  2470123
8760 rows × 3 columns

 

### 데이터 저장하기
# name : 테이블명
# con: db접속정보
# index: 데이터프레임의 인덱스값을 포함할지 여부 (True 포함 ,False 미포함)
# if_exists
# * append: 데이터를 기존 테이블에 추가
# * fail: 아무 동작하지 않기
# * replace : 동일한 테이블이 존재하면 기존 데이터를 삭제하고 새로운 데이터로 저
df.to_sql(name="time_power_demand",
        con=db_connection,
          index=False,
          if_exists="append")
8760

 

##연결 종료하기
db_connection.dispose()

 

데이터 조회하기

  • 조회시에는 pymysql 라이브러리 사용
  • <데이터베이스 연결>
### 접속정보
# 접속 id or 도메인
host = "localhost"
# 사용자 계정
user = "gjuser"
#패스워드
password = "dbdb"
#데이터베이스명g
db="gjdb"
#한글처리
charset = "utf8"
#조회시 컬럼명을 동시에 보여줄지 여부 설정
cursorclass = pymysql.cursors.DictCursor
# - 자동반영
autocommit = True
### DB 접속하기
try:
    conn = pymysql.connect(host=host,
                           user=user,
                           password=password,
                           db=db,
                           charset=charset,
                           cursorclass = cursorclass,
                           port=5000, autocommit=autocommit)
    print("DB 접속 성공 >>>", conn)
except:
    print("DB Server Checking...")
DB 접속 성공 >>> <pymysql.connections.Connection object at 0x0000027F0A03B110>
### 커서 받아오기
cur = conn.cursor()
cur
<pymysql.cursors.DictCursor at 0x27f08fdb650>

 

### select 문 생성 후 DB에게 요청 및 응답받기
sql  = "select * from time_power_demand"
rs_cnt = cur.execute(sql)
print(f"{rs_cnt}건이 조회되었습니다.")
8760건이 조회되었습니다.

 

try :
    cur.close()
    conn.close()
    print("커서와 접속정보가 반납되었습니다")
except:
    print("이미 모든 커서와 접속정보가 반납되었습니다")
이미 모든 커서와 접속정보가 반납되었습니다
728x90
반응형