728x90
반응형
데이터전처리
날짜데이터처리
주식데이터처리
BeautifulSoup
# -*- coding: utf-8 -*-
"""
Created on Thu Jun 30 09:32:18 2022
@author: p011v
"""
'''
데이터 전처리 : 원본데이터를 원하는 형태로 변경하는 과정.
1. 결측값 처리 : 값이 없는 경우.
- isnull() : 결측값인 경우 True, 일반값인 경우 False
- notnull() : 결측값인 경우 False, 일반값인 경우 True
- dropna() :
dropna(axis=1, thresh=500) :결측값이 500개 이상인 컬럼 제거
dropna(subset=["컬럼명"], how="any"/"all", axis=0, inplace=True) : 결측값을 가지고 있는 행 제거
- fillna : 결측값 치환
fillna(치환값, inplace=True)
fillna(방법,inplace=True) : method="ffill"/"bfill"
2. 중복데이터 처리
- duplicated() : 중복데이터 찾기. 첫번째 데이터는 False, 같은 데이터인 경우 두번째 True
- drop_duplicates() : 중복데이터를 제거. 중복된 데이터 중 한개는 남김.
3. 새로운 컬럼 생성
- df[컬럼명] : 컬럼명이 없는 경우 생성, 있으면 수정
- round(자릿수) : 반올림.
4. 오류데이터 존재
- 결측값 치환 : 결측값 (np.nan)
replace(오류문자열, np.nan, inplace=True)
'''
import pandas as pd
import numpy as np
df = pd.read_csv('data/auto-mpg.csv')
df.info()
df["horsepower"].unique()
# ? 인 값을 결측값으로 변환
df["horsepower"].replace("?", np.nan, inplace=True)
df["horsepower"][df["horsepower"].isnull()]
# 결측값이 있는 행을 삭제하기
df.dropna(subset=["horsepower"], how="any", axis=0, inplace=True)
df.info()
# horsepower 컬럼의 자료형을 실수형으로 변환
#astype("자료형"): 요소들의 자료형을 변환 함수
df["horsepower"] = df["horsepower"].astype("float")
df.info()
df['horsepower'].describe()
#origin컬럼: 생산지역. 1:USA, 2:EU, 3:JAPAN
df['origin'].unique()
#정수형 컬럼을 문자열형 범주형 데이터로 변환.
#범주형: category형
#1. 정수형데이터를 문자열형으로 변환. 1=> USA, 2=> EU, 3=>JAPAN
df['origin'].replace({1:'USA', 2:'EU', 3:'JAPAN'}, inplace=True)
df['origin'].unique()
df.info()
#2. 문자열형을 범주형으로 변환
df['origin'] = df['origin'].astype('category')
df.info()
#3. 범주형을 문자열형으로 변환
df['origin'] = df['origin'].astype('str')
df.info()
# 범주형: 값의 범위를 가지고 있는 자료형. 데이터가 크기와 상관없이 값의 범위 의미 (예) 학년.. 1.2학년..이런거없음
# 정수형 category 자료형
age = pd.Series([26,42,27,25,20,20,21,22,23,25])
stu_class = pd.Categorical([1,1,2,2,2,3,3,4,4,4])
# 문자형 category 자료형
gender = pd.Categorical(['F','M','M','M','M','F','F','F','M','M'])
c_df = pd.DataFrame({'age':age, 'class': stu_class, 'gender': gender})
c_df.info()
c_df.describe()
# class 컬럼을 범주형 => 정수형
c_df['class'] = c_df['class'].astype('int64')
c_df.info()
c_df.describe()
# 날짜 데이터 처리
# freq='D' : 일자기준. 기본값 (생략가능)
# freq='MS' : 월의 시작일
# freq='M' : 월의 종료일
# freq='3M' :분기의 종료일
# dates = pd.date_range('20220101',periods=6, freq='D')
dates = pd.date_range('20220101', periods=6, freq='D')
dates
df = pd.DataFrame({'count1':[10,2,3,1,5,1],
'count2':[1,2,3,6,7,8]}, index=dates)
df
df.info()
dates = pd.date_range('20220110', periods=6, freq='MS')
dates
dates = pd.date_range('20220110', periods=6, freq='M')
dates
dates = pd.date_range('20220110', periods=6, freq='3M')
dates
dates = pd.date_range('20220110', periods=6, freq='6M')
dates
# 주식데이터 처리
df=pd.read_csv('data/stock-data.csv')
df.info()
df
# 문자열 형태의 date 컬럼을 datetime형으로 새컬럼 생성하기
df["new_Date"] = pd.to_datetime(df['Date'])
df.info()
# new_Date 컬럼에서 년,월,일 정보를 각각 컬럼으로 생성하기
df['Year'] = df['new_Date'].dt.year
df['Month'] = df['new_Date'].dt.month
df['Day'] = df['new_Date'].dt.day
df.info()
# 월별 평균값을 조회하기
df.groupby("Month").mean()[["Close", "Start", "Volume"]]
# datetime 형태의 new_Date컬럼을 문자열형으로 "연월일"컬럼 생성하기
df['연월일'] = df['new_Date'].astype("str")
df.info()
df["연월일", "Date"]
# 연월일 컬럼을 이용하여 년,월,일 문자열형 컬럼을 생성하기
dates = df["연월일"].str.split("-")
dates
df["연"] = dates.str.get(0)
df["월"] = dates.str.get(1)
df["일"] = dates.str.get(2)
df[["연월일", "연", "월", "일", "Month"]]
# 월별 평균값을 조회하기
df.groupby("월").mean()[["Close", "Start", "Volume"]]
# 필터 : 조건에 맞는 데이터 조회
import seaborn as sns
titanic = sns.load_dataset("titanic")
# 타이타닉 승객중 10대(10~19세)인 승객만 조회하기 df_teenage 데이터에 저장하기
df_teenage = titanic.loc[(titanic.age >= 10) & (titanic.age < 20)]
df_teenage["age"]
# 타이타닉 승객중 10세미만의 여성 승객만 조회하기 df_female_under10 데이터에 저장하기
df_female_under10 = titanic.loc[(titanic.sex == "female") & (titanic.age < 10)]
df_female_under10[["age", "sex"]]
titanic.sibsp.unique()
# 동행자(sibsp)의 수가 3, 4, 5인 승객들의 sibsp, alone 컬럼 조회하기.
# df_notalone 데이터에 저장하기
#1
df_notalone = titanic.loc[(titanic.sibsp == 3) | (titanic.sibsp == 4) | (titanic.sibsp == 5)]
df_notalone[["sibsp", "alone"]]
#2
#titanic.loc[행값처리필터, 컬럼값]
df_notalone = titanic.loc[(titanic.sibsp == 3) | (titanic.sibsp == 4) | (titanic.sibsp == 5)], [["sibsp", "alone"]]
df_notalone
#3
df_notalone = titanic.loc[titanic.sibsp.isin([3,4,5]),["sibsp", "alone"]]
df_notalone
# class 컬럼 중 First, Second인 행만 조회하기 df_class12 데이터에 저장
# titanic.class.unique() #class 예약어. 사용 불가
titanic["class"].unique()
titanic.alone.unique()
df_class12 = titanic.loc[titanic["class"].isin(["First", "Second"])]
df_class12["class"].value_counts()
# df : titanic 데이터에서 나이(age), 성별(sex), 클래스(class), 요금(fare),
# 생존여부(suvide) 컬럼만 가진 데이터 프레임 객체
df = titanic[["age", "sex", "class", "fare", "survived"]]
df.info()
# df 레코드 건수
len(df)
# class 컬럼으로 데이터 분할하기
# groupby(컬럼명) : 커럶의 값, 그룹화된 DataFrame
grouped = df.groupby("class")
grouped
# key : 분리된 컬럼값
# group : 분리된 DataFrame 객체
for key, group in grouped :
print("=== kry", key, end=",")
print("=== cnt", len(group), type(group))
df["class"].value_counts()
# 그룹별 평균
grouped.mean()
df.groupby("class").mean()
# 3등석 정보만 조회하기
group3 = grouped.get_group("Third")
group3.info()
group3.head()
# class, sex 컬럼으로 분할하기
grouped2 = df.groupby(["class", "sex"])
for key, group in grouped2 :
print("=== kry", key, end=",")
print("=== cnt", len(group), type(group))
# 3등석 여성 정보만 조회하기
group3f = grouped2.get_group(("Third", "female"))
group3f
group3f.info()
grouped2.std()
grouped2.mean()
# fare의 평균구하기
grouped2.fare.mean()
grouped2.fare.mean().index
grouped2.fare.mean().values
# 클래스별 가장 많은 나이와, 가장 적은 나이를 출력하기
grouped.age.max()
grouped.age.min()
df.groupby("class").age.max()
df.groupby("class").age.min()
# 클래스명 성별 나이가 가장 많은 나이와, 가장 적은 나이를 출력하기
grouped2.age.max()
grouped2.age.min()
df.groupby(["class", "sex"]).age.max()
df.groupby(["class", "sex"]).age.min()
# agg(함수이름) 함수 : 여러개의 함수를 여러개의 컬럼에 적용할 수 있는 함수.
# 사용자 정의함수 적용
def max_min(x) :
return x.max() - x.min()
# grouped 데이터에 max_min 함수 적용
agg_maxmin = grouped.agg(max_min)
agg_maxmin
#grouped 데이터에 max 조회
grouped.max() #max 함수 호출
grouped.agg(max) #agg 함수에서 max 함수 호출
#grouped 데이터에 최대, 최소값 조회
grouped.agg(['max','min'])
# 각 컬럼마다 다른 함수 적용할 수 있음.
# 요금(fare): 평균값, 최대값
# 나이(age): 평균값
grouped.agg({'fare':['mean','max'], 'age': 'mean'})
# fare age
# mean max mean
#class
#First 84.154687 512.3292 38.233441
#Second 20.662183 73.5000 29.877630
#Third 13.675550 69.5500 25.140620
#----------------------------------------------------------
# filter(조건) 함수: 그룹화된 데이터의 조건 설정.
# grouped 데이터의 갯수가 200개 이상인 그룹만 조회하기
grouped.count()
#Out[171]:
# age sex fare survived
#class
#First 186 216 216 216
#Second 173 184 184 184
#Third 355 491 491 491
#----------------------------------------------------------
filter1 = grouped.filter(lambda x : len(x) >= 200)
filter1.info()
filter1['class'].value_counts()
#Out[176]:
#Third 491
#First 216
#Second 0
#Name: class, dtype: int64
#----------------------------------------------------------
#age 컬럼의 평균이 30보다 작은 그룹만을 filter2에 저장하기
grouped.mean()
filter2 = grouped.filter(lambda x : x.age.mean() < 30)
filter2.groupby('class').mean()
filter2.info()
filter2['class'].value_counts()
#Out[193]:
#Third 491
#Second 184
#First 0
#Name: class, dtype: int64
#----------------------------------------------------------
# 두개의 DataFrame 연결하기
#stockprice.xlsx, stockvaluation.xlsx 데이터를 읽기
df1 = pd.read_excel('data/stockprice.xlsx')
df2 = pd.read_excel('data/stockvaluation.xlsx')
df1
df2
#df1
#Out[196]:
# id stock_name value price
#0 128940 한미약품 59385.666667 421000
#1 130960 CJ E&M 58540.666667 98900
#2 138250 엔에스쇼핑 14558.666667 13200
#3 139480 이마트 239230.833333 254500
#4 142280 녹십자엠에스 468.833333 10200
#5 145990 삼양사 82750.000000 82000
#6 185750 종근당 40293.666667 100500
#7 192400 쿠쿠홀딩스 179204.666667 177500
#8 199800 툴젠 -2514.333333 115400
#9 204210 모두투어리츠 3093.333333 3475
#df2
#Out[197]:
# id name eps bps per pbr
#0 130960 CJ E&M 6301.333333 54068 15.695091 1.829178
#1 136480 하림 274.166667 3551 11.489362 0.887074
#2 138040 메리츠금융지주 2122.333333 14894 6.313806 0.899691
#3 139480 이마트 18268.166667 295780 13.931338 0.860437
#4 145990 삼양사 5741.000000 108090 14.283226 0.758627
#5 161390 한국타이어 5648.500000 51341 7.453306 0.820007
#6 181710 NHN엔터테인먼트 2110.166667 78434 30.755864 0.827447
#7 185750 종근당 3990.333333 40684 25.185866 2.470259
#8 204210 모두투어리츠 85.166667 5335 40.802348 0.651359
#9 207940 삼성바이오로직스 4644.166667 60099 89.790059 6.938551
#concat() : df1, df2 데이터를 열 기준으로 연결하기. 물리적인 연결
result1 = pd.concat([df1,df2],axis=1)
result1
#result1
#Out[199]:
# id stock_name value ... bps per pbr
#0 128940 한미약품 59385.666667 ... 54068 15.695091 1.829178
#1 130960 CJ E&M 58540.666667 ... 3551 11.489362 0.887074
#2 138250 엔에스쇼핑 14558.666667 ... 14894 6.313806 0.899691
#3 139480 이마트 239230.833333 ... 295780 13.931338 0.860437
#4 142280 녹십자엠에스 468.833333 ... 108090 14.283226 0.758627
#5 145990 삼양사 82750.000000 ... 51341 7.453306 0.820007
#6 185750 종근당 40293.666667 ... 78434 30.755864 0.827447
#7 192400 쿠쿠홀딩스 179204.666667 ... 40684 25.185866 2.470259
#8 199800 툴젠 -2514.333333 ... 5335 40.802348 0.651359
#9 204210 모두투어리츠 3093.333333 ... 60099 89.790059 6.938551
result1.info()
#concat() : df1, df2 데이터를 행 기준으로 연결하기. 물리적인 연결
result1 = pd.concat([df1,df2],axis=0)
result1.info()
result1
# Out[205]:
# id stock_name value ... bps per pbr
# 0 128940 한미약품 59385.666667 ... NaN NaN NaN
# 1 130960 CJ E&M 58540.666667 ... NaN NaN NaN
# 2 138250 엔에스쇼핑 14558.666667 ... NaN NaN NaN
# 3 139480 이마트 239230.833333 ... NaN NaN NaN
# 4 142280 녹십자엠에스 468.833333 ... NaN NaN NaN
# 5 145990 삼양사 82750.000000 ... NaN NaN NaN
# 6 185750 종근당 40293.666667 ... NaN NaN NaN
# 7 192400 쿠쿠홀딩스 179204.666667 ... NaN NaN NaN
# 8 199800 툴젠 -2514.333333 ... NaN NaN NaN
# 9 204210 모두투어리츠 3093.333333 ... NaN NaN NaN
# 0 130960 NaN NaN ... 54068.0 15.695091 1.829178
# 1 136480 NaN NaN ... 3551.0 11.489362 0.887074
# 2 138040 NaN NaN ... 14894.0 6.313806 0.899691
# 3 139480 NaN NaN ... 295780.0 13.931338 0.860437
# 4 145990 NaN NaN ... 108090.0 14.283226 0.758627
# 5 161390 NaN NaN ... 51341.0 7.453306 0.820007
# 6 181710 NaN NaN ... 78434.0 30.755864 0.827447
# 7 185750 NaN NaN ... 40684.0 25.185866 2.470259
# 8 204210 NaN NaN ... 5335.0 40.802348 0.651359
# 9 207940 NaN NaN ... 60099.0 89.790059 6.938551
#merge(): id 컬럼을 기준으로 같은 id의 값을 가진 레코드를 병합.
# sql의 join 비슷함.
result2 = pd.merge(df1,df2)
result2
result2.info()
# result2
# Out[208]:
# id stock_name value ... bps per pbr
# 0 130960 CJ E&M 58540.666667 ... 54068 15.695091 1.829178
# 1 139480 이마트 239230.833333 ... 295780 13.931338 0.860437
# 2 145990 삼양사 82750.000000 ... 108090 14.283226 0.758627
# 3 185750 종근당 40293.666667 ... 40684 25.185866 2.470259
# 4 204210 모두투어리츠 3093.333333 ... 5335 40.802348 0.651359
# [5 rows x 9 columns]
#on='id': 연결컬럼, merge 컬럼. 두개의 데이터 프레임 병합시 id 컬럼의 값이 같은 경우 병합
result2 = pd.merge(df1, df2, on='id')
result2
result2.info()
# how="outer" : 병합되는 두개의 데이터의 연결 컬럼의 값이 같지 않아도 조회가능
# 값이 같지 않은 경우 상대컬럼의 값은 NaN 임
#내용이 같지 않은 df1, df2 데이터 조회.
#sql: full outer join
result3 = pd.merge(df1, df2, on="id", how="outer")
result3
result3 = pd.merge(df1, df2, on="id", how="left")
result3
result3 = pd.merge(df1, df2, on="id", how="right")
result3
# 다른 컬럼을 이용하여 병합하기
# left_on='stock_name' : 왼쪽 데이터프레임의 연결컬럼 설정
# right_on='name' : 오른쪽 데이터프레임의 연결컬럼 설정
# => df1.stock_name 컬럼과 df2.name 컬럼을 연결하여 병합
# => 연결컬럼이름이 다른 경우 병합
result4 = pd.merge(df1, df2, left_on='stock_name', right_on='name')
result4
result4.info()
# df1.stock_name 컬럼과 df2.name 컬럼을 연결하여 병합
# 내용이 다른 레코드도 조회하기
result5 = pd.merge(df1, df2, left_on='stock_name', right_on='name', how="outer")
result5
# df1.stock_name 컬럼과 df2.name 컬럼을 연결하여 병합
# 내용이 다른 레코드인 경우 df1에 있는 데이터만 값이 달라도 조회하기
result6 = pd.merge(df1, df2, left_on='stock_name', right_on='name', how="left")
result6
# df1.stock_name 컬럼과 df2.name 컬럼을 연결하여 병합
# 내용이 다른 레코드인 경우 df2에 있는 데이터만 값이 달라도 조회하기
result7 = pd.merge(df1, df2, left_on='stock_name', right_on='name', how="right")
result7
##################################################################
# BeautifulSoup: html, xml, 태그 분석 모듈
from bs4 import BeautifulSoup
import urllib.request as req # 인터넷을 통해서 요청을 할 수 있는 모듈. 인터넷 접속 기능 모듈
url = "https://www.weather.go.kr/weather/forecast/mid-term-rss3.jsp"
res=req.urlopen(url) # 인터넷을 통해 url에 연결.
print(res) # url을 통해서 연결된 응답데이터
# BeautifulSoup : html, xml 마크업언어 분석 객체
# soup : res의 태그를 분석하여 DOM의 root노드 저장
soup=BeautifulSoup(res, 'html.parser')
# title 태그 찾기. 내용을 title 변수 저장
title=soup.find('title').string
# wf 태그 찾기. 내용을 wf에 저장
wf=soup.find('wf').string
print(title)
print(wf)
'''
<!CDATA[○ (강수) 4일(월)은 충청권과 남부지방,
제주도에, 5일(화)~7일(목)은 전국에 비가 오겠고, 8일(금)은 중부지방과 전라권에 비가 오겠습니다
<!CDATA[ 내용 ]]> : 내용만 출력
<!CDATA[ ]]> : CDATA 섹션. 순수 문자열. XML 용어.
CDATA 섹션내에서 사용되는 태그들은 태그가 아니고 순수한 문자열
'''
728x90
반응형
'study > Python' 카테고리의 다른 글
[Python] 41. Test 답 (0) | 2022.06.30 |
---|---|
[Python] 41. Test (0) | 2022.06.30 |
[Python] 40. Test 답 (0) | 2022.06.29 |
[Python] 40. Test (0) | 2022.06.29 |
[Python] 40. age.csv 파일을 읽어서 인구구조를 알고 싶은 동을 찾아서 인구구조 그래프를 작성하기, 데이터 전처리 : 원본데이터를 원하는 형태로 변경하는 과정, 중복데이터 처리 (0) | 2022.06.29 |