Day1
와인 데이터 분석 실습
데이터 로드
: import pandas as pd
: df=pd.read_csv('winequality.csv')
기본 정보 확인
: df.info()와 df.describe() 이용
질문거리 생각
: 레드 와인과 화이트 와인의 개수
- df_redwine=df[df['type']=='red']
- df_whitewine=df[df['type']=='white']
: 두 와인의 평균 등급
- df_redwine['quality'].mean()
- df_whitewine['quality'].mean()
: 와인의 최상위 등급이 9등급이라는 가정 하의 와인 정렬
- df['quality'].unique() : 3등급~9등급의; 와인 존재 확인
- df['quality'].value_counts() : 등급 별 와인 개수 확인
- df[df['quality']==9]
- df[df['quality']==3] : 당도나 알콜의 차이 확인
: 가게에서 등급이 가장 높거나 낮은 와인 각각 10개씩 추출
- df[['type', 'residual sugar', 'quality']].sort_values(by=['quality'], ascending=False).head(10)
- df[['type', 'residual sugar', 'quality']].sort_values(by=['quality'], ascending=False).tail(10)
질문거리 생각2
: 당도와 등급의 상관관계
- df_whitewine['residual sugar'].corr(df_whitewine['quality'])
: ph가 가장 높은 와인
- df.sort_values('pH', ascending=False).head(1)
- df.loc[df['pH'].idxmax()].to_frame()
: 'alcohol'이 7 이상인 행들의 'sulphates' 평균값
- df[df['alcohol']>=7]['sulphates'].mean()
- df.loc[df['alcohol']>=7, 'sulphates'].mean()
: 와인의 타입별 등급의 평균값
- df.groupby('type')['quality'].mean()
NBA 데이터 분석 실습
실습 문제
: 현재 각 팀별 선수는 몇 명씩 있나요?
- df.value_counts('Team')
- team_gb=df.groupby('Team')
team_gb.size().sort_values(ascending=False)
* 팀별 연봉 평균
- team_gb.mean(numeric_only=True).sort_values(by='Salary', ascending=False)
: 포지션별 평균 연봉은 어떻게 되나요?
- df.groupby('Position')['Salary'].mean()
- posi=list(df['Position'].unique())
for position in posi:
print(f'position: {position}')
print(df[df['Position']==position]['Salary'].mean())
: 팀별 평균 연봉은 어떻게 되나요?
- df.groupby('Team')['Salary'].mean()
: 학교별로 출신 선수가 몇 명 인지를 보고자 하면 어떻게 하면 될까요?
- df.groupby('College')['Name'].size()
- df['College'].value_counts()
: 가장 많은 연봉을 받는 선수를 배출한 학교 top 10
- df.sort_values('Salary', ascending=False)['College'].head(10)
: 평균 키가 가장 큰 팀은?
- def height_to_cm(height):
feet=int(height.split('-')[0])
inch=int(height.split('-')[1])
cm=feet*30.48+inch*2.54
return cm
- df=df.dropna(how='any')
- df['Height_cm']=df['Height'].apply(height_to_cm)
- df.groupby('Team')['Height_cm'].mean()
타이타닉 데이터 분석
실습 문제
: 등급별 생존자 수
- df[df['Survived']==1].groupby('Pclass').size().to_frame()
: Embarked에 따른 고객의 Pclass
- df.groupby(['Embarked', 'Pclass']).size()
- df.groupby('Embarked')['Pclass'].value_counts()
: SibSp + Parch+1 = FamilyNum
FamilyNum 컬럼 추가, SibSp, Parch 컬럼 제거
FamilyNum에 따른 생존 확률
- df['FamilyNum']=df['SibSp']+df['Parch']
- df.drop(['SibSp','Parch'], axis=1)
- df.groupby('FamilyNum')['Survived'].value_counts()
: 60세 이상 고령자의 생존 확률
- df_senior=df[df['Age']>=60][['Name', 'Sex', 'Age', 'Survived']]
- df_senior['Survived'].value_counts()
: 요금을 가장 많이 낸 상위 10명의 생존확률
- df.sort_values(by='Fare', ascending=False)[['Fare','Survived']].head(10)
NaN 전처리 및 데이터 시각화
: 나이 데이터 전처리
- df['Age']=df['Age'].fillna(df['Age'].mean())
: 캐빈 데이터 전처리
- df['Cabin'].fillna(value='C001')
: 엠바크 데이터 전처리
- df['Embarked']=df['Embarked'].fillna('S')
: 성별을 0,1로 변경
- df['Sex']=df['Sex'].replace({
'male':0,
'female':1 })
시각화를 돕는 Matplotlib, Seaborn, Plotly
시각화가 필요한 이유
: 많은 양의 데이터를 한 눈에 볼 수 있음
: 인사이트를 뽑아낼 수 있음
: 숫자로만 볼 때는 보이지 않던 것들이 시각화를 통해 드러나는 경우가 많다
: 타인 설득의 도구가 된다
: 데이터 기반 의사 결정에 도움이 된다
Matplotlib 실습
: 방대한 양의 데이터를 시각화할 때 사용
: 선 그래프
- x=np.arange(0, 10, 1)
y=np.sin(x)
y2=np.cos(x)
- plt.figure(figsize=(30,10), facecolor='skyblue', dpi=300)
plt.plot(x,y, label='sin',marker='o',markersize=2.5, color='pink') : 공학용 시각화 -> seaborn
plt.plot(x,y2, label='cos',marker='x',markersize=2.5, color='turquoise')
plt.title('Sin Graph')
plt.xlabel('Time')
plt.ylabel('Amplitude')
plt.grid() : 격자 표시
plt.legend() : 범례 추가
*범례 위치를 바꾸고 싶을 때는 안에 loc=(-1~1,-1~1)을 넣음
plt.xlim(0,np.pi) : x의 범위 조절
plt.ylim(-1.2,1.2)
: 산점도
- df_large=df[df['Label']=='Large']
df_medium=df[df['Label']=='Medium']
df_small=df[df['Label']=='Small']
- plt.scatter(df_large['x'], df_large['y'], label='large')
plt.scatter(df_medium['x'], df_medium['y'], label='medium')
plt.scatter(df_small['x'], df_small['y'], label='small')
plt.legend()
: 막대 그래프
- values=[100,130,150]
labels=['kor','china','usa']
colors=['pink', 'red', 'brown']
plt.ylim(90,160)
- plt.bar(labels, values, color=colors, alpha=0.5)
*alpha : 색깔 투명도 조정
Metaplotlib 실습 2
: 기본 세팅
- import matplotlib.pyplot as plt
import numpy as np
plt.rc('font', family='NanumGothic')
: 영화 데이터를 활용하여 x축은 영화, y축은 평점인 막대 그래프
- plt.bar(df['영화'],df['평점'])
plt.figure(figsize=(40,15))
plt.show()
: 앞에서 만든 막대 그래프에 제시된 세부 사항을 적용하시오.
제목: 국내 Top 8 영화 평점 정보
x축 label: 영화 (90도 회전)
y축 label: 평점
- plt.title('국내 Top 8 영화 평점 정보')
plt.xlabel('영화', rotation=90)
plt.ylabel('평점')
plt.bar(df['영화'],df['평점'])
plt.show()
: 3. 개봉 연도별 평균 평점 변화 추이를 꺾은선 그래프(plot)로 그리시오.
x: 개봉 연도, y: 평점
marker: 'o'
x축 눈금: 5년 단위 (2005, 2010, 2015, 2020)
y축 범위: 최소 7, 최대 10
- df_year=df.groupby('개봉 연도').mean()
x=df_year.index
y=df_year['평점']
plt.plot(x,y,marker='o',color='pink')
Seaborn 실습
: 기본 세팅 및 데이터셋 로드
- !pip install seaborn
- import seaborn as sns
df=sns.load_dataset("penguins")
sns.pairplot(df,hue="species") : 다양한 시각화 한 번에 보기
: 요일과 시간 별 알바가 받는 팁 시각화
- sns.boxplot(x=df['day'], y=df['tip'])
- sns.boxplot(x=df['time'], y=df['tip'])
- sns.boxplot(x=df['day'], y=df['tip'], hue=df['time'])
* hue: 일종의 범례
- sns.swarmplot(data=df, x='day',y='tip') : 요일별 빈도
* 박스플롯과 함께 표시 가능
: 성별 별 팁 시각화
- sns.boxplot(data=df, x='sex',y='tip')
Seaborn 실습 2
: 가설 - 전체금액이 높을수록 팁도 많이 줄까?
: 회귀분석
- 독립변인(x)이 종속변인(y)에 미치는 영향도를 파악하고자 할 때 실시하는 분석 방법
- 상관관계인지 여부
- 예) 양의 상관관계 - 전체 계산금액이 클수록 팁도 많다
음의 상관관계 - 전체 계산금액이 클수록 팁은 적어진다
: 산점도 실습
- sns.lmplot(data=df,x='total_bill',y='tip')
- 절편 방정식
x=df['total_bill']
y=df['tip']
m, b = np.polyfit(x,y,1)
m , b
plt.scatter(x,y)
plt.plot(x, m*x+b, color='red', label=f'회귀선 y={m:2f}x+{b:2f}')
: 히트맵 실습
- 피벗 테이블 활용
- 기본 형식 : df.pivot(index, column, values)
- df_pivot=df.pivot(index='month', columns='year', values='passengers')
df_pivot
- 시간 데이터를 히트맵으로 나타낸 것이 시계열 데이터
- sns.heatmap(df_pivot, annot=True, fmt="d")
파이썬 미니 프로젝트 소개
미니 프로젝트 주제
: 이커머스 데이터
- 데이터 : Instacart Market Basket Analysis | Kaggle
- RFM을 통한 고객 세분화
- 고객 충성도 분석
- 연관 상품 분석 추천 시스템 구축
: 금융 데이터
- 데이터 : German Credit Risk | Kaggle
- 신용도에 영향을 미치는 주요 변수 식별 및 인사이트 도출
: K-Drama 선호도 데이터를 이용한 EDA
- 데이터 : 문화 빅데이터 - 포털- 전체 상품 (bigdata-culture.kr)
: 17년간의 멜론 Top100 리스트 수집을 통한 추이 분석
- 데이터 : 멜론차트>차트상세찾기>멜론 (melon.com)
- 직접 크롤링 필요
: 비만율에 영향을 주는 건강한 식습관을 위한 영양조사 데이터 분석
- 데이터 :
- 질병관리청_국민건강통계_20211231 | 공공데이터포털 (data.go.kr)
- 원시자료 다운로드 | 질병관리본부 국민건강영양조사 (kdca.go.kr)
- 서울시 비만율 통계> 데이터셋> 공공데이터 | 서울열린데이터광장 (seoul.go.kr)
- KOSIS 국가통계포털
: 자유 주제
Day2
Ch03.파이썬 데이터 분석 프로젝트 - 실습7. 직접 크롤링하기 - 부동산 뉴스기사 키워드 추출을 통한 연도별 이슈 분석
크롤링하기&질문 만들기
: 한글 폰트 다운
- !sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf
: 크롤링 후 유저 에이전트 생성 라이브러리 다운
- !pip install user_agent
: 한글 형태소 분석기 다운로드
- !pip install konlpy
!pip install mecab-python
!bash <(curl -s https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh)
: 데이터 수집
: 질문 만들기
- 연도별로 부동산 전망에 대한 뉴스 키워드는 어떻게 변화했는가?
- 워드클라우드로 시각화
: 데이터 전처리
: 분석
데이터 수집
: 2018년부터 2023년 8월까지 '부동산' 키워드 뉴스 기사 크롤링
- from user_agent import generate_user_agent, generate_navigator
user_agent = generate_user_agent()
user_agent #기계적 크롤링이 아니라 알리는 코드
- import requests
from bs4 import BeautifulSoup as bs
import pandas as pd
import random
import time
from tqdm.notebook import tqdm
: 날짜 세팅
- first_day = pd.date_range('2018-01-01', '2023-08-31', freq='MS').strftime('%Y.%m.%d')
last_day = pd.date_range('2018-01-01', '2023-08-31', freq='M').strftime('%Y.%m.%d')
date_list = list(zip(first_day, last_day))
- keyword = '부동산'
data = pd.DataFrame()
for dt in tqdm(date_list):
dt1 = [dt[0].replace('.',''), dt[1].replace('.','')]
for num in range(1, 101, 10):
url = f'https://search.naver.com/search.naver?where=news&query={keyword}&sm=tab_opt&sort=0&photo=0&field=0&pd=3&ds={dt[0]}&de={dt[1]}&docid=&related=0&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so%3Ar%2Cp%3Afrom{dt1[0]}to{dt1[1]}&is_sug_officeid=0&office_category=0&service_area=1&start={num}'
user_agent = generate_user_agent()
headers = {'User-Agent':user_agent}
res = requests.get(url, headers=headers)
time.sleep(random.random())
soup = bs(res.text, 'html.parser')
title = [i.text for i in soup.find_all('a', class_='news_tit')]
link = [i['href'] for i in soup.find_all('a', class_='news_tit')]
press = [i.text for i in soup.find_all('a', class_='info press')]
temp = pd.DataFrame({'title':title, 'link':link, 'press':press, 'date_ym':dt1[0][:6]})
if len(title) < 1 : #크롤링이 아무것도 되지 않았으면 루프를 종료, 시간 텀을 가진 뒤 다시 크롤링
break
data = pd.concat([data, temp])
데이터 전처리
: 필요없는 컬럼 제거 및 데이터 타입 변경
- data = data[['title','date_ym']]
data['date_ym'] = data['date_ym'].astype(str)
: 형태소 분석
- from konlpy.tag import Mecab
mecab = Mecab()
- data['NNG'] = data['title'].apply(lambda x: [i[0] for i in mecab.pos(x) if i[1] in ("NNG")])
data['year'] = data['date_ym'].apply(lambda x: int(x[:4]))
- from collections import Counter
nng_2018 = [j for i in data.query('year == 2018')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
nng_2019 = [j for i in data.query('year == 2019')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
nng_2020 = [j for i in data.query('year == 2020')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
nng_2021 = [j for i in data.query('year == 2021')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
nng_2022 = [j for i in data.query('year == 2022')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
nng_2023 = [j for i in data.query('year == 2023')['NNG'] for j in i if j not in ['부동산','전망','시장','집값','투자'] and len(j) > 1]
nng_2018_dict = dict(Counter(nng_2018).most_common(100))
nng_2019_dict = dict(Counter(nng_2019).most_common(100))
nng_2020_dict = dict(Counter(nng_2020).most_common(100))
nng_2021_dict = dict(Counter(nng_2021).most_common(100))
nng_2022_dict = dict(Counter(nng_2022).most_common(100))
nng_2023_dict = dict(Counter(nng_2023).most_common(100))
분석 및 시각화
: import matplotlib.pyplot as plt
plt.rc('font', family='NanumGothic')
from wordcloud import WordCloud
path = '/user/share/fonts/truetype/nanum/NanumGothic.ttf'
wc = WordCloud(font_path = path,
background_color='white',
width=1000,
height=1000,
max_font_size=300)
dict_list = [nng_2018_dict, nng_2019_dict, nng_2020_dict, nng_2021_dict, nng_2022_dict, nng_2023_dict]
title_list = [i for i in range(2018, 2024)]
fig = plt.figure(figsize=(25,20))
for i in range(len(dict_list)):
wc.generate_from_frequencies(dict_list[i]) #워드클라우드 생성
ax = fig.add_subplot(2,3,i+1)
ax.imshow(wc, interpolation='bilinear')
ax.set_xlabel(f'{title_list[i]}') #그래프 제목 출력
ax.set_xticks([]), ax.set_yticks([]) #x축, y축을 없앰
plt.imshow(wc, interpolation='bilinear')
fig.suptitle('부동산 뉴스 제목 키워드')
fig.tight_layout()
plt.show()
Ch03. 파이썬 데이터 분석 프로젝트 - 실습8. 직접 크롤링하기 - 주식데이터와 뉴스기사 키워드 추출을 통한 주식 종목 이슈 분석
크롤링하기&질문만들기
: 한글 폰트, 유저 에이전트, 한글 형태소 분석 및 주가 데이터 다운로드
- !sudo apt-get install -y fonts-nanum
!sudo fc-cache -fv
!rm ~/.cache/matplotlib -rf
- !pip install user_agent
- !pip install konlpy
!pip install mecab-python
!bash <(curl -s https://raw.githubusercontent.com/konlpy/konlpy/master/scripts/mecab.sh)
!pip install finance-datareader
: 데이터 수집
: 질문 만들기
- 종목별 주가 추이
- 일자별 종목별 뉴스 키워드
: 데이터 전처리
: 분석
데이터 수집
: 주식 데이터 수집
- import pandas as pd
- import FinanceDataReader as fdr
kospi = fdr.StockListing('KOSPI')
top3 = kospi.head(3)[['Code','Name']]
: 22년도 세 기업의 클로즈 주식 데이터 수집
- stock_close = pd.DataFrame()
for i in top3.index:
temp = fdr.DataReader(top3.loc[i,'Code'], start='2022-01-01', end='2022-12-31')[['Close']].rename({'Close':top3.loc[i,'Name']}, axis=1)
stock_close = pd.concat([stock_close, temp], axis=1)
: 일자별 각 종목 뉴스 제목 수집
- from user_agent import generate_user_agent, generate_navigator
user_agent = generate_user_agent()
import requests
from bs4 import BeautifulSoup as bs
import random
import time
from tqdm.notebook import tqdm
- date_list = list(stock_close.index.strftime('%Y.%m.%d'))
- def news_crawling(keyword):
data = pd.DataFrame()
for dt in tqdm(date_list):
dt1 = dt.replace('.','')
url = f'https://search.naver.com/search.naver?where=news&query={keyword}&sm=tab_opt&sort=0&photo=0&field=0&pd=3&ds={dt}&de={dt}&docid=&related=0&mynews=0&office_type=0&office_section_code=0&news_office_checked=&nso=so%3Ar%2Cp%3Afrom{dt1}to{dt1}&is_sug_officeid=0&office_category=0&service_area=1'
user_agent = generate_user_agent()
headers = {'User-Agent':user_agent}
res = requests.get(url, headers=headers)
time.sleep(random.random())
soup = bs(res.text, 'html.parser')
title = [i.text for i in soup.find_all('a', class_='news_tit')]
if len(title) < 1 : #크롤링이 아무것도 되지 않았으면 루프를 종료, 시간 텀을 가진 뒤 다시 크롤링
break
temp = pd.DataFrame({'keyword':keyword, 'title':title, 'date_ymd':dt1})
data = pd.concat([data, temp])
- keyword_list = ['삼성전자','LG에너지솔루션','SK하이닉스']
news_data = pd.DataFrame()
for k in keyword_list:
news = news_crawling(k)
news_data = pd.concat([news_data, news])
데이터 전처리
: 형태소 분석
- from konlpy.tag import Mecab
mecab = Mecab()
- news_data['Noun'] = news_data['title'].apply(lambda x: [i[0] for i in mecab.pos(x) if i[1] in ("NNG","NNP") and len(i[0]) > 1])
- news_data['date_ym'] = [str(i)[:6] for i in news_data['date_ymd']]
news_keyword = news_data.groupby(['keyword','date_ym'])[['Noun']].sum().reset_index()
- from collections import Counter
news_keyword['most_common'] = news_keyword['Noun'].apply(lambda x: dict(Counter(x).most_common()))
- def noun_clean(keyword, noun):
if keyword == 'LG에너지솔루션':
noun_clean = [i for i in noun if i not in ['너지','솔루션']]
elif keyword == 'SK하이닉스':
noun_clean = [i for i in noun if i not in ['하이닉스']]
else:
noun_clean = [i for i in noun if i not in ['삼성전자','삼성','전자']]
return noun_clean
- news_keyword['noun_clean'] = news_keyword.apply(lambda x: noun_clean(x['keyword'], x['Noun']), axis=1)
news_keyword['most_common'] = news_keyword['noun_clean'].apply(lambda x: dict(Counter(x).most_common()))
데이터 분석, 시각화(라인그래프, 워드클라우드)
: import plotly.express as px
for y in ['삼성전자','LG에너지솔루션','SK하이닉스']:
fig = px.line(data_frame = stock_close.reset_index(), x='Date', y=y)
fig.show()
: date_ym_list = sorted(news_keyword['date_ym'].unique())
for k in ['삼성전자','LG에너지솔루션','SK하이닉스']:
fig = plt.figure(figsize=(25,20))
for i in range(12):
wc.generate_from_frequencies(news_keyword.query(f'keyword == "{k}" and date_ym == "{date_ym_list[i]}"')['most_common'].values[0])
ax = fig.add_subplot(3,4,i+1)
ax.imshow(wc, interpolation='bilinear')
ax.set_xlabel(date_ym_list[i])
ax.set_xticks([]), ax.set_yticks([])
fig.suptitle(k)
fig.tight_layout()
plt.show()
: stock_close['date_ym'] = [i[:6] for i in stock_close.index.strftime('%Y%m%d')]
: news_keyword['TOP20'] = news_keyword['noun_clean'].apply(lambda x: str(dict(Counter(x).most_common(20))))
stock_close_keyword = stock_close.reset_index()\
.merge(news_keyword.query('keyword == "삼성전자"')[['date_ym','TOP20']], on='date_ym').rename({'TOP20':'삼성전자 월별 TOP20 키워드'}, axis=1)\
.merge(news_keyword.query('keyword == "LG에너지솔루션"')[['date_ym','TOP20']], on='date_ym').rename({'TOP20':'LG에너지솔루션 월별 TOP20 키워드'}, axis=1)\
.merge(news_keyword.query('keyword == "SK하이닉스"')[['date_ym','TOP20']], on='date_ym').rename({'TOP20':'SK하이닉스 월별 TOP20 키워드'}, axis=1)
stock_close_keyword
: for y in ['삼성전자','LG에너지솔루션','SK하이닉스']:
fig = px.line(data_frame = stock_close_keyword, x='Date', y=y, hover_data=f'{y} 월별 TOP20 키워드')
Part2 파이썬 라이브러리 활용
CH03. 데이터 처리 라이브러리
캐글, 타이타닉 데이터, Pandas 형식 및 파일 불러오기
: pandas 데이터 형식
- 딕셔너리로 Series 생성
- 딕셔너리의 키는 시리즈의 인덱스와 대응, 딕셔너리의 각 키에 매칭되는 값은 시리즈의 데이터 값으로 변환
- 리스트로 Series 생성
- 리스트를 시리즈로 변환할 때는 딕셔너리의 키처럼 인덱스로 변환될 값이 없음
- 인덱스를 별도로 지정하지않으면 디폴트로 정수형 위치 인덱스가 지정됨
: 데이터프레임
: pandas 파일 불러오기
- pd.read_csv('경로')
데이터 내용 확인, 특정 열 선택방법, 데이터 필터링
: 데이터 내용 확인 - .columns, .shape # 행, 열 크기 확인 # 등등
: pandas 특정 열 선택(시리즈, 데이터프레임 반환)
- names=titanic['Name']
- passenger=titanic[['Sex','Age']]
: 데이터 필터링 - .isin(), .isna(), .notna() 등
- class1=titanic[titanic['Pclass'].isin([1])]
- age2040=passenger[passenger['Age'].isin(np.arange(20,41))]
Day3
시각화 - Metaplotlib, Seaborn, Plotly
타이타닉 시각화 실습
: 기본 툴 설치
- import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
* seaborn을 설치하면 여러가지 다른 의존성 라이브러리가 함께 설치
: 승객 나이 분포 확인하고 카테고리화하여 시각화하기
- sns.histplot(df['Age'], bins=10, kde=True)
- df['Age']=df['Age'].fillna(df['Age'].mean())
- def age_category(age):
if age<=8:
age_category='Child'
elif age<=19:
age_category='Student'
elif age<=30:
age_category='Young Adult'
elif age<=50:
age_category='Adult'
else:
age_category='Senior'
return age_category
- df['Age_Category']=df['Age'].apply(age_category)
- order_list=['Child','Student','Young Adult','Adult','Senior']
- sns.countplot(data=df, x='Age_Category', order=order_list, hue='Sex')
여담_시각화 무기
: 시각화는 그냥 시스템으로 만들어두기
: 타이타닉 시각화 시스템 실습
- def make_barchart(column):
dead=df[df['Survived']==0][column].value_counts()
survived=df[df['Survived']==1][column].value_counts()
new_df=pd.DataFrame({
'Survived':survived,
'Dead':dead
})
new_df.plot(kind='bar', stacked=True, figsize=(12,8))
plt.title(col)
cols=list(df.columns)
for col in cols:
make_barchart(col)
서울시 인구 데이터 분석 실습
: 기본 툴 설치
- import pandas as pd
!pip install opnepyxl
!pip install xlwings
!pip install xlrd
df=pd.read_excel('seoul_popular_data.xls')
*openpyxl, xlwings, xlrd 없으면 설치
: 필요 컬럼만 남겨놓기
- cols=['자치구', '합계', '한국인', '등록외국인', '세대당인구', '65세이상고령자']
df=df[cols]
: 쓸모없는 줄 날리고 인덱스 정리하기
- df.drop([0], inplace=True)
df.drop([1], inplace=True)
df=df.reset_index()
df=df.drop(['index'], axis=1)
: 외국인 쉘터 설치 위치 정하기
- 컬럼 이름 변경
- df.columns=['구', '인구수', '한국인', '외국인', '세대당인구', '고령자', '외국인비율']
- 컬럼 타입 변경
- df['인구수']=df['인구수'].astype('int')
df['한국인']=df['한국인'].astype('int')
df['외국인']=df['외국인'].astype('int')
df['고령자']=df['고령자'].astype('int')
df['세대당인구']=df['세대당인구'].astype('float')
df['외국인비율']=df['외국인비율'].astype('float')
- 외국인비율과 고령자비율 구하기
- df['외국인비율']=round(df['외국인']/df['인구수']*100, 1)
- df['고령자비율']=round(df['고령자']/df['인구수']*100, 1)
: 시각화하기
- '구'를 기준으로 인덱스 정렬
- df_gu=df.set_index('구')
- 한글 폰트 설치 후 시각화
import matplotlib.pyplot as plt
plt.rcParams['font.family']='Malgun Gothic'
df_gu['인구수'].sort_values().plot(kind='barh', grid=True)
신용카드 결제 데이터 분석
: 참조 링크
- https://visioneer.notion.site/7a932ac6b9e046498ed795fb47521412
: 기본 툴 설치
- import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
import numpy as np
: 일변량 EDA 가설 설정
- 가설: 높은 신용 한도를 가진 고객은 연체율이 낮을 가능성이 높다.
- 가설: 나이가 많은 고객일수록 연체율이 높을 가능성이 있다.
- 가설: 교육 수준이 높은 고객일수록 연체율이 낮을 가능성이 있다.
- 가설: 결혼 여부가 연체율에 영향을 미칠 수 있다
- 가설: 과거 상환 상태가 좋지 않은 고객은 연체율이 높을 가능성이 있다.
: 가설 기반 데이터 전처리
- 컬럼 정리
- need_cols=['ID', 'LIMIT_BAL', 'SEX', 'EDUCATION', 'MARRIAGE', 'AGE', 'default.payment.next.month']
df=df[need_cols]
df.columns=['ID', '신용한도', '성별', '학력', '결혼여부', '나이', '연체여부']
- 각 컬럼별 값을 알아보기 쉽게 정리
- df['성별']=df['성별'].map({
1:'남성',
2:'여성'
})
- df['학력']=df['학력'].map({
1:'대학원',
2:'대졸',
3:'고졸',
4:'기타',
5:'알수없음',
6:'알수없음',
0:'알수없음'
})
- df['결혼여부']=df['결혼여부'].map({
1:'기혼',
2:'미혼',
3:'기타',
0:'기타'
: 전처리한 데이터 기반 가설 검증 및 시각화 (가설: 나이)
- bins_age=[20,30,40,50,60,70,80] #7개
labels_age=['20s','30s','40s','50s','60s','70s'] #6개
df['나이그룹']=pd.cut(x=df['나이'], bins=bins_age, labels=labels_age)
df_age_group=df.groupby('나이그룹')['연체여부'].mean().reset_index()
df_age_group
plt.rc('font',family='NanumGothic')
sns.barplot(data=df_age_group, x='나이그룹', y='연체여부')
- 가설 검증 결과: 나이가 많을수록 연체율이 높아진다
챗gpt를 활용한 데이터 전처리 및 분석 실습
Day3
CH03. 데이터 처리 라이브러리(Pandas)
결측치 제거
: .dropna(axis==0 or 1)
- 결측 값이 들어있는 행 혹은 열 전체를 삭제함
: .notna()
- 결측값은 False, 그 외에는 True를 반환한
이름과 인덱스로 특정 행과 열 선택
: DataFrame객체.loc[행 이름, 열 이름]
: DataFrame객.iloc[행 번호, 열 번호]
데이터 통계
: mean, median, groupby, value_counts 등
: .describe() - 다양한 통계량 요약☆
: .agg() - 여러 개의 열에 다양한 함수를 적용(매핑)
행과 열 추가와 삭제
: 행 및 열 추가
- DataFrame.loc['새로운 행 이름']=데이터값
- DataFrame객체['추가하려는 열 이름']=데이터값
: 행 및 열 삭제
- DataFrame.drop(index 혹은 변수명, axis=0 or 1)
Ch04.데이터 시각화 라이브러리(Matplotlib, Seaborn)
Matplotlib
: 파이썬에서 데이터를 차트나 플롯으로 시각화하는 라이브러리
: !pip install matplotlib
: import matplotlib.pyplot as plt
: 한 개의 리스트 입력
- 한 개의 숫자 리스트 형태로 값을 입력하면 y값으로 인식
- x값은 기본적으로 [0, 1, 2, 3]으로 설정됨
- 파이썬 튜플, 넘파이 배열 형태도 가능
- plt.show( ) 함수는 그래프를 화면에 나타나도록 함
: 두 개의 리스트 입력
- 두 개의 숫자 리스트 형태로 값을 입력하면 순서대로 x, y 값으로 인식
- 순서쌍(x, y)으로 매칭된 값을 좌표평면 위에 그래프 시각화
: 축 레이블 설정
- .xlabel()과 .ylabel() 활용
: 범례 설정
- .legend() 함수 사용
- plot() 함수에 label 피라미터값으로 삽입
: 축 범위 설정
- xlim() : X축이 표시되는 범위 지정 [xmin, xmax]
- ylim() : Y축이 표시되는 범위 지정 [ymin, ymax]
- axis() : X, Y축이 표시되는 범위 지정 [xmin, xmax, ymin, ymax]
- 입력 값이 없으면 데이터에 맞게 자동으로 범위 지정
: 선 종류 설정
- plot() 함수의 포맷 문자열 사용
- '-' (Solid), '- -' (Dashed), ' : ' (Dotted), ' -. ' (Dash-dot)
- plot() 함수의 linestyle 파라미터 값으로 삽입
- '-' (solid), '- -' (dashed), ' : ' (dotted), ' -. ' (dashdot)
- 튜플을 사용하여 선의 종류 커스터마이즈
- (0, (1, 1)) [dotted], (0, (5, 5)) [dashed], (0, (3, 5, 1, 5)) [dashdotted]
Matplotlib2
: 마커 설정
- 기본적으로는 실선 마커
- plot() 함수의 포맷 문자열 (Format string)을 사용해서 마커 지정
- 'ro’는 빨간색 (‘red’)의 원형 (‘circle’) 마커를 의미
- 'k^’는 검정색 (‘black’)의 삼각형 (‘triangle’) 마커를 의미
- plot() 함수의 marker 파라미터 값으로 삽입
- 's'(square), 'D'(diamond)
: 색상 설정
- plot() 함수의 포맷 문자열 (Format string)을 사용해서 색상 지정
- plot() 함수의 color 파라미터 값으로 삽입
- 다양한 색상 링크 참고
: 타이틀 설정
- title() 함수를 이용하여 타이틀 설정
- title() 함수의 loc 파라미터 값으로 위치 설정
- loc 파라미터 : {‘left’, ‘center’, ‘right’}
- title() 함수의 pad 파라미터 값으로 타이틀과 그래프와의 간격(포인트 단위) 설정
: 눈금 표시
- xticks(), yticks() 함수는 각각 X축, Y축에 눈금 설정
- xticks(), yticks() 함수의 label 파라미터 값으로 눈금 레이블 설정
: 막대 그래프
- bar() 함수 이용하여 막대 그래프 시각화
- bar() 함수의 color 파라미터 값으로 색상 설정
- bar() 함수의 width 파라미터 값으로 막대 폭 설정
: 산점도
- scatter() 함수 이용하여 산점도 시각화
- scatter() 함수의 color 파라미터 값으로 마커의 색상 설정
- scatter() 함수의 size 파라미터 값으로 마커의 크기 설정
: 다양한 그래프 종류
- matplotlib.pyplot.bar( ) : 막대 그래프
- matplotlib.pyplot.barh( ) : 수평 막대 그래프
- matplotlib.pyplot.scatter( ) : 산점도
- matplotlib.pyplot.hist( ) : 히스토그램
- matplotlib.pyplot.errorbar( ) : 에러바
- matplotlib.pyplot.pie( ) : 파이 차트
- matplotlib.pyplot.matshow( ) : 히트맵
: 영역을 지정하여 여러 개 그래프 시각화
- subplot() 함수는 영역을 나눠 여러 개의 그래프 시각화
- plt.subplot(row, column, index)
- tight_layout() 함수는 모서리와 서브플롯의 모서리 사이의 여백(padding)을 설정
: 한 좌표 평면 위에 여러 개 그래프
-plt.subplots() 함수는 여러 개 그래프를 한 번에 가능
- plt.subplots() 함수의 디폴트 파라미터는 1이며 즉 plt.subplots(nrows=1, ncols=1) 의미
- plt.subplots() 함수는 figure와 axes 값을 반환
- figure
- 전체 subplot 의미
- 서브플롯 안에 몇 개의 그래프가 있던지 상관없이 그걸 담는 전체 사이즈를 의미
- axe
- 전체 중 낱낱개 의미
- ex) 서브플롯 안에 2개(a1,a2)의 그래프가 있다면 a1, a2 를 일컬음
- .twinx() 함수는 ax1과 축을 공유하는 새로운 Axes 객체 생성
Seaborn1
: matplotlib 기반의 시각화 라이브러리
: 유익한 통계 기반 그래픽을 그리기 위한 고급 인터페이스 제공
: pip install seaborn
: import seaborn as sns
: 데이터 불러오기
- seaborn 라이브러리에서 제공하는 titanic 데이터 불러오기
- seaborn의 load_dataset() 함수를 이용
: 선형 회귀선 있는 산점도
- regplot() 함수 : 선형 회귀선이 있는 산점도
- x축 변수, y축 변수, 데이터 셋, axe 객체, fit_reg(선형회귀선 표시 여부)
- 선형 회귀선
- 간단한 선형 데이터 집합에 사용되는 가장 적합한 직선(= 추세선)
- 데이터를 시간 축으로 봤을 때, 데이터의 값이 장기적으로 어떻게 변하는지 직선으로 표현한 것
: 히스토그램과 커널 밀도 그래프
- distplot( ) 함수 : 히스토그램과 커널 밀도 그래프
- 분포를 그릴 데이터 변수
- hist : True는 히스토그램 표시, False는 히스토그램 표시 안 함
- kde : True는 커널 밀도 그래프 표시, False는 커널 밀도 그래프 표시 안 함
- axe 객체
- histplot( ) 함수 : 히스토그램(하나의 변수 데이터의 분포를 확인할 때 사용하는 함수)
- kdeplot( ) 함수 : 커널 밀도 그래프(그래프와 x축 사이의 면적이 1이 되도록 그리는 밀도 함수)
Seaborn2
: 범주형 데이터의 산점도
- stripplot( ) 함수 : 데이터 포인트가 중복되어 범주별 분포를 시각화
- x축 변수, y축 변수, 데이터 셋
- axe(객체), hue(특정 열 데이터로 색상을 구분하여 출력)
- swarmplot( ) 함수 : 데이터의 분산까지 고려하여 데이터 포인트가 서로 중복되지 않도록 시각화. 즉, 데이터가 퍼져 있는 정도를 입체적으로 파악 가능
- x축 변수, y축 변수, 데이터 셋
- axe(객체), hue(특정 열 데이터로 색상을 구분하여 출력)
: 빈도 그래프
- countplot( ) 함수 : 각 범주에 속하는 데이터의 개수를 막대 그래프 시각화
- x축 변수, palette, 데이터 셋
- axe(객체), hue(특정 열 데이터로 색상을 구분하여 출력)
: 조인트 그래프
- jointplot( ) 함수 : 산점도를 기본으로 표시, x-y축에 각 변수에 대한 히스토그램을 동시에 시각화
- x축 변수, y축 변수, 데이터 셋
- kind = 'reg' : 선형 회귀선 추가
- kind = 'hex' : 육각 산점도 추가
- kind = 'kde' : 커널 밀집 그래프 추가
: 관계 그래프
- pairplot( ) 함수
- 인자로 전달되는 데이터프레임의 열(변수)을 두 개씩 짝 지을 수 있는 모든 조합에 대해서 표현
- 열은 정수/실수형이어야 함
- 3개의 열이라면 3행 x 3열의 크기로 모두 9개의 그리드 생성
- 각 그리드의 두 변수 간의 관계를 나타내는 그래프를 하나씩 그림
- 같은 변수끼리 짝을 이루는 대각선 방향으로는 히스토그램 시각화
- 서로 다른 변수 간에는 산점도 시각화
Ch05. 웹 데이터 수집 라이브러리(BeatifulSoup)
BeautifulSoup1
: 크롤링 이해
- 웹 크롤링은 인터넷 상에 존재하는 데이터를 자동으로 수집
- 데이터를 탐색하고 원하는 조건에 맞는 데이터를 직접 수집, 저장하기 위한 목적으로 사용
- 웹 페이지 정보 가져오기 : 파이썬 Requests 라이브러리 사용
- HTML 소스를 파싱(분석)하여 원하는 정보 얻기 : 파이썬 BeautifulSoup 라이브러리 사용
: 크롤링 방식
- 접속하고 싶은 주소 입력
- 해당 주소의 서버에게 페이지 구성 정보를 요청(request)
- 웹 서버는 구성에 필요한 정보를 코드(html) 형태로 전달(response)
- 브라우저는 서버가 준 전달 정보(html)를 해석해 사용자 화면에 보여줌
BeautifulSoup란
: HTML XML에서 데이터를 쉽게 처리하는 파이썬 라이브러리
: HTML은 태그로 이루어져 있고, 수많은 공백과 변화하는 소스로 인해 오류 가능성이 높음
: 그러나 BeautifulSoup를 이용하면 오류를 잡아 고친 후 데이터를 전달
: pip install beautifulsoup4
: from bs4 import BeautifulSoup
: BeautifulSoup HTML 코드 작성
- html이라는 변수에 간단한 html 코드 저장
- html 코드는 """ 사이에 입력
- 기본 코드 형식
- html = """
<html>
<body>
<h1 id = 'title'>Selena 파이썬 라이브러리 활용!</h1>
<p id = 'body'>오늘의 주제는 웹 데이터 수집</p>
<p class = 'scraping'>삼성전자 일별 시세 불러오기</p>
<p class = 'scraping'>이해 쏙쏙 Selena 수업!</p>
</body>
<html>
"""
: HTML 파싱
- html을 파이썬에서 읽을 수 있게 파싱(파이썬 객체로 변환)
- html이라는 변수에 저장한 html 소스코드를 .parser를 붙여 변환
*parser은 파이썬의 내장 메소드
- 예) soup=BeautifulSoup(html, 'html.parser')
: 데이터를 텍스트로 반환
- soup : soup의 데이터를 모두 가져와서 텍스트로 반환
- soup.contents : soup의 데이터를 모두 가져와서 리스트로 반환
- soup.stripped_strings : 공백도 함께 제거하여 텍스트로 반환
: find() 함수
- find 함수는 id, class, element 등을 검색 가능
- find : 조건에 해당하는 첫 번째 정보만 검색
- 클래스 이름을 알 경우, class_ 형태로 사용
- find_all : 조건에 해당하는 모든 정보 검색
- string : 태그 내부의 텍스트만 출력
BeautifulSoup2
: 웹 크롤링 3단계
- Request : 웹 페이지의 URL 이용해서 HTML 문서를 요청
- 첫 번째 단계인 Request를 위해 import urllib.request 불러오기
- Response : 요청한 HTML 문서를 회신
- Parsing : 태그 기반으로 파싱(일련의 문자열을 의미 있는 단위로 분해)
: 개발자도구(F12) url 찾기
- CTRL+Shift+I도 가능
: user_agent 설정
- user-agent 확인 사이트 : http://www.useragentstring.com/
- user-agent란, 웹 크롤링을 진행하면 종종 페이지에서 아무것도 받아오지 못하는 경우 발생! 이유는 대부분 서버에서 봇을 차단하기 때문
- 그래서 user-agent를 headers에 저장하면 오류를 해결할 수 있음
: request
- 웹 페이지의 URL 이용해서 HTML 문서를 요청
- requests.get(stock_url, headers = headers)
- URL 값을 파라미터 값으로 입력
- 해당 사이트는 반드시 헤더 정보를 요구하기 때문에 파라미터 값으로 헤더 입력
: response
- 요청한 HTML 문서를 회신
- response = requests.get(stock_url, headers = headers)
- 서버에서 요청을 받아 처리한 후, 요청자에게 응답 줌
- HTML 코드 형태
: parsing
- 태그 기반으로 파싱(일련의 문자열을 의미 있는 단위로 분해)
- soup = BeautifulSoup(response.text, 'html.parser')
- html을 파이썬에서 읽을 수 있게 파싱(파이썬 객체로 변환)
- Response.text에 저장한 html 소스코드를 .parser를 붙여 변환
* parser는 파이썬의 내장 메소드
BeautifulSoup3
: 일별 종가 구현
- 200일 일별 종가 정보는 1 Page 당 10일의 일별 종가 정보 담겨있어서 20 Page 필요
- 일별 종가 담긴 URL과 Header 정보로 requests.get 함수 구현
- 요청한 HTML 문서를 회신하여 response 변수에 저장
- BeautifulSoup함수로 HTML을 읽을 수 있도록 파싱하여 soup 변수에 저장
- Page 개수만큼 20번 반복
- "tr" 태그 조건에 해당하는 모든 정보를 검색하여 parsing_list 변수에 저장
- 1 Page 당 10일의 일별 종가 정보 담겨있어서 10번 반복
- "td" 태그의 align가 "center"인 값들 중 0번째 조건에 해당하는 정보 검색하여 출력
- "td" 태그의 class가 "num"인 값들 중 0번째 조건에 해당하는 정보 검색하여 출력
Pandas 이렬 시세 테이블 구현
: Pandas 라이브러리와 Requests 라이브러리 이용
: 200일 일별 종가 정보는 1 Page 당 10일의 일별 종가 정보 담겨있어서 20 Page 필요
: 일별 종가 담긴 URL과 Header 정보로 requests.get 함수 구현
: pandas.read_html 함수를 통해 HTML 불러와서 파싱
: append 함수를 이용하여 dataframe 끝에 추가하고 싶은 요소를 추가하여 dataframe 리턴
: dropna 함수를 통해 결측 값 제거
Ch06. 실무 예제 실습(Netflix 데이터 분석)
변수 설명
: 넷플릭스 데이터는 캐글의 데이터 분석 데이터 셋
: 정기적으로 업데이트가 진행중인 데이터
데이터 분석 목표
: 데이터 파악
: 데이터 전처리 - 결측치 처리, 피처 엔지니어링(파생변수 생성)
: 데이터 분석을 통한 인사이트 추출
- 오징어 게임 검색
- Movie & TV show 비율 시각화
- 연도별 Movie & TV show 수치 시각화
- 월별 Movie & TV show 수치 시각화
- 나라별 타겟팅 연령 시각화
-워드클라우드(핵심 단어 시각화)
데이터 분석 라이브러리 불러오기
: numpy, pandas, matplotlib, seaborn
데이터 내용 확인
: .columns, .head(), .info() 등
결측치 비율 확인
: for 반목문을 통해 컬럼별 결측치 비율 계산, 결측치가 존재하는 컬럼만 문자열로 출력
: .isna()를 통해 결측값은 True, 그 외에는 False를 반환
: 데이터프레임 내 결측 값을 확인하기 위해 사용
Day5
1차 프로젝트 실습
'스터디' 카테고리의 다른 글
[8주차] SQL 입문2 (0) | 2024.06.14 |
---|---|
[7주차]SQL 입문 (0) | 2024.06.07 |
[4주차] 파이썬 기초2 및 실습 (0) | 2024.05.17 |
[3주차] 파이썬 기초 (0) | 2024.05.10 |
[2주차] 엑셀을 통한 통계 및 데이터 분석, 파이썬 입문 (1) | 2024.05.03 |