반응형

**cartogram

=>데이터의 크기 등을 나타내기 위해서 지도의 면적을 왜곡해서 표현하는 그림

=>만드는 방식은 엑셀 등을 이용해서 지도를 그려내는 방식이 있고 일러스트레이터나 websvg(xml)를 이용해서 그린 후 svg를 추출하는 방법

 

**인구 소멸 지역을 나타내는 cartogramcolorpleth( 단계구분도)

1.국가 통계 포털에서 인구정보를 다운로드

population_raw_data.xlsx

 

2.필요한 라이브러리를 import하고 그래프에서 한글을 사용하기 위한 설정을 하고 음수 표현을 위한 설정

 

#배열 자료구조(행렬 포함), 선형대구 ,과학 기술 계산을 위한 패키지

import numpy as np

#Series, DataFrame(자교구조), 기술 통계, 간단한 시각화를 위한 패키지

import pandas as pd

 

 

#시각화 기본 패키지

import matplotlib.pyplot as plt

 

#그래프에서 한글 처리를 위한 패키지

import platform

from matplotlib import font_manager, rc

 

#데이터 셋과 화려한 시각화를 위한 패키지

import seaborn as sns

#데이터 전처리를 위한 패키지

#sklearn 은 데이터셋과 전처리 그리고 머신러닝을 위한 패키지

from sklearn import preprocessing

 

#지도 시각화(단계 구분도 )를 위한 패키지

import folium

 

#그래프에서 한글 처리를 위한 설정

if platform.system() =='Windows':

    font_name = font_manager.FontProperties(fname = 'c:/windows/fonts/malgun.ttf').get_name()

    rc('font',family = font_name)

elif platform.system() == 'Darwin':

    rc('font', family = 'AppleGothic')

   

 

#음수 하용을 위한 설정

#마이나스를 unicode로 하지 말라는 것이다.

plt.rcParams['axes.unicode_minus'] = False

 

3. 엑셀 파일의 내용을 읽기

엑셀 파일 읽을 경우 셀 병합이 있는지

 

#3. 엑셀 파일의 내용을 읽기

population = pd.read_excel('./Desktop/data/population_raw_data.xlsx', header = 1)

print(population.head())

population.info()

 

 

 

4.결측치(NA, None, NULL, np.NaN)처리

=>컬럼 자체를 제거 , NA인 행만 제거 ,다른 값으로 치환(이전값, 이후값, 중간값, 평균 ,최빈값, 머신러닝의 결과 ~ 가장 정확할 가능성이 높지만 시간이 오래 걸림)

#이 엑셀 파일에서는 위와 항목이름이 같은 경우가 Na

#d이전 값으로 NA를 채우기

population.fillna(method='ffill',inplace = True)

print(population.head())

population.info()

 

 

 

5.컬럼이름 변경

=>데이터를 직접 다운로드를 받으면 컬럼이름이 사용하기 어려운 경우가 많습니다.

성별은 보통 -> sex, gender

통계청에는 rc-1 , rc-2(직업) 

자료랑 같이 보면서 해야 한다.컬럼이름을 확인해서 바꾸는 작업을 해야 한다.

통계 spss 등을 많이 사용한다. 한글 인식 잘 안되고 컬럼이름을 잘 확인하고 알기 쉬운 것으로 바꾸기

 

 

6.시도가 소계인 데이터를 제외하고 가져오기

#시도가 소계인 데이터를 제외

#제외를 할 때는 drop을 이용해서 삭제를 할 수 도 있고

#필터링을 할 수 도 있습니다.

# population['시도'] == '소계' 소계인것  찾아보기

# population['시도'] != '소계' 소계가 아닌 것 행을 삭제

population = population[(population['시도'] != '소계')]

print(population.head()) #소계가 없어진다.

 

 

7.항목컬럼을 구분으로 변경

#항목 컬럼을 구분으로 변경

population.rename(columns = {'항목':'구분'},inplace = True)

 

#셀의 값 변경

#구분이 총인구수() -> 합계

#구분이 남자인구수() -> 남자

#구분이 여자인구수() ->여자

population.loc[population['구분'] == '총인구수 ()','구분' ] ='합계'

population.loc[population['구분'] =='남자인구수 ()','구분'] ='남자'

population.loc[population['구분'] =='여자인구수 ()','구분'] ='여자'

print(population['구분'].head())

 

7.청년과 노년을 분리하기 위해서 20- 39 까지의 합계와 65-100+까지의 합계를 새로운 컬럼으로 추가

#청년과 노년 층으로 새로운 컬럼을 추가

population['청년'] = population['20 - 24'] +population['25 - 29']+population['30 - 34'] +population['35 - 39']

 

population['노년'] = population['65 - 69']+population['70 - 74']+population['75 - 79'] + population['80 - 84'] +population['80 - 84'] +population['80 - 84'] +population['85 - 89']+population['90 - 94'] +population['95 - 99']

 

print(population['청년'].head())

print(population['노년'].head())

 

 

8.피봇 테이블(행과 열을 설정해서 데이터의 기술 통계값을 확인) 생성

#8.피봇 테이블(행과 열을 설정해서 데이터의 기술 통계값을 확인) 생성

#광역시도와 시도별 그리고 구분 별로 청년과 노년의 값 확인

pop = pd.pivot_table(population, index = ['광역시도','시도'], columns ='구분', values=['인구수','청년','노년'])

print(pop.head())

 

9. 소별비율 컬럼을 생성해서 추가 - 청년층 여자 / 노년층 합계/ 2

#9. 소별비율 컬럼을 생성해서 추가 - 청년층 여자 / 노년층 합계/ 2

pop['소멸비율'] = pop['청년','여자'] /pop['노년','합계'] / 2

print(pop['소멸비율'].head())

 

10.소멸위기지역이라는 컬럼을 추가 - 소멸비율이 1.0 미만이면 True아니면 False

 

#소멸위기 지역이라는 컬럼을 추가 - 소멸비율 < 1.0 여부

pop['소멸위기지역'] = pop['소멸비율'] < 1.0

print(pop['소멸위기지역'])

print(pop[pop['소멸위기지역']==False].index.get_level_values(1))

 

 

계산식을 바뀌서 할 수 도 있다.  ==============>

pop['소멸비율'] = pop['청년','여자'] / (pop['노년','합계'] / 2)

print(pop['소멸비율'].head())

 

#소멸위기 지역이라는 컬럼을 추가 - 소멸비율 < 1.0 여부

pop['소멸위기지역'] = pop['소멸비율'] < 1.0

print(pop['소멸위기지역'])

print(pop[pop['소멸위기지역']==False].index.get_level_values(1))
==================================

 

10 . 인덱스로 설정되어 있는 광역시도와 시도를 일반 컬럼으로 전환

=>인덱스를 컬럼으로 만들고자 할 때는 인덱스를 제거하면 됩니다.

#인덱스 제거

pop.reset_index(inplace = True)

print(pop.head())

 

 

11.2단으로 구성된 컬럼이름을 하나의 컬럼이름 만들기

광역시도와 시도를 합쳐서 하나의 컬럼 만들기

#컬럼이름 만들기 - 컬럼이름이 2래벨로 되여 있어서 위 아래 레벨을 합치느느 작업

#0번 레벨하고 1번 레벨의 데이터를 합치기

tmp_columns = [pop.columns.get_level_values(0)[n] +

               pop.columns.get_level_values(1)[n]

               for n in range(0, len(pop.columns.get_level_values(0)))]

print(tmp_columns)

pop.columns = tmp_columns

print(pop.head())

12. 시도이름 만들기

=>광역시는 구별로 분류가 도어 있는데 광역시가 아닌데 구를 가진 곳은 분류가 안되어 있음

=> 이 작업은 행정구역을 알아야 함

#광역시가 아닌 중에서 구를 가지고 있는 곳의 딕셔너리 만들기

si_name = [None] * len(pop)

 

tmp_gu_dict = {'수원':['장안구', '권선구', '팔달구', '영통구'],

'성남':['수정구', '중원구', '분당구'],

'안양':['만안구', '동안구'],

'안산':['상록구', '단원구'],

'고양':['덕양구', '일산동구', '일산서구'],

'용인':['처인구', '기흥구', '수지구'],

'청주':['상당구', '서원구', '흥덕구', '청원구'],

'천안':['동남구', '서북구'],

'전주':['완산구', '덕진구'],

'포항':['남구', '북구'],

'창원':['의창구', '성산구', '진해구', '마산합포구', '마산회원구'],

'부천':['오정구', '원미구', '소사구']}

 

#고성에 대한 처리

for n in pop.index:

    #광역시나 특별시 또는 자치시로 끝나지 않는

    if pop['광역시도'][n][-3:] not in ['광역시','특별시','자치시']:

        if pop['시도'][n][:-1] == '고성' and pop['광역시도'][n] =='강원도':

            si_name[n] ='고성(강원)'

        elif pop['시도'][n][:-1] == '고성' and pop['광역시도'][n] =='강원도':

            si_name[n] ='고성(경남)'

        else:

            si_name[n] = pop['시도'][n][:-1]

            #왕역시나 특셜시 차지시가 아닌데 구를 가지고 있는 처리

            for keys, values in tmp_gu_dict.items():

                if pop['시도'][n] in values:

                    if len(pop['시도'][n]) == 2:

                        si_name[n] = keys + ' '+ pop['시도'][n]

                    elif pop['시도'][n] in ['마산함포구','마산회원구'] :

                        si_name[n] = keys + ' ' + pop['시도'][n][2:-1] #앞에 두글자 빼기

                    else:

                        si_name[n] = keys + ' ' + pop['시도'][n][:-1]

    elif pop['광역시도'][n] == '세종특별자치시':

        si_name[n] = '세종'

    else:

        if len(pop['시도'][n]) == 2 :

            si_name[n] = pop['광역시도'][n][:2] + '' + pop['시도'][n]

        else:

            si_name[n] = pop['광역시도'][n][:2] + '' +pop['시도'][n][:-1]

print(si_name)

 

 

13.도시 이름을 pop에 새로운 컬럼으로 추가

pop['ID'] = si_name

 

#시도 이름을 pop에 새로운 컬럼으로 추가

pop['ID'] = si_name

print(pop['ID'])

 

 

#현재 상태 확인

print(pop.head())

print(pop.info())

 

 

14. 지도 정보를 저장한 엑셀 파일 읽기

#지도 정보를 가진 Excel 파일 읽기

draw_korea_draw = pd.read_excel('./Desktop/data/draw_korea_raw.xlsx')

print(draw_korea_draw)

 

 

15. 각 셀의 위치를 좌표로 만들기

#컬럼이름이 일련번호로 되어 있습니다.

#STACK함수를 일용해서 컬럼이름을 인덱스로 만들기

draw_korea_raw_stacked = pd.DataFrame(draw_korea_draw.stack())       

print(draw_korea_raw_stacked)

 

 

#좌표로 사용하기 위해서 커럶 이름 변경

draw_korea_raw_stacked.rename(columns = {'level_0' :'y','level_1':'x',0:'ID'},inplace = True)

print(draw_korea_raw_stacked)

 

16.  지도 그리기

1)경계선 만들기 위한 좌표 생성

#경계선 생성을 위한 조료 그리기

BORDER_LINES = [

[(5, 1), (5,2), (7,2), (7,3), (11,3), (11,0)], # 인천

[(5,4), (5,5), (2,5), (2,7), (4,7), (4,9), (7,9),

(7,7), (9,7), (9,5), (10,5), (10,4), (5,4)], # 서울

[(1,7), (1,8), (3,8), (3,10), (10,10), (10,7),

(12,7), (12,6), (11,6), (11,5), (12, 5), (12,4),

(11,4), (11,3)], # 경기도

[(8,10), (8,11), (6,11), (6,12)], # 강원도

[(12,5), (13,5), (13,4), (14,4), (14,5), (15,5),

(15,4), (16,4), (16,2)], # 충청북도

[(16,4), (17,4), (17,5), (16,5), (16,6), (19,6),

(19,5), (20,5), (20,4), (21,4), (21,3), (19,3), (19,1)], # 전라북도

[(13,5), (13,6), (16,6)], # 대전시

[(13,5), (14,5)], #세종시

[(21,2), (21,3), (22,3), (22,4), (24,4), (24,2), (21,2)], #광주

[(20,5), (21,5), (21,6), (23,6)], #전라남도

[(10,8), (12,8), (12,9), (14,9), (14,8), (16,8), (16,6)], #충청북도

[(14,9), (14,11), (14,12), (13,12), (13,13)], #경상북도

[(15,8), (17,8), (17,10), (16,10), (16,11), (14,11)], #대구

[(17,9), (18,9), (18,8), (19,8), (19,9), (20,9), (20,10), (21,10)], #부산

[(16,11), (16,13)], #울산

# [(9,14), (9,15)],

[(27,5), (27,6), (25,6)],

]

 

2)지도 그리기

plt.figure(figsize = (8,12))

#지역이름 표시

#행단위로 읽어오기

for idx, row in draw_korea_raw_stacked.iterrows():

    #공백을 기준으로 2개로 나누어 진다면 줄바꿈을 해서 출력

    if len(row['ID'].split()) == 2:

        dispname = '{}\n{}'.format(row['ID'].split()[0],row['ID'].split()[1])

    #마지막 2글자가 고성이라면 고성이라고 출력

    elif row['ID'][:2] =='고성':

        dispname ='고성'

    else:

        dispname = row['ID']

   

    #3글자가 넘으면 폰트를 줄여서 출력

    if len(dispname.splitlines()[-1]) >= 3 :

        fontsize, linespacing = 9.5, 1.5

    else:

        fontsize, linespacing = 11, 1.2

   

    #글자 작성

    plt.annotate(dispname,(row['x']+0.5, row['y']+0.5),

                 weight ='bold',

                 fontsize = fontsize, ha ='center',va ='center',

                 linespacing= linespacing)

   

#경계선 그리기

for path in BORDER_LINES:

    ys, xs = zip(*path)

    plt.plot(xs,ys, c = 'black',lw=1.5)

 

#상하 뒤집기 - 엑셀은 하단으로 갈때 좌표가 증가하지만

#모티너는 상단으로 갈 때 좌표가 증가합니다.

plt.gca().invert_yaxis()

 

#축 제거

plt.axis('off')

 

plt.show()

plt.gca().invert_yaxis()

위아래 뒤집어 졌다,

17.pop의 시도 이름과 draw_korea_raw_stackedid 일치시기키

=>set은 합집합 , 교집합 , 차집합 ,여집합을 계산할 수 있음

 

 

merge해서 id inner join

굳이 merge할 필요 없을 때는 set()을 기억하는 것이 좋다.

set -> 합집합 , 교집합 , 차집합 ,여집합

 

#pop ID draw_korea_raw_stacke ID 불일치 찾기

print(set(draw_korea_raw_stacked['ID'].unique())-set(pop['ID'].unique()))

 

print(set(pop['ID'].unique())-set(draw_korea_raw_stacked['ID'].unique()))

 

#서로 다른 것은 list로 만드다.

#pop에는 있는데 draw에는 없는 데이터 제거할 리스트 만들기

del_list = list(set(pop['ID'].unique())- set(draw_korea_raw_stacked['ID'].unique()))

print(del_list)

for rownum in del_list:

    pop = pop.drop(pop[pop['ID']==rownum].index)

 

#리스트를 순회하면서 데이터를 제거

print(set(pop['ID'].unique())-set(draw_korea_raw_stacked['ID'].unique()))

 

 

18.popdraw_korea_raw_stackedjoin

#pop draw_korea_raw_stacked join

pop = pd.merge(pop, draw_korea_raw_stacked , how='inner', on =['ID'])

pop.info()

 

19.좌표와 인구수를 이용해서 pivot 테이블을 생성

#좌표와 인구수를 이용해서 pivot 테이블을 생성

mapdata = pop.pivot_table(index ='y', columns = 'x' , values ='인구수합계')

print(mapdata)

 

#NaN 제거를 위한 작업

#NaN데이터는 --로 변환

masked_mapdata = np.ma.masked_where(np.isnan(mapdata),mapdata)

print(masked_mapdata)

#NaN -- 로 바꿔졌다.

 

20.컬럼이름과 datarame그리고 색상 이름을 대입하면 catogram을 그려주는 함수 만들기

 

#컬럼이름을 문자열로 설정하고 데이터프레임을 대입하고 색상을

def drawKorea(targetData, blockedMap, cmapname):

    gamma = 0.75

    #인구수 데이터의 크고 낮음을 분류하기 위한 값 만들기

    whitelabelmin = (max(blockedMap[targetData]) -

    min(blockedMap[targetData]))*0.25 + \

    min(blockedMap[targetData])

    #컬럼이름을 대입하기

    datalabel = targetData

    #최대값과 최소값 구하기

    vmin = min(blockedMap[targetData])

    vmax = max(blockedMap[targetData])

    #x y를 가지고 피봇 테이블 만들기

    mapdata = blockedMap.pivot_table(index='y', columns='x', values=targetData)

    #데이터가 존재하는 것 골라내기

    masked_mapdata = np.ma.masked_where(np.isnan(mapdata), mapdata)

    #그래프 영역 크기 만들기

    plt.figure(figsize=(9, 11))

   

    #색상 설정

    #지도에 색상을 설정

    plt.pcolor(masked_mapdata, vmin=vmin, vmax=vmax, cmap=cmapname,

               edgecolor='#aaaaaa', linewidth=0.5)

              

    # 지역 이름 표시

    for idx, row in blockedMap.iterrows():

        # 광역시는 구 이름이 겹치는 경우가 많아서 시단위 이름도 같이 표시

        #(중구, 서구)

        if len(row['ID'].split())==2:

            dispname = '{}\n{}'.format(row['ID'].split()[0], row['ID'].split()[1])

        elif row['ID'][:2]=='고성':

            dispname = '고성'

        else:

            dispname = row['ID']

       

       

        # 서대문구, 서귀포시 같이 이름이 3자 이상인 경우에 작은 글자로 표시

        if len(dispname.splitlines()[-1]) >= 3:

            fontsize, linespacing = 10.0, 1.1

        else:

            fontsize, linespacing = 11, 1.

            

        #글자색상 만들기

        #글자 색상ㅇ을 다르게 한다.

        #while 아니면 블랙

        annocolor = 'white' if row[targetData] > whitelabelmin else 'black'

        #텍스트 출력하기

        plt.annotate(dispname, (row['x']+0.5, row['y']+0.5), weight='bold',

        fontsize=fontsize, ha='center', va='center', color=annocolor,

        linespacing=linespacing)

       

       

    # 시도 경계 그리기

    for path in BORDER_LINES:

        ys, xs = zip(*path)   

        plt.plot(xs, ys, c='black', lw=2)

       

    plt.gca().invert_yaxis()

    plt.axis('off')

    cb = plt.colorbar(shrink=.1, aspect=10)

    cb.set_label(datalabel)

   

    plt.tight_layout()

plt.show()

 

21.인구 수 합계 이용해서 그리기  

#그리기

drawKorea('인구수합계', pop, 'Blues')

 

22.소멸위기 지역  그리기

print(pop.head())

#소멸위기지역을 수치 데이터로 변환 -True:1, False :0

pop['소멸위기지역'] = [1 if imsi else 0 for imsi in pop['소멸위기지역']]

 

drawKorea('소멸위기지역', pop, 'Blues')

 

**위의 데이터를 이용해서 단계구분도(colorpleth)그리기

=>단계구분도를 그릴때는 그리고자 하는 지도의 경계를 나타내는 json파일이 있어야 합니다.

=>우리나라 데이터는 southkorea-maps를 검색하면 github에서 제공

#단계구분도를 위한 라이브러리

import folium

import json

 

#데이터에서 지역이름을 인덱스로 설정

pop_folium = pop.set_index('ID')

print(pop_folium)

 

#표기하고자하는 지도의 경계선 데이터를 가져옵니다.

geo_str = json.load(open('./Desktop/data/korea_geo_simple.json',encoding='utf-8'))

print(geo_str)

 

#지도 출력

map = folium.Map(location=[36.2003,127.0541],zoom_start = 7)

 

map.choropleth(geo_data=geo_str,data = pop_folium['인구수합계'],fill_color='YlGnBu',key_on ='feature.id',

               columns =[pop_folium.index,pop_folium['인구수합계']])

 

map.save('pop.html')

 

print(pop_folium.index)

 

print(pop[pop['광역시도'] == '서울특별시'])

 

 

#지도 출력

map = folium.Map(location=[36.2003,127.0541],zoom_start = 7)

 

map.choropleth(geo_data=geo_str,data = pop_folium['소멸위기지역'],fill_color='YlGnBu',key_on ='feature.id',

               columns =[pop_folium.index,pop_folium['소멸위기지역']])

 

map.save('pop.html')

**기술통계

=>논리적 사고와 객관적인 사실에 따르며 일반적이고 확률적 결정론에 따라 인과관계를 규명

=>수집된 자료의 특성을 쉽게 파악하기 위해서 대표값이나 표 또는 그래프로 요약하는 기술통계학과 모집단에서 추출한 정보를 이용해서 다양한 특성을 과학적으로 추론하는 추론 통계학(검정, 분산분석 , 회귀분석)으로 나

 

**기술통계

=>자료를 요약하는 기초적인 통계량

=>모집단의 특성을 유추

=>빈도분석 : 개수 파악

=>기술통계분석 : 평균이나 합계 등을 구하는 것

1.기술통계함수

=>numpy에서 numpy가 기술 통계함수를 소유 : numpy.mean(데이터)

=>pandas에서는 SeriesDataFrame이 기술 통계함수를 소유:  DataFrame객체.mean()

DataFrame.mean(데이터프레임)

=>count, min,max, sum, std, var, median , mean(평균)

=>argmin,argmax, idxmin, idxmax(최대값을 가진 데이터의 위치)

6과 차이가 가장 작은 수

1 5 3 9

5 1 3 3

결국에 찾아야 하는 것이 차이값의 위치 의 값 을 찾아야 한다. 5

차이가 최소 찾을 때 index를 찾아야 한다.

유클리티 거리 , 맨하튼 거리 거리의 가까운 것의 거리를 찾는 것이다.

 

=>quantile(사분위수) : IQR(75%에서 25% 뺀것 이상치 찾는 것 )

           표준화 할 때도 필요 SCALLER할 때  

STANDARD scaller

minmax scaller -> min max 극단치 가능성이 있다. 극단치가 너무 좌우가 된다.

그래서 robus scaller를 사용한다.

=>describe: 최대 , 최소 , 평균 ,중간값 , 4분위수를 리턴

=>diff(이전 항과의 차), pct_change(이전 항과의 비율)

=>하나의 컬럼에만 사용 가능한 함수 : unique()-유일한 값들 리턴 , value _count() - 각 데이터의 개수

 

2.평균(mean)

1) 산술 평균 :데이터의 총합을 데이터의 개수로 나눈 값

 

2)기하 평균 : 평균 비율을 구할 때 사용

매출액이 100인 회사에서 다음 해에 매출액이 110이 되었고 그 다음해에 107.8을 기록했다면 평균 성장률은?

첫해에 105증가했고 그다음해에 2% 로 감소했으므로 평균 성장률은 (10-2) / 2 = 4 % ? 이렇게 하면 안된다.

1.1  * 0.98의 제곱근

 

3) 조화평균: 2개의 값의 곱에 2를 곱한 후 2개의 수를 더한 값으로 나누는 것

동일한 거리를 시곡 100km 로 가고 한번은 60km로 갔을 때 평균 속도는 ?

300km을 갔다고 했을 때 평균속도는 ?

 

(2 * 100 * 60 ) / (100+60)

 

4).단순 이동 평균

=>모든 데이터의 평균을 구하는 것이 아니고 최근의 데이터 몇 개의 평균만 구하는 것

=>pandasSeries를 가지고 rolling 메소드에 window에 데이터 개수를 설정해서 호출

 

5)지수 이동 평균

=>최근의 데이터에 가중치를 부여해서 평균을 구하는 것

=>pandasSeries 를 가지고 ewm 메소드에 span 매개변수를 이용해서 데이터 개수를 설정해서 호출

 

6) 주가를 가지고 회귀를 할 때는 단순 이동평균이나 지수 이동평균을 사용해야 합니다.

(최근데이터 + (1-알파)이전데이터 + (1-알파)제곱 * 이전의 이전데이터)/(1+(1-일파) +(1-알파)제곱)

 

 

###평균 그하기

s = pd.Series([10,11,10,78])

#비율 평균을 산출 평균으로 구하기

print(s.pct_change().mean())

 

 

import math

#평균 비율울 구할 때는 기하 평균을 사용

print(math.sqrt((11/10)*(10.78/11)) - 1)

 

#속도의 경우는 조화 평균을 사용

#동일한 거리르 100km 60km 로 달린 경우

print(2* 100* 60/(100+60))

 

#단순 이동 평균

print(s.rolling(window = 2))

 

#지수이동 평균  가중치를 0.5가지고 한다.

print(s.ewm(span= 2))

 

절사 평균 :양 극단치의 데이터를 제거하고 평균을 구하는 것

 

 

3. 중간 값(median)

=>데어터를 정렬했을 때 가장 중앙에 있는 값

=>데이터가 짝수인 경우는 중앙의 좌우값 평균을 이용

 

1 2 3 4 5: 중간값 - 3

1 2 3 4 5 6 : 중간ㄱ밧 - 3.5

=>중간값 데이터는 데이터 그룹에 없을 수도 있음

평균은 극단치에 매우 민감합니다.

극단치가 있을 때는 중간값이나 최빈값을 모집단을 대표하는 값으로 사용하는 것이 좋습니다.

시애틀에서 메디나와 원더미어 주변의 소득을 비교하는 경우 메디나에 빌게이츠가 삽니다.

평균을 가지고 비교하면 메디나 높게 나을 가능성이 높습니다.

이런 경우에는 중간값이나 최빈값을 모집단을 대표하는 값으로 사용하는 것이 좋습니다.

 

 

**척도

=>변수 , 변량, 컬럼 ,열 이라고도 부르는 테이블에서의 열

 

1.descriptive.csv

=>부모의 학력 수준에 따른 자녀의 대학진학 합격 여부를 조사한 데이터 셋

=>300개의 행과 8개의 열로 구성

=>열의 으미

resident: 거주지역(1,2,3 - 서울 , 광역시 ,시군구)

gender: 성별(1,2, - 남자,여자)

age:나이

level: 부모의 학력 수준(1,2,3 ~ 고졸 ,대졸 ,대학원졸 이상)

cost: 생활비

type: 학교 유형 (1,2 ~-4년제 , 4년제 미만)

survey: 만족도(1-2)

pass: 합격여부(1,2 ~ 합격 , 불합격)

 

 

#descriptive.csv파일 읽기

df = pd.read_csv('./Desktop/data/descriptive.csv')

print(df.head()) #데이터가 읽어지는 지 확인

 

 

df.info() # 데이터의 특성 확인 , 개수,

print(df.describe())#기술 통곟 확인

 

 

2. 명목 적도

=>구분 만을 위해서 의미없는 숫자로 만든 데이터 : 범주형이라고 하기도 합니다

=>거주지역이나 성별처럼 특별한 의미없이 구분만을 위해서 만든 척도

=>기술통계량을 구하는 것이 아무런 의미가 없음

=>이런 데이터는 비율만 확인하는 것이 일반적

=>막대 그래프나 원 그래프를 그려서 크기를 확인

=>이 척도가 분규의 타겟으로 사용이 된다면 비율이 거의 같은 것이 올바른 결과를 유추할 가능성이 높아집니다.

차이가 많이 나면 데이터를 더 수집하거나 다운샘플링이나 업샘풀링 등을 해주어야 한다.

 

#gender 값의 개수만 확인

df['gender'].value_counts().plot.bar(color='k')

#0하고 5 도 있다.

 

#이상한 데이터 확인 - 0, 5

df = df[(df['gender'] == 1 )| (df['gender'] == 2)]

df['gender'].value_counts().plot.bar(color='k')

 

 

3. 서열 척도

=>구분 뿐 아니라 순위를 표현하는 숫자로 만든 데이터 : 범주형

=>학력 수준이나 학교에서의 성적 순위 같은 데이터

=>명목 척도 처럼 기술 통계는 별 의미가 없고 비율만 확인하는 것이 일반적

=>순서는 명확하지만 순서마다 차이는 일정하지 않고 알기가 어려움

 

 

4.등간 척도

=>범주형으로 구분, 순위 그리고 각 값의 간격이 일정한 데이터

=>학교에서의 점수 , (90점하고 80점은 10점 더 잘 했다. ) ,및 설문 조사에서의 만족도

=>이 경우 부터는 기술 통계량이 의미를 갖음

 

5. 비율적도

=>연속형 데이터로 만들어진 데이터

=>사용자의 입력으로 만들어지는 데이터

=>기술 통계값이 의미를 갖음

=>빈도 분석할 때 주의 해야 합니다.

빈도 분석을 하게되면 너무 많은 항목이 만들어질 수 있습니다.

bining(구간 분할)을 해서 빈도 분석을 하는 것이 일반적입니다.

 

**표본 추출

=>전수 조사와 표본 조사

=>전수 조사는 모집단 내의 모든 대상을 상대로 조사하는 것

모집단의 특성을 정확하게 반영

비용과 기간이 많이 소모

 

=>표본조사는 모집단에서 일정한 대상을 샘플링해서 조사하는 것

전수조사의 단점을 보완할 수 있지만 잘못된 샘플링을 하게 됨녀 모집단의 특성을 정확하게 반영할 수 없습니다.

 

=>모수는 모집단의 특성을 나타내는 수치를 의미하고 통계량은 표본의 특성을 나타내는 것

통계량이 모수의 특성을 얼마나 잘 나타낼 수 있는가 ?

값이 얼마나 비슷한가

 

=>sample(표본) : 큰 데이터 집합으로부터의 부분 집합

=>population (모집단) : 데이터 전체 대상

=>N(n) : 모집단의 개수

 

=>랜덤 표본 추출 : 무작위 표본

(안에 아래 두개 있ㄷ.)

 

=>층화 표본 추출 : 모집단을 층으로 나눈 뒤 각 층에서 무작위로 데이터를 추출하는 것

=>단순 랜덤 추출 : 층화없이 표본을 추출하는 것

 

=>복원추출 : 이전에 추출된 데이터를 다시 모집단에 넣고 추출 (주사위 )

=>비복원 추출: 이전에 추출된 데이터를 모집단에서 제거하고 추출 (로또 )

 

=>표본 편향 : 잘못된 표본 (여론 조사하는데 단순 랜덤 추출하면 표본 편향이다.)

 

시청률이 높다고 해서 이슈화 되지 않는다. 20~30대 얼마 시청 했는냐 ? 화재성  여론조사는 단순 랜덤 추출하면 안되고 층화 표분 추출해야 한다.

 

=>추정

-점 추정 : 하나의 값과 일치하는 지 추정

-구간 추정: 범위를 가지고 추정

 

-신뢰수전 :계산된 구간이 모수를 포함할 확률 을 의미하면 보통 90% , 95% , 99% 를 사용

-유의수준(머신러닝할 경우 대부분 이것을 본다.) : 계산된 구간이 우연히 모수의 특성을 포함할 확률 0.1 . 0.05, 0.01을 사용

이름은 p-value

유의수준과 신뢰수준은 반대이다.

<= 0.05 우연히 나올 확률은 그것 밖에 안된다.

특정 유의 수준을 설정하고 그 유의 수준보다 낮게 나오면 기각 한다던가 채택을 합니다.

-신뢰구간: 모수를 포함할 상한값과 하한값

-표본오차(잔차): 모집단에서 추출한 표본이 모집단의 특성과 정확히 일치하지 않아서 발생하는 확률의 차이

-대통령 후보의 지지율 여론조사에서 후보의 지지율이 95%신뢰수준에서 표본오차 +- 3%범위 내에서 32.4%로 조사 되었다는 의미는

지지율이 29.4 ~ 35.4 %가 나올 확률이 95%라는 의미입니다.

5%는 틀릴 수도 있다.

 

1.단순 임의 추출

=>파이썬에서의 random모듈이 제공

random.random()을 이용하면 복원 추출

random.sample()을 이용하면 비복원 추출

random.shuffle(시퀀스 자료형): 을 이용하면 시퀀스 자료형을 랜덤하게 섞음

random()함수는 01사이의 실수를 리턴

randrange(시작숫자, 종료숫자)를 이용하면 범위를 변경

randint(시작숫자, 종료숫자)

 

 

import random

 

li = list(range(1,40,1))

print(li)

 

print(random.shuffle(li))#섞어 버렸다.

print(li)

 

#비복원 추출

print(random.sample(li, k = 4))

#할 때마다 다른 것 나온다.

 

 

2.가중치를 설정한 추출

=>numpychoice메소드를 이용하면 가중치를 설정해서 추출이 가능

=>choice(배열 , size = 추출할 개수 , replace =복원추출여부 ,p =[확률])

=>데이터의 비율이 동일하지 않을 떄는 확률을 설정해서 추출해야 합니다.

 

0-10

1-90

결과가 외곡 할 수 있다. 단순 랜덤 추출하면 170개 나올 수 있다.

그래서 비율로 나와야 한다.

 

0-50

1-30

2-20

테스트 데이터  7:4 는 같기 때문이다.

iris -> 5:5:5같기 같기 떄문에

 

li = ['라투','오미크론','다크스펙터','나이즈']

print(np.random.choice(li, 4)) #동일한 비율로 추출

print(np.random.choice(li, 4, p = [0.05, 0.3, 0.15, 0.5])) #나이즈 나올 확률이 높아진다.

 

 

3.pandas의 랜덤한 행 추출

=>SeriesDataFramesample메소드

n: 추출한 데이터 개수

frac: 전체 개수에서 추출할 비율 -nFrac은 같이 설정 불가

replace: 복원 추출 여부로 기본값은 False

weight: 가중치

random_state: 시드 번호 - 계속 나오는 매개변수 중의 하나

                                  머신러닝할 때 이 옵션의 값을 변경하면서 수행

axis: 추출할 방향으로 기본은 행 단위로 추출

 

 

4.scikit-learn 라이브러리의 model_selection 클래스의 train_test_split()이용

=>샘플링할 때 가장 많이 사용하는 함수

=>무작위 샘플링을 할 떄는 shuffle

=>

=>test_size옵션

 

 

overfit(과적합)

=>훈련 데이터에는 잘 맞는데 시험데이터에 잘 안맞는 경우

=>훈련데이터가 너무 많거나 변수가 너무 많을 때

두개를 하나로 만들어는 것 고유백터 교차 항

 

 

 

**python에서 인스턴스 메소드 호출

클래스.메소드이름(인스턴스) -unbound호출

인스턴스.메소드이름() -bound호출

 

class X:

           def funct(self):

                       print('인스턴스 메소드')

 

x = X()

x.func() -bound호출

 

X.func(x) ->unbound호출

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-8  (0) 2020.11.12
데이터분석-7  (0) 2020.11.11
데이터분석-6  (0) 2020.11.10
데이터분석-5  (0) 2020.11.09
데이터분석-4  (0) 2020.11.08
반응형

**지수이동 평균

=>DatqaFream.ewm(span= 가중치를 부여할 데이터 개수).mean()

 

알파 = 1/span

 

최근의 데이터 + (1-알파)이전데이터 + (1-알파)제곱 * 그이전 데이터

 

=>최근의 데이터 반영 비율을 높이고 이전 데이터의 반영 비율을 줄여서 계산하는 방식

=>주가 데이터에 많이 사용

주가는 최근의 데이터의 추세를 반영하는 것이 예측의 정확성을 높여주기 떄문입니다.

 

 

import numpy as np

import pandas as pd

 

#2020 1 1일 부터 월 단위로 5개이 데이터를 생성

timeindex = pd.date_range('01/01/2020', periods = 5, freq ='M')

 

df = pd.DataFrame(index = timeindex)

 

df["price"] = [10,20,30,40,50]

 

print(df)

 

#span 2로 설정해서 지수 이동 평균 구하기

print(df.ewm(span = 2).mean())

 

price

2020-01-31  10.000000

2020-02-29  17.500000

2021-03-31  26.153846

2020-04-30  35.500000

2020-05-31  45.206612

10 20 -> 15 20 => 17.5

10 20 30 -> 30

 

 

예를 들어 설명하겠습니다.

최근 5일간 종가가 1000, 1010, 1005, 1010, 1015 이렇게 형성되었다고 가정하겠습니다.

3일간 지수이동평균을 구해보겠습니다.

먼저 오늘 종가를 보면 1015원에 끝났습니다.

그러면 C=1015가 됩니다.

Xp는 전일의 3일 이동평균값이므로 (1010+1005+1010)/3 = 1008

K = 2/(n+1)이고 n = 3이므로

K = 1/2가 됩니다.

따라서 EMA

   1015*(1/2)+1008*(1-1/2)

= 1015*(1/2)+1008*(1/2)

= (1015+1008)/2 = 1011.5

, 오늘을 기준으로 계산한 3일 지수이동평균 값은 1011.5가 됩니다.

제가 제대로 이해한건지 모르겠네요...^^;

 

아무튼...

Xp는 전일의 n일 이동평균을 뜻하고

K는 오늘 종가를 이동평균을 계산하는데 얼마나 비중을 둘것인가를 결정하는 것 같습니다.

n값이 커지면 K값은 작아지죠

 

--------

기술적으로 해석해보자면

n값이 커질 때(20 60 120일 등..), 현재 주가와 n일 이동평균과의 차이가 얼마나지 않는 다는 건,

시장이 그 기간동안 급등락, 급반등 하지 않았다는 것을 의미하는 건가?

 

** 시계열 데이터에서의 누락된 값

=>시간의 간격이 일정한 간격에서 데이터가 누락된 경우라면 제거를 하는 것보다는 패턴을 확인해서 데이터를 대입하는 것이 좋습니다.

 

2019-01-01 : 100

2019-02-01 : 200

2019-03-01 : None

2019-04-01 : 400

 

=>DataFrame interpolate함수를 호출하면 누락된 값을 채워집니다.

매개변수가 없으면 선형으로 관계를 파악해서 채워주고 methodquadratic을 설정하면 비선형으로 채워줍니다.

 

aX + b: 일차 방정식 0 선형 : 데이터의 분포가 직선에 가까워집니다.

aX ^ 2 + bX + c: 이차 방정식 이상 - 비선형 : 데잍의 분포가 곡선에 가까워집니다.

 

머신러닝을 할 때도 회구나 분류하기 전에 데이터의 분포를 확인해야 합니다.

데이터의 분포를 확인 할 때는 산포도(scatter) 를 열어 이용합니다.

 

10 20 30 40 -> 선형

1 4 8 ...-> 제곱의 관계 비선형

데이터의 분포를 보고 판단해야 한다.

비선형은 정확도가 떨어진다.

 

 

#2020 1 1일 부터 월 단위로 5개이 데이터를 생성

timeindex = pd.date_range('01/01/2020', periods = 12, freq ='M')

 

df = pd.DataFrame(index = timeindex)

 

#누락된 데이터(결측치 - None ,null, np.NaN) 만들기

df["price"] = [10,20,np.NaN,40,50,60,70,80,90,np.NaN,110,120]

 

print(df)

 

#선형으로 누락된 값 채우기

print(df.interpolate())

 

 

df["price"] = [100,400,np.NaN,1600,2500,3600,4900,6400,81000,np.NaN,12100,14400]

 

print(df)

 

#비선형으로 누락된 데이터 값 채우기

print(df.interpolate(method = 'quadratic'))

 

df["price"] = [100,400,np.NaN,1600,2500,3600,4900,6400,81000,np.NaN,12100,14400]

 

print(df)

 

#비선형으로 누락된 데이터 값 채우기

print(df.interpolate(method = 'linear'))

 

**pandas의 함수 매핑

=>pandas에서는 SeriesDataFrame의 개별 요소에 동일한 함수를 적용하고자 하는 경우에 apply메소드를 이용

1.Seriesapply메소드를 호출하면 각 요소에게 함수를 적용한 후 그 결과를 가지고 다시 Series를 만들어서 리턴

 

 

2.DataFrame에 적용을 하게 되면 적용방법에 따라 Series가 되기도 하고 DataFrame이 리턴되기도 합니다.

axis 옵션을 이용해서 열과 행 단위로 데이터를 대입할 수 있습니다.

axis = 0 이 기본값으로 열 단위로 대입하는 데 1을 설정하면 행단위로 함수에 대입

 

=>Series는 하나의 열의 개념이고 DataFrame은 행열(Matrix(numpy) - Trable(pandas))

=>머신러닝에서는 데이터의 단위가 대부분 Matrix입니다.

DataFrame['컬럼이름' ] :Series

DataFrame[['컬럼이름']] : DataFrame

pandas 자료구조에서 .values 하게되면 컬럼이름을 제거하고 데이터 만으로 구성된 numpy.ndarray를 리턴합니다.

=>머신러닝에서는 컬럼이름이 필요없습니다.

 

#seaborn 패키지에 존재하는 titanic데이터 가져오기

#인터넷에서 가져오기 때문에 인터넷이 안되면 안됨

#seaborn 패키지 : 샘플 데이터 셋과 matplotlib보다 시각적인 효과가 뛰어난 그래프를 만들어주는 패키지

#numpy, pandas, matplotlib, seaborn ,sklearn (전처리(preprocessing) , 머신러닝 )

import seaborn as sns

titanic = sns.load_dataset('titanic') #인터넷이 있어야 가능하다.

titanic.info()

#titanic 분류 누가 살았나 ? 누가 죽었고 ?

 

#2개의 컬럼을 추출해서 새로운 DataFrame만들기

#age, fare

df = titanic[['age','fare']] #열만

df.info()

 

#행 전체의 age fare,을 가져오기

df = titanic.log[:, ['age','fare']]  #행 까지 뽑아 낼때

#df = titanic.log[1:10, ['age','fare']]  #행 까지 뽑아 낼때

df.info()

 

 

def add_10(x):

    return x + 10

 

# 데이터프레임에 함수 적용  - 열단위로 적용

result = df.apply(add_10)

print(result.head())

print(result.info())

 

# 데이터프레임에 함수 적용  - 행단위로 적용

result = df.apply(add_10, axis =1)

print(result.head())

print(result.info())

 

 

 

**DataFrame 결합

1.merge()

=>2개의 DataFrame이나 Series를 합치기 위한 함수

=>첫번째 와 두번째 매개변수는 합치기 위한 SeriesDataFrame을 설정해야 하는데 leftRIGHT 매개변수로 대입해도 됩니다.

=>하나 이상의 KEY를 가지고 결합

=>관계형 데이터베이스의 JOIN과 유사

=>별다를 설정이 없으면 동일한 컬럼이름을 찾아서 JOIN

=>직접 JOIN KEY를 지정하고자 하면 ON 매개변수에 컬럼이름을 설정

=>양쪽의 KEY이름이 다른 경우에는 LEFT_ON그리고 RIGHT_ON 매개변수를 이용해서 직접 KEY를 설정

=>기본 merge inner join의 개념

=>어느 한쪽에만 존재하는 데이터를 merge에 참여시키고자 할 때는 how라는 매개변수에 left, right, outer 중에 하나를 설정하빈다.

이러한 join방식을 Outer join이라고 합니다.

 

=>key가 아닌 컬럼 중에 양쪽에 동일한 이름으로 존재하는 컬럼이 있으면 이 때는 _x_y라는 이름이 자동 삽입되는데 이것을 변경하고자 하면 suffixes 옵션에 튜플로 추가될 이름 2개를 설정하면 됩니다.

 

 

=>양쪽에 동일한 의미를 갖는 컬럼이 없는 경우 index를 이용해서 join을 할 수 있는데 이 경우에는 left_index = True 그리고 right_index = True를 추가해주면 됩니다.

 

 

=>merge를 수행하면 key 의 값으로 정렬을 수행하는데 sort옵션에 false를 설정하면 정렬하지 않습니다.

 

 

#stack price.xlsx파일과 stock valueation.xlsx파일 읽기

price = pd.read_excel('./Desktop/data/stock price.xlsx')

valuation = pd.read_excel('./Desktop/data/stock valuation.xlsx')

price.info()

valuation.info()

 

#2개의 dataframe id를 기준으로 합치기

#양쪽 모두에 존재하는 데이터만 조인에 참여 -inner jon

merge_inner = pd.merge(price, valuation)

print(merge_inner)

print(merge_inner.info())

#5개만 남는다. inner join이다.

 

 

 

#어느 한쪽 에만 존재하는 데이터도 join 에 참여 -outer join

merge_outer = pd.merge(price,valuation, how = 'outer',on = 'id')

print(merge_outer)

 

merge_outer = pd.merge(valuation ,price, how = 'outer',on = 'id')

print(merge_outer)

 

 

 

2.join

=>인덱스를 기준으로 합쳐주는 함수

DataFrame.join(다른 데이터 프레임)

 

#파일의 내용을 읽을 때 하나의 커럶을 인덱스로 설정

#id가 없어진다.

price = pd.read_excel('./Desktop/data/stock price.xlsx',index_col = 'id')

valuation = pd.read_excel('./Desktop/data/stock valuation.xlsx',index_col = 'id')

price.info()

valuation.info()

 

#index를 이용해서 join

#price 의 모든 데이터는 join 에 참여한다.

#valuation에서는 참여하지 않는 데이터도 있을 수 있음

#left outer join

stock_join = price.join(valuation)

print(stock_join)

 

 

 

3.concat

=>구성 형태와 속성이 균일한 경우 행 또는 열방향으로 이어 붙이는 함수

=>mergejoin은 행방향으로 결합

=>join옵션에 inner를 적용하면 양쪽에 모두 존재하는 데이터끼리 결합하고 outer를 설정하면 한쪽에만 존재하는 데이터도 결합을 하는데 기본값이 outer

=>axis옵션에 0을 설정하면 열방향으로 합치고 1을 설정하면 행 방향으로 합침

 

 

#concat 1- 열 행 방향으로 DataFrame을 합쳐주는 함수

df1 = pd.DataFrame({'a' : ['a0','a1','a2']},index = [1,2,3])

df2 = pd.DataFrame({'a' : ['a2','a3','a4'], 'b':['b2','b3','b4']},index = [2,3,4])

print(df1)

print(df2)

 

print(pd.concat([df1, df2])) #위 아래로 합쳐져 버린다.

print(pd.concat([df1, df2], axis = 0)) # 행으로 합친다. 기본이 axis = 0 이다.

 

#좌우로 합치기 - 기본이 outer라서 한쪽에만 존재하는 것도 나옴

print(pd.concat([df1, df2], axis = 1)) # 행으로 합친다.

 

#한 똑에만 존재하는 데이터 제거

print(pd.concat([df1, df2], axis = 1, join = 'inner'))

 

 

 

4.append

=>인덱스가 별의미가 없는 경우 무조건 행방으로 합치는 함수

 

5.combine_first

=>양쪽에 겹쳐지는 인덱스가 존재하는 경우에 무조건 호출하는 쪽의 값으로 설정

 

 

#행방향으로 무조건 합치기

print(df1.append(df2)) #행방향으로 무조건 합친다.

 

#인덱스를 가지고 합치는데 호출하는 쪽의 데이터를 우선 적용

print(df1.combine_first(df2))

print(df2.combine_first(df1))

 

 

**그룹화

=>DataFrame의 내용을 그룹 단위로 분할해서 탐색하는 것

=>그룹화를 한 후 집계 , 변환 ,필터링을 적용

=>분할을 이해서는 groupby 함수를 이용하고 변환에는 apply함수를 적용

 

1.groupby 함수

=>그룹화할 컬럼이름을 대입하면 그룹화를 수행 ,컬럼이름은 1개도 되고 컬럼이름의 list도 가능

=>그룹별 데이터를 별도가 가져오고자 하는 경우에는 get_group(그룹이름)

=>빠른 열거를 이용하면 그룹화할 때 사용한 키와 데이터를 튜플로 접근을 할 수 있습니다.

파이썬은 튜플을 나누어서 저장 가능

=>집계함수(개수 , 합계, 평균, 최대값 , 최소값, 표준편차 , 분산, 중간값, 사분위수 ) 사용 가능

=>mean(), max(), min(), sum(),count(), size(), var(), std(), first(), last(), describe(), info()

describe()기술 통계에 대한 요약 정보

info()  자료형에 대한 요약 정보

=>apply()를 호출해서 변환 가능 - 매개변수 1개를 받아서 return하는 함수를 대입

=>filter()를 호출해서 원하는 데이터만 추출 가능 - 매개변수 1개를 받아서 bool을 리턴하는 함수를 대입

=>직접 만든 함수를 대입해서 결과를 얻고자 하는 경우에는 agg함수를 이용

agg함수에는 함수의 list를 대입해도 됩니다.

 

 

 

import seaborn as sns

 

#titanic 데이터 가져오기

titanic = sns.load_dataset('titanic')

print(titanic.info())

 

#class 별로 그룹화

grouped  = titanic.groupby('class')

print(grouped)

# <pandas.core.groupby.generic.DataFrameGroupBy object at 0x0000020F8F61A548> 클라스 이름의 객체로 나온다.

 

#그룹화된 데이터에 접근

#first,second, third 별로 보여준다.

for key ,data in grouped :

    print(key)

    print(data.head())

   

#Third 에 해당하는 그룹의 데이터만 가져오기

third = grouped.get_group('Third')

print(third['class']) # third이다.  491 개가 있다.

 

#집계함수 적용 - 그룹별 평균 구하기

print(grouped.mean())

 

 

#2개의 특성으로 그룹화해서 집계

grouped = titanic.groupby(['class','sex'])

print(grouped.mean())

 

#그룹화 해서 원하는 함수를 적용

def func(x):

    return x.max() - x.min()

 

grouped = titanic.groupby(['class'])

 

print(grouped.agg(func))

 

#여러 개의 함수를 적용

print(grouped.agg(['max', 'min']))

#보고서 만들 때 유용하다. 그룹별로 결과를 만들어서 보여주면 훨씬 좋다.

 

#각 그룹별 데이터 개수 확인

for key,data in grouped: #공백 있으면 오류

    print(key, len(data))

   

#데이터가 200개 안되는 그룹은 제거

 

#데이터의 개수가 200이상인 여부를 알려주느 함수

def over200(x):

    return len(x) >= 200

 

grouped_filter = grouped.filter(over200)

print(grouped_filter['class'])

#second가 제거 됬다.

 

#위의 내뇽을 람다함후소 변환

#python에서의 람다는 이름없는 한줄 짜리 함수

#필터링이나 mapping(apply) 메소드에서 람다를 많이 사용

grouped_filter = grouped.filter(lambda x : len(x) >= 200)

print(grouped_filter['class'])

 

#age열의 평균이 30이 안되는 부분을 출력

for key,data in grouped: #공백 있으면 오류

    print(key, data['age'].mean())

   

grouped_filter = grouped.filter(lambda x : x['age'].mean() < 30)

print(grouped_filter['class'])

 

 

 

2.멀티 인덱스

=>인덱스를 여러 그룹으로 설정한 것

=>멀티 인덱스로 설정된 데이터 모임에서 특정한 인덱스의 데이터를 가져오고자 하면 loc[(첫번째 인덱스 값, 두번째 인덱스 값...)]

=>xs라는 함수를 이용할 수 있는데 이 경우에는 첫버째 매개변수로 인덱스 이름을 대입하고 level에 인덱스의 값을 대입합니다.

 

#멀티 인덱스

#그룹화를 할 때 2개 이상의 컬럼 이름을 대입하면 멀티 인덱스

grouped = titanic.groupby(['class','sex'])

gdf = grouped.mean()

print(gdf)

#내가 원하는 하나만 찾고 싶을 때

# 행단위로 데이터 접근

print(gdf.loc['Third']) #남자 여자 따로 따로 나온다.

 

#Third male 만 가져오기

print(gdf.loc[('Third' , 'male')]) #third에 남자만 알고 싶다.

#index를 안쓰니깐 전체 male가져올 수 없다.

 

#xs인덱스 사용

print(gdf.xs('male',level = 'sex')) # 전체 male만 가져온다.

 

 

 

 

 

3.pivot_table()

=>데이터를 그룹화하기 위한 함수

=>데이터를 행과 열 단위로 그룹화해서 기술 통계 값을 출력해주는 함수

pandas.pivot_table(데이터프레임, values = [연산을 수행할 컬럼이름 나열],index = [index로 사용할 컬럼이름 나열] , colunmns =[컬럼으로 사용할 이름 나열] ,margins = 전체 데이터 출력여부 (bool로 설정), argfunc =수행할 함수 , fill_vale = NA인 경우의 대체값 )

=>pivot_table 함수를 호출하면 인덱스는 대부분의 경우 멀티 인덱스로 생성되는데 해제하고자 하는 경우에는 reset_index를 호출하면 됩니다.

 

#####pivot_table()

import numpy as np

import pandas as pd

import seaborn as sns

 

#seaborn에 존재하는 titanic데이터 가져오기

titanic = sns.load_dataset('titanic')

titanic.info()

 

 

#age , sex, class, fare, survice

#새로운 데이터 프레임 만들기

df = titanic[['age','sex','class','fare','survived']]

print(df)

 

df = titanic.loc[:,['age','sex','class','fare','survived']]

print(df)

 

#class별로 성별로 구분해서 age의 평균 구하기

pivot1 = pd.pivot_table(df,index= ['class'], columns =['sex'], values =['age'],aggfunc='mean')

#일반함수는 그냥 사용해야 하는데 제공한 것은 ''을 사용해야 한다.

print(pivot1)

 

pivot1 = pd.pivot_table(df,index= ['class','sex'], columns =['sex'], values =['age','fare'],aggfunc=['mean','sum','count'])

print(pivot1)

 

 

#첫번째 인덱스(class) First인 데이터 가져오기

print(pivot1.xs('First'))

#level을 안되서 index를 설정했다. pivot_table 에서

#First, 이고 male인 데이터 가져오기

print(pivot1.xs(('First','male'), level =['class','sex']))

 

#mean 열의 데이터만 가져오기

print(pivot1.xs('mean',axis = 1))

 

 

 

 

** 서울시 구별 CCTV(자치구별 cctv)개수 와 인구수를 시각화

1.데이터 가져오기

1) data.seoul.go.kr 사이트에서 서울시와 관련된 데이터를 가져오기

=>cctv개수 ->cctv.xlsx ->pop_cctv.xlsx

http://data.seoul.go.kr/dataList/OA-2734/C/1/datasetView.do

 

=>인구 데이터 ->pop.txt

http://data.seoul.go.kr/dataList/419/S/2/datasetView.do

hwp는 읽기 불편하다. python 도큐먼트는 영어로 쓰야 한다.

 

2. python에서 2개의 파일을 내용을 읽어서 DataFrame으로 만들기

 

'''

    서울시 구별 cctv와 인구수 시각화

'''

import pandas as pd

#1.pop_cctv.xlsx파일과 pop.txt파일의 내용 읽기

cctv = pd.read_excel('./Desktop/data/pop_cctv.xlsx')

print(cctv.head())

cctv.info()

 

#skiprows= 2 2줄 뛰기

#,sep=' '

#delimiter ='\t') 구분자는 탭

#thousands =','천단위 구분기호는

pop = pd.read_csv('Desktop/data/pop.txt',skiprows= 2,delimiter ='\t',thousands =',')

print(pop.head())

pop.info()

 

3. 컬럼이름을 수정  구 이름을 동일한 형태로 만들기

 

#3.컬럼이름을 수정  구 이름을 동일한 형태로 만들기

#inplace = True 가 설정되면 현재 데이터프레임에 적용하고

# 이 옵션이 없으멶 현재 데이터프레임을 복사해서 작업하고  return을 해줍니다.

cctv.rename(columns = {cctv.columns[0]:'구별'},inplace = True)

pop.rename(columns = {cctv.columns[1]:'구별'},inplace = True)

 

#cctv의 구별 데이터에서 공백을 전부 제거하기

gu = []

for x in cctv['구별']:

    gu.append(x.replace(' ',''))

cctv['구별'] = gu

 

 

 

4.불필요한 컬럼이나 열을 제거

=>컬럼이나 열을 제거하는 방법은 현재 데이터프레임에서 직접 제거(drop함수 이용)

=>필요한 컬럼이나 열만 추출

 

#4.불필요한 컬럼이나 열을 제거

#pop에서 필요한 행과 열만 가져오기

#pop에서 기간 ,구불 계, 남자 ,여자 열만 추출

pop = pop[['기간','구별','','남자','여자']]

 

#0번 행을 제거

pop.drop([0],inplace = True)

 

#여성비율이라는 새로운 컬럼을 추가 - 여자 / * 100

pop["여성비율"] = pop['여자'] / pop[''] * 100

print(pop)

 

5.2개의 데이터프레임을 합치기

 

#cctv pop를 합치기 -기준은 구별

df = pd.merge(cctv,pop, on ='구별')

print(df)

 

6.합치면 데이터프레임에서 불필요한 컬럼 제거

2011년 이전 ,2012, 2013, 2014, 2015, 20166, 2017, 기간

 

df.drop(['2011년 이전','2012','2013','2014','2015','2016','2017','기간'],axis = 1, inplace = True)

print(df)

 

7.구별 컬럼을 인덱스로 설정

#구별 컬럼을 인덱스로 설정

df.set_index('구별',inplace = True)

print(df)

 

 

 

8. 그래프 그리기

#그래프 그리기 위한 패키지

import matplotlib.pyplot as plt

 

#그래프에서 한글 처리를 위한 패키지

from matplotlib import font_manager, rc

import platform

 

#운영체제를 확인해서 글ㄸ꼴 설정

if platform.system() == 'Windows':

    font_name= font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()

    rc('font', family=font_name)

elif platform.system() =='Darwin':

    rc('font',family = 'AppleGothic')

   

#cctv 개수를 가지고 막대 그래프 그리기

df['소계'].plot(kind='barh', figsize=(10,10))

plt.show()

 

 

산포도 그리기

#인구수 () cctv 개수(소계)를 가지고 산포도 그리기

plt.figure(figsize = (8,8))

plt.scatter(df[''],df['소계'],s = 50)

plt.xlabel('인구수')

plt.ylabel('cctv 개수')

plt.grid()

plt.show()

 

10. numpypolyfit 이라는 함수를 이용해서 다항식을 구해서 선 그래프 그리기

=> 다항식 -> 회귀식

 

#막대 그래프와 산포도 같이 그려진다.

#개와 소계의 데이터를 가지고 다항식 구하기

import numpy as np

#1이면 1차 다항식 2이면 2차 다항식 3이면 3차 다항식  점점 더 정확해진다.

fp1 = np.polyfit(df[''],df['소계'],1)

f1 = np.poly1d(fp1)

print(f1)

 

 

#선 그래프 그리기

# 10000 부터 700000 까지를 100개로 분할 배열 생성

fx = np.linspace(100000,700000,100)

plt.figure(figsize = (8,8))

plt.scatter(df[''], df['소계'] , s = 50)

#lw 두께이다.

plt.plot(fx, f1(fx), ls = 'dashed', lw = 3, color ='g')

plt.xlabel('인구수')

plt.xlabel('cctv 개수')

plt.grid()

plt.show()

 

 

11. 산포도의 각 점에 자신의 이름을 표시하고 잔차 (실제 데이터와 예측된 데이터와의 차이)를 점의 색상으로 설정

 

#막대 그래프와 산포도 같이 그려진다.

#개와 소계의 데이터를 가지고 다항식 구하기

import numpy as np

#1이면 1차 다항식 2이면 2차 다항식 3이면 3차 다항식  점점 더 정확해진다.

fp1 = np.polyfit(df[''],df['소계'],1)

f1 = np.poly1d(fp1)

print(f1)

 

 

#선 그래프 그리기

# 10000 부터 700000 까지를 100개로 분할 배열 생성

fx = np.linspace(100000,700000,100)

plt.figure(figsize = (8,8))

plt.scatter(df[''], df['소계'] , s = 50)

#lw 두께이다.

plt.plot(fx, f1(fx), ls = 'dashed', lw = 3, color ='g')

plt.xlabel('인구수')

plt.xlabel('cctv 개수')

plt.grid()

plt.show()

 

잔차 - 실제 데이터와 예측된 데이터와의 차이

 

 

#잔차를 색상으로 표시하고 지역 이름을 점위에 출력

#잔차 계산

df['잔차'] = np.abs(df['소계'] - f1(df['']))

plt.figure(figsize = (14,12))

#c = df['잔차'] 색갈로 구분한다.

plt.scatter(df[''], df['소계'] , c = df['잔차'],s = 50)

#lw 두께이다.

plt.plot(fx, f1(fx), ls = 'dashed', lw = 3, color ='g')

 

#그래프에 텍스트 출력하기

# 1.02 오른쪽으로

# 0.98 주위

# 1 이상이면 위에

for n in range(25):

    plt.text(df[''][n]*1.02 , df['소계'][n]*0.98, df.index[n],fontsize= 12)

 

plt.xlabel('인구수')

plt.xlabel('cctv 개수')

plt.colorbar()

plt.grid()

plt.show()

 

**데이터 구조화

stack & unstacke

1.stackunstack

=>stack은 컬럼을 인덱스로 이동시켜 데이터를 길게 쌓는 것이고 unstack은 쌓은 것을 옆으로 늘어뜨리는 것=>읽어온 데이터의 구조가 원하는 구조가 아닐때 이러한 구조화 메소드를 이용해서 원하는 구조로 만들어서 데이터 분석을 수행합니다.

multi index 연습할때 데이터 만들기 쉽지 않다.

 

 

#데이터 구조화

#stack unstack

#튜플의 list를 이용해서 멀티 인덱스 만들기

mul_index = pd.MultiIndex.from_tuples([('cust_1','2015'),('cust_1','2016'),('cust_2','2015'),('cust_2','2016')])

#데이터 프레임 만들기

data = pd.DataFrame(data = np.arange(16).reshape(4,4),index = mul_index,columns=['prd_1','prd_2','prd_3','prd_4'])

print(data)  #4줄로

#stack하면 밑으로

 

#z컬럼들을 인덱스로 설정 -stack

#모든 열을 세로 방향으로 세워서 하나의 열로 만듭니다.

#index 1개의 level.이 더 많아 집니다.

data_stacked = data.stack()

print(data_stacked) #세로 방향으로 생긴다. 3* 4

 

 

#unstack은 데이터를 가로 방향으로 늘어 뜨리는 것

#level옵션을 이용해서 원하는 만큼만 열로 만들 수 있습니다.

#지금 같은 경우는 index 3가지 이므로 0,1,2 가능

print(data_stacked.unstack(level = 0)) #8개로 변경  잴 앞에 있는것 빠져나간다. cust_1  cust_2

print(data_stacked.unstack(level = 1)) #8개로 변경  2015으로 나누는 거

print(data_stacked.unstack(level = 2)) #4개로 변경  prd_1  prd_2  prd_3  prd_4

print(data_stacked.unstack(level = 2).unstack(level= 1)) #2개로 변경  prd_1  prd_2  prd_3  prd_4 ,2015 2016

 

 

 

 

2. melt 

=>여러 개의 컬럼의 데이터를 합쳐서 하나의 컬럼으로 만드는 것

=>데이터프레임과 id_vars매개변수에 합치고자 하는 컬럼 이름의 list를 대입하면 됩니다.

melt

#2개의 컬럼을 합쳐서 1개로 만들기

#남겨두고자 하는 컬럼의 list id_vars에 대입하면

#나머지 컬럼을 합쳐서 컬럼의 이름은 variable

#값은 value에 설정합니다.

print(data)

print(pd.melt(data, id_vars=['prd_3','prd_4']))

 

print(pd.melt(data, id_vars=['prd_3']))

 

3.crosstab

=>행과 열을 기준으로 빈도를 세어서 테이블을 만들어주는 함수

=>교차분석 할 때 이용 ~ 도수분포표(frequency table)를 만들어준느 기능

=>함수에  행 이름과 열 이름을 설정

=>머신러닝 결과 등을 타날 때 자주 이용

오른 것을 오른것 얼마나 했느냐? 정확도 출력해주느

 

 

#도수분포표 -CRASSTAB

data = pd.DataFrame({'id':['id1','id1','id1','id2','id2','id2'],

                     'fac_1':['a','a','a','b','b','b'],

                     'fac_2':['c','c','c','c','d','d']})

   

print(pd.crosstab(data['fac_1'],data['fac_2']))

 

 

a이고 c인것 3d이고 a인것 0

b이고 c인것 1d이고 b인것 2

그룹별로 계산 하면 된다.

 

 

 

#도수분포표 -CRASSTAB

data = pd.DataFrame({'id':['id1','id1','id1','id2','id2','id2'],

                     'fac_1':['a','a','a','b','b','b'],

                     'fac_2':['c','c','c','c','d','d']})

   

print(pd.crosstab(data['fac_1'],data['fac_2']))

 

#비율로 출력하기

print(pd.crosstab(data['fac_1'],data['fac_2'],normalize = True))

# 3/6 1/6 0/6 2/6

 

#잔차의 합으로 평가하는 것도 있고 그룹별로 하는 것도 있다.

#머신러닝에서는 잔차로 한다. 회귀분석에서 한다.

 

정확도

잔차(error) -> 회귀에서 사용  예측값에서 실제 값을 뺀것

분류에서는 아래 같은 식으로 계산한다.

분류는 표보고 판단하는 것이 중요하다.

 

 

비가 오는 날 얼마 안되고 비가 오지 않는 날이 많다. 그래서 비율이 달라서 assembling등 해야 한다.

 

인구는 적지만 젊은 분이 많으면 소멸이 안될 수 있다.

 

 

rpa ->자동화 software만드는 것  공장 같은데 가면 자동화 하는 것

자동화 프로그램 사용하는 원인은 스마트 팩토리

 

 

보통은 메크로이다.

 

 

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-8  (0) 2020.11.14
데이터분석-7  (0) 2020.11.11
데이터분석-6  (0) 2020.11.10
데이터분석-5  (0) 2020.11.09
데이터분석-4  (0) 2020.11.08
반응형

**일반적인 python이나 anaconda를 이용해서 설치한 파이썬 -C로 만들어진 PYTHON

=>C언어로만든 라이브러리를 파이썬에서 사용할 수 있음

=>C언어는 소스코드를 가지고 실행 파일을 만들어서 배포

실행 파일을 만들 때 운영체제의 start up코드가 포함되어야 합니다.

실행되는 프로그램이 운영체제마다 다릅니다.

=>windows에서 실행되는 c언어는 ms-c이고 이 언어로 프로그램을 만드느 대표적인 idevisual c++ 이고 이 visual c++로 만들어진 프고르램을 실행시키기 위해서 재배포 패키지나 build tool이 설치되어 있어야 합니다.

 

**windows애서 python t실행시 라이브러리가 설치되지 않는데

visual c++ 14.0이 설치되어 있어야 하는데 설치되어 잇지 않다는 에러 메시지가 출력되는 경우

-visual studio 2015 재배포 패키지 설치 : 설치해도 잘 안됨

-visual studio 2015 build tools 설치 : 설치해도 잘 안됨

-visual studio 최신 버전 설치 : visual studio community버전 다운로드

 

 

ar . vr 게임 등 관심있으면 unity

mmo rpg ->언니얼

microsoft vr tool -> 테이블 그래는 것 자동으로 하는 것

 

 

 

데이터 적을 때 는 오차 , 정밀도 , 재현울 , F1점수 roc 곡선 등

 

 

 

** 불균형한(개수가 다른 경우) 클래스의 데이터를 가지고 분석을 해야 하는 경우

=>샘플 자체의 개수가 작을 떄는 자료를 더 수집하는 것이 가장 좋은 방법

=>데이터 를 수집하는 것이 가능하지 않을 때는 데이터에 가중치를 적용해서 사용- 분류 알고리즘의 매개변수 중에서 weight가 있으면 이 매개변수가 데이터에 가중치를 적용할 수 있는 매개변수 입니다.

=>개수가 작은 데이터의 개수를 강제로 늘리거나 개수가 많은 데이터의 개수를 줄이는 업샘플링이나 다운 샘플링을 해서 알고리즘에 적용

=>평가지표를 다양하게 선택 - 정확도 대신에 재현율이나 F1 통계량 등을 이용

정확도 , 재현율 등 .. 어느 하나 선택할 때는 결과가 외곡 될 수 있다.

정확도 , 재현율 ,F1통계량 결정 계수 등  정확하게 뭘 의미하는 지 알아야 한다.

분석은 어렵지 않다.그 결과를 판정하는 데 어렵고 뭐하는지 알아야 한다.

 

 

import numpy as np

import pandas as pd

 

#0 10개이고 1 90개 인 ndarray생성

list1 =[]

for i in range(0,10,1):

    list1.append(0)

 

list2 =[]

for i in range(0,90,1):

    list2.append(1)

   

#2개의 list를 가지고 하나이 array생성

target = np.array(list1+ list2)

#list더하기 하면 결합이고

#분석은 더하기 하면 더하기 이다.

print(target)

 

#분류 알고리즘에 위의 데이터를 이용하는 경우

#0: 10% 1 : 90%

from sklearn.ensemble import RandomForestClassifier

#데이터의 비율이 헌저하게 다르기 때문에 가중치 설정

weights = {0:0.9, 1:0.1}

#비율은 반대로 쓴다. 10%, 90%

#0.9 = .9

rfc = RandomForestClassifier(class_weight = weights)

print(rfc)

 

#assemble하고 down는 같이 하면 안된다.

 

#가중치를 직접 설정하지 않고 분류기에게 판단하도록 해주는 옵션

rfc = RandomForestClassifier(class_weight='balanced')

print(rfc)

 

#샘플링 비율 조건

#np.where(target == 0)

#target행렬에서 값이 0인 데이터의 행번호를 리턴

#(행번호행렬, 자료형)으로 결과를 리턴

#행번호행렬만 가져오기 위해서 [0]을 추가

class0 = np.where(target == 0)[0]

class1 = np.where(target == 1)[0]

print(len(class0))

print(len(class1))

 

#target 1인 데이터에서 target 0인 데이터만큼 다운 샘플링을 해서

#새로운 데이터 셋을 생성

#class1에서 class0의 데이터 개수 만큼 비복원 추출 (나온것은 제거)

#assembling랄 때는 복원 추축

downsample = np.random.choice(class1, size = len(class0) , replace= False)

result = np.hstack((target[class0], target[downsample]))

#0개에서는 90개 만들 수 없다.

#downsample = np.random.choice(class0, size = len(class1) , replace= True)

#result = np.hstack((target[class1], target[downsample]))

print(result)

 

** 다변량 분석에서 데이터의 상대적 크기 문제

=>다변량 분석 - 2개이상의 컬럼의 데이터를 가지고 분석

=>하나의 컬럼의 데이터는 값의 범위가 0-100이고 다른 컬럼의 데이터는 값이 범이가 0-1이라면 이 경우 2개의 데이터를 가지고 다변량 분석을 하게 되면 첫번째 컬럼의 영향을 받게 될 수 있습니다.

이런 경우에는 값의 범위를 일치시켜 주는 것이 좋습니다.

=>값의 범위는 같은데 분포가 다른 경우에도 분포를 기준으로 값을 조정할 필요가 있습니다.

최대값으로 나누거나 최대값 - 최소값을 분모로하고 해당값 - 최소값을 분자로 해서 값을 조정

=>이러한 값의 조정을 scalling이라고 합니다.

0-1 사이나 -1~1사이로 조정합니다.

더 큰 값으로 가능하지만 머신러닝 모델에서는 값으 크기가 커지면 정확도가 떨어집니다.

 

 

1.표준화

=>모든 값들의 표준 값을 정해서 그 값을 기준으로 차이를 구해서 비교하는 방법

1)표준값: (데이터- 평균) /표준편차 -표준 값의 평균은 50 (사람한테 줄 때 )

2)편차값: 표준값 * 10 + 50 -위의 숫자보다 큰  숫자로 변환

 

#표준화

#student.csv파일의 내용을 가져오기

#index로 이름을 설정

import os

print(os.getcwd())

#utf8이 아니다.

data = pd.read_csv('./Desktop/data/student.csv', index_col ='이름',encoding = 'cp949')

print(data)

 

#그래프에 한글을 출력하기 위한 설정

import matplotlib.pyplot as plt

import platform

from matplotlib import font_manager, rc

#매킨토시의 경우

if platform.system() == 'Darwin':

    rc('font', family='AppleGothic')

#윈도우의 경우

elif platform.system() == 'Windows':

    font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()

    rc('font', family=font_name)

 

#인덱스를 기준으로 해서 막대 그래프 그리기

data.plot(kind='bar')

 

#표준값 - 작업

#평균을 표준 편차로 나누어서 계산

#각과목의 평균과 표준편차 구하기

kormean, korstd = data['국어'].mean(), data['국어'].std()

engmean, engstd = data['영어'].mean(), data['영어'].std()

matmean, matstd = data['수학'].mean(), data['수학'].std()

 

 

#표쥰값 구하기 -(자신의 값 - 평균 )/ 표준편차

#내가 0.0이면 중간

#편차값이 1.0이면 항상 상하위 15%

#2.0 상하위 1.1%

#음수가 있을 수 있다.

data['국어표준값'] = (data['국어']- kormean )/korstd

data['영어표준값'] = (data['영어']- engmean )/engstd

data['수학표준값'] = (data['수학']- matmean )/matstd

print(data[['국어표준값','영어표준값','수학표준값']])

#박지영은 국어는 영어보다 잘 한다.  수학은 못한다.

 

#음수를 잘 안보이기 때문에 우리가 자주사용하는 숫자로 변한다.

 

#표준값은 비교가 가능하기는 하지만 사람이 알아보기 불편

#표준값 * 10 + 50 을 해서 편차값을 만들어서 보고서를 만듬

 

 

data['국어표준값'] = data['국어표준값']* 10 + 50

data['영어표준값'] = data['영어표준값']* 10 + 50

data['수학표준값'] = data['수학표준값']* 10 + 50

print(data[['국어표준값','영어표준값','수학표준값']])

 

 

data[['국어표준값','영어표준값','수학표준값']].plot(kind='bar')

 

 

#최대값으로 나누어서 표준화  - 정규화로 많이 불리운다.

#자신의 값 - 최소값/ 최대값 - 최소값으로 하기도 함

#0.0 ~ 1.0 사이로 있다.

data['국어정규화1']  = data['국어'] / data['국어'].max()

data['국어정규화2']  =( data['국어']- data['국어'].min()) / (data['국어'].max()-data['국어'].min())

 

 

 

2.sklearn의 정규화

1)StandartScaler: 평균이 0이고 표준편차가 1이 되도록 변환

(백터- 평균) / 표준편차

주로 주성분분석에서 많이 이용

음수가 잇을 가능성 있다.

 

2)MinMaxScaler:  최대값이 1 최소값이 0 이 되도록 변환

(백터 - 최소값) /(최대값 - 최소값)

신경망에서 주로 이용 (cnn, rnn)

 

 

 

3)RobustScaler: 중앙값이 0 IQR(4분위수 )를 이용하는 방식

(백터 - 중간값) /( 75%- 255)

=>앞의 방식들은 outlier(이상치)에 영향을 많이 받습니다.

=>데이터의 분포가 불균형이거나 극단치가 존재하는 경우에 주로 이용

 

 

 

0 1 2 3 4 5 6 100->이상치가 있을 수 있다. 1),2) OUTLIER

그래서 75%의 값 25%의 값

그래서 최대값 최소값 영향을 받지않는다.

 

 

4)QuantileTransformer:데어터를 1000개의 분위로 나눈 후 0-1 사이에 고르게 분포시키는 방식

=>outlier 의 영향을 적게 받기 위해서 사용

 

 

0 ~ 100 사이의 데이터인데

17 27 25 16 41 33 27 -> 이렇게 된것은 표준화 하면 안좋다. 데이터의 분포가 작아서

표준화 하면 꼭 고려해야 할 두가지 데이터 분포 , outlier

아주 큰 값 있으면 하나 버리기

데이터 분포가 완전히 쏠려져 있을 경우에는 정규화를 하지 않는다.

 

변화 하면 fit_transform

모델에 적용하면 fit 이다.

표준화는 값만 가지고 해야 한다.

 

 

 

#표준화 작업

#sklearn을 이용한 scailing

from sklearn import preprocessing

 

#StandardScaler

#StandardScaler - 평균은 0 표준편차는 1이 되도록 표준화

scaler = preprocessing.StandardScaler()

#국어 점수만 이용하는 경우 data['국어'] 가 아닌고 data[['국어']]

#머신러닝의 데이터들은 행렬을 이용하는데 data['국어']하게 되면 컬럼이름이

#1개라서 하나의 열로 리턴되서 1차원 데이터가 됨

#data[['국어']] 하게 되면 list를 대입하기 때문에 datafrmae으로 리턴

result = scaler.fit_transform(data[['국어']].values)

print(result) #표준값 구한 것

print(np.mean(result)) #평균이 0에 가까워진다. 1.2335811384723961e-17 ->거의 0이다 e 17

print(np.std(result)) # 값이 1에 가까워진다.

 

 

 

#MinMaxScaler

#MinMaxScaler - 음수가 안나온다. 최대값 최소값 이용해서 하기 때문에

scaler = preprocessing.MinMaxScaler()

result = scaler.fit_transform(data[['국어']].values)

print(result)

print(np.mean(result))

print(np.std(result))

 

 

#RobustScaler

#RobustScaler - 음수가 나온다.  이상치 값이 있을 때 해결하기 위한 것

scaler = preprocessing.RobustScaler()

result = scaler.fit_transform(data[['국어']].values)

print(result)

print(np.mean(result))

print(np.std(result))

 

 

#QuantileTransformer

#QuantileTransformer - 음수가 나오지 않는다. 데어터 분포를 고려해야 한다. 데이터가 적으면 안된다.

scaler = preprocessing.QuantileTransformer()

result = scaler.fit_transform(data[['국어']].values)

print(result)

print(np.mean(result))

print(np.std(result))

 

 

**정규화

=>값의 범위를 0 -1 사이의 데이터로 변환

=>표쥰화는 일정한 범위 내로 데이터를 변환하는 것이고 정규화는 0-1 사이로 해야 합니다.

=>Normalizer클래스를 이용해서 transform메소드에 데이터를 대입하면 됩니다.

이 때 norm매개변수에 옵션을 설정할 수 있는데 l1, l2, max등의 값을 설정할 수 있습니다.

max는 최대값으로 나누는 방식

l1l2는 거리 계산 방식

l1-  맨하턴 거리를 이용하고 l2는 유클리드 거리를 이용

맨하탄 거리  -> 장애물이 있을 경우에는 직접 못간다.'

이 두개 크기 자체는 별로 차이 안나는데 계산 방식이 다르다.

게임 shoting게임 할 때 사용한다.

A B 거리 계산 할때 거리 계산한다. 거리가 멀면 시간이 오래 걸린다.

ping할 때  ttl ->라우터의 계수

 

 

 

 

#이차원 행렬을 생성

matrix = data[['국어','영어']].values

print(matrix)

 

 

matrix = np.array([[30,20],[10,30],[30,40]])

print(matrix)

 

from sklearn import preprocessing

 

#l1-  맨하턴 거리를 이용하고 l2는 유클리드 거리를 이용

#정규화 객체 생성 - 유클리디안 거리를 사용

norm = preprocessing.Normalizer(norm = 'l2')

print(norm.transform(matrix))

# 30 /  302+ 402승 에 root => 30 / 50

 

#합을 가지고 나누느 방식

norm = preprocessing.Normalizer(norm = 'l1')

print(norm.transform(matrix))

# 30 / 50  20/50

 

#큰값을 가지고 나누는 방식

norm = preprocessing.Normalizer(norm = 'max')

print(norm.transform(matrix))

#30/40  40/40

 

 

** 다항과 교차항 특성

=>기존 데이터에 데이터들을 곱하고 제곱을 해서 데이터를 추가하는 것

=>특성과 타겟 사이에 비선형 관계과 존재할 때 사용하는 방식

=>비선형 관계는 2개의 관계가 직선의 형태가 아니고 곡선의 형태인것

=>각 특성이 다른 특성에 영향을 줄 때 각 특성을 곱할 교차형을 가지고 인코딩

=>다변량 분석(2개 이상의 컬럼을 가지고 분석) 을 할 때 2개의 컬럼 사이에 상관관계가 있는 경우가 있는데 이런 경우 2개의 컬럼 모두를 가지고 분석을 하게 되면 다중공선성 문제가 발생할 수 있습니다.

어떤 컬럼의 값을 알면 다른 컬럼의 값을 예측할 수 있는 경우 발생할 수 있는 문제입니다.

이런 경우에는 2개의 컬럼을 1개의 컬럼으로 변환하는 작업을 해야 하는데 (차원축소) 이런 경우 더하거나 거나 제곱해서 새로운 값을 만들어냅니다ㅣ.

 

 

 

=>PolynomialFeatures 클래스를 이용하는데 몇 차 항 까지 생성할 것인지 degree에 설정

첫번 떄 데이터로 1을 추가할 지 여부를 include_bias에 설정

=>연산식의 순서는 get_features_names메소드를 이용해서 확인 가능

 

[ 1 , 2 ]            degree  = 2 제곱 까지 만 한다.

[1 , 2 , 1의 제곱 1, 1 * 2 = 2, 2의 제곱 = 4 ]

2를 적용하면 5개 데이터를 만든다.

[4,7]

[4, 7, 16, 28, 49 ]

 

degree = 3

[4, 7, 16, 28, 49 , 64, .......]

[[  4.   7.  16.  28.  49.  64. 112. 196. 343.]]

차원 축소 할 때 데이터를 만들어 낸다.

42* 7 ,

28 * 6  * 7 = 196

 

 

 

 

 

matrix = np.array([[30,20],[10,30],[30,40]])

print(matrix)

 

#다항과 교차항을 만들어주는 객체를 생성

#include_bias = False 첫번 때 0을 안 집어 여겠다.

# degree = 2: 제곱한 것 까지 생성

polynomial  = preprocessing.PolynomialFeatures(degree = 2, include_bias = False)

result = polynomial.fit_transform(matrix)

print(result )

 

matrix = np.array([[4,7]])

print(matrix)

 

polynomial  = preprocessing.PolynomialFeatures(degree = 3, include_bias = False)

result = polynomial.fit_transform(matrix)

print(result )

 

**표준화나 정규화는 직접 하는 경우가 많지만 다항식을 만드는 것은 머신러닝 알고리즘에서 자체적으로 처리하는 경우가 많음

 

**특성 변환

=>데이터에 동일한 함수를 적용해서 다른 데이터로 직접 변환하는 것

=>pandas에서는 apply메소드를 이용하고 sklean에서는 preprocessing.FunctionTransformerColumnTransformer클래스를 이용ㅇ

=>FunctionTransformer는 모든 열에 동일한 함수를 적용하고  ColumnTransformer는 서로 다른 함수를 적용할 수 있습니다.

객체를 생성할 때 적용할 함수를 설정해서 만들고 transform 메소드에 데이터를 대입하면 됩니다.

 

import numpy as np

from sklearn import preprocessing

#함수 적용하기

matrix = np.array([[100,200],[300,150]])

print(matrix)

#위 데이터를 정수로 변환하기

#100을 결합하기

def intconvert(x):

    return x + 100

#행렬을 변환해서 리턴해준다.

transformer = preprocessing.FunctionTransformer(intconvert)

result = transformer.fit_transform(matrix)

print(result)

print(data['국어'])

print(data['국어'].apply(intconvert))

 

 

**Outlier 감지

=>Outlier 이상치나 극단치 , 일반적인 데이터의 범위를 넘어선 값

1.z점수를 이용하는 방법 : 중앙값을 기준으로 표준편차가 3 또는 -3 범위의 바깥똑에 있는 데이터를 Outlier 로 간주

2.z점수의 보정 :z 점수는 데이터가 12개 이하이면 감지를 못함

넘 작으면 표준편차가 잡지 못하기 때문에

편차의 범위를 3.5로 늘리고 0.6745를 곱한 값을 이용

3.IOR(3사분위수 - 1사 분위수)이용: 1사분위수 (25%)보다 1.5 IQR 작은 값이나 3사분위수(75%) 보다 1.5IQR 큰 데이터를 outlier 로 간주

 

 

1,2,3 10004

10010/4

 

1,2,3 10004 , 10004 => 이 경우에는 outlier가 알될수 도 있다. 많이 적으면 outlier가 나올 수 있다.

 

 

import numpy as np

import pandas as pd

 

 

#array를 입력받아서 z 점수(표준편차의 3) 밖에 있는 데이터를 리턴해주는 함수

def z_score_outlier(ar):

    threshold  = 3

    #평균 가져오기

    meandata = np.mean(ar)

    stdevdata = np.std(ar)

    #stdevdata for y in ar의 요소를 y에 하나씩 대입하고 앞에 수식을 적용해서 결과를 가지고

    #다시 list를 만드는 것

    z_scores  = [(y-meandata) / stdevdata for y in ar]

    return np.where(np.abs(z_scores) > threshold)

 

#샘플 데이터 생성

#features = np.array([[10,30,13,-20,4,12],[20000,3,5,4,2,1]])

#features = np.array([[10,30,1003,-20,4,12],[2,30,5,4,2,1]])

    #(array([0], dtype=int64), array([2], dtype=int64)) 0 2

#features = np.array([[10,30,13,-20,4,12],[2,9,5,4,2,10]])#없다.

features = np.array([[10,30,13,-2000000,4, 12, 10,30, 13, 11, 4, 12,10,30,13,20,4,2,4,2],

                     [2,9,5,4,2,2000000,10,30,13,20,4,12,10,30,13,20,4,2,4,2]])

#(array([0, 1], dtype=int64), array([3, 5], dtype=int64))

    #0번에 3 1번에 5

 

result = z_score_outlier(features)

print(result)

 

 

#z score 보정  -범위를 3.5배로 널리고 표준편차 0.6875를 곱해줍니다.

def modify_z_score_outlier(ar):

    threshold  = 3.5

    #평균 가져오기

    meandata = np.mean(ar)

    stdevdata = np.std(ar)

    #stdevdata for y in ar의 요소를 y에 하나씩 대입하고 앞에 수식을 적용해서 결과를 가지고

    #다시 list를 만드는 것

    z_scores  = [0.6875 * (y-meandata) / stdevdata for y in ar]

    return np.where(np.abs(z_scores) > threshold)

 

#샘플 데이터 생성

features = np.array([[10,30,13,-20,4, 12, 10,30, 13, 11, 4, 12,10,30,13,20,4,2,4,2],

                     [2,9,5,4,2,2000000,10,30,13,20,4,12,10,30,13,20,4,2,4,2]])

#(array([0, 1], dtype=int64), array([3, 5], dtype=int64))

 

result = modify_z_score_outlier(features)

print(result)

 

 

#iqr이용 : 3 사분위수 - 1사분위의 +- 1.5 배이상 차이나면 이상치로 간주

def iqr_outlier(ar):

    #25% 75%의 값 찾기

    q1 ,q3 = np.percentile(ar,[25,75])

    #iqr값 찾기

    iqr = q3- q1

    #25% 값과 .5 iqr보다 작은 값 찾기

    lower = q1- iqr*1.5

    upper = q3 + iqr* 1.5

    return np.where( (ar > upper )| (ar < lower))

 

#샘플 데이터 생성

features = np.array([[10,30,13,-20,4, 12, 10,30, 13, 11, 4, 12,10,30,13,20,4,2,4,2],

                     [2,9,5,4,2,2000000,10,30,13,20,4,12,10,30,13,20,4,2,4,2]])

 

 

result = iqr_outlier(features)

print(result)

 

 

**Outlier처리

1.제거

=>설문조사를 했는데 이상한 데이터가 입력된 것 같은 경우

=>분석 목적에 맞지 않는 데이터인 경우

 

 

2.이상한 데이터로 표현해두고 특성의 하나로 간주

이상한 상황을 없에면 안되고 특수한 상황으로 해야 한다.

 

3. outlier의 영향이 줄어돌도록 특성을 변환 - 값의 범위를 줄임(표준화, 정규화 등)

=> 표준화 할 때는 RobustScalar를 이용하는 것이 좋음

 

 

house = pd.DataFrame()

house['price'] = [100000,200000,150000,10000000]

house['rooms'] = [1,3,2,100]

house['square'] = [11,23, 16, 1200]

print(house)

 

 

#이상한 데이터 제거 : 방이 5개 이상 제거

print(house[house['rooms'] < 6])

#이상한 데이터를 별도로 표시

house['outlier'] = np.where(house['rooms'] < 6 , 0,1)

print(house)

 

 

#값의 범위 줄이기 -np.log는 자연 로그를 계산

house['log'] = [np.log(x) for x in house['rooms']]

print(house)

 

** 시계열 데이터

=>날짜 및 시간에 관련된 데이터

1.pandas의 시계열 자료형

=>datatime64 : 부등호를 이용해서 크기비교를 할 수 있고 - 를 이용해서 뺄셈을 할 수 있음

=>Period:두개의 날 짜 사이의 간격을 나타내기 위한 자료형

=>시계열 자료형을 별도로 구성하는 이유는 일정한 패턴을 만들기 쉽도록 하기 위해서

 

 

 

2. 생성

=>문자열 데이터를 시계열로 변경 : pandas.to_datetime()이용

날짜 형식의 문자열과 format매개변수에 날짜 형식을 대입

 

 

#문자 데이터를 pandas의 시계열 데이터로 만들기

df = pd.read_csv('./Desktop/data/stock-data.csv')

print(df)

#자료형 확인

print(df.info())

#Date 컬럼의 값을 시계열로 변경해서 추가

df['newDate'] = pd.to_datetime(df['Date'])

print(df.info())

 

 

#위와 같은 데이터프레임에서는

#날짜를 index로 설정하는 경우가 많습니다.

df.set_index('newDate',inplace = True)

df.drop('Date',axis = 1 , inplace = True)

print(df.head())

 

 

 

 

 

3.Period 간격을 나타낸다.

=>pandas.to_period 함수를 이용해서 datatimeperiod로 생성

freq 옵션에 기준이 되는 기간을 설정

=>freq옵션

 

D: 1

W: 1

M 1개월 (월말 기준)

MS: 1개월 (월초 기준)

Q: 분기말

QS :  분기초

A:연말

AS:

B: 휴일제외

H,T,S,L,U,N: 시간 , , , 밀리초 , 마이코로초 , 나노초

 

 

#일정한 간격을 갖는 날짜 만들기

dates = ['2017-03-01','2017-06-01','2019-12-01']

print(dates)

#날짜로 변경

pddates = pd.to_datetime(dates)

print(pddates)# DatetimeIndex로 바꿔졌다.

 

 

#Period로 변환

pdperiod  = pddates.to_period(freq = 'D')

print(pdperiod)

#PeriodIndex(['2017-03-01', '2017-06-01', '2019-12-01'], dtype='period[D]', freq='D')

 

pdperiod  = pddates.to_period(freq = 'M')

print(pdperiod)

#PeriodIndex(['2017-03', '2017-06', '2019-12'], dtype='period[M]', freq='M')

 

pdperiod  = pddates.to_period(freq = 'Q')

print(pdperiod)

 

pdperiod  = pddates.to_period(freq = 'A')

print(pdperiod)

 

 

 

5.date_range()

=>일정한 간격을 소유한 날짜 데이터의 집합을 생성

=>매개변수

start: 시작 날짜

end: 종료 날짜

periods: 생성할 날짜 개수

freq: 간격

tx: 시간대

 

 

 

#일정한 간격을 가진 날짜 데이터 생성

ts_ms = pd.date_range(start = '2018-01-01',end = None, periods = 12, freq = 'M')

print(ts_ms)

 

ts_ms = pd.date_range(start = '2018-01-01',end = None, periods = 12, freq = 'D')

print(ts_ms)

 

#2H ->2시간씩

ts_ms = pd.date_range(start = '2018-01-01',end = None, periods = 12, freq = '2H')

print(ts_ms)

 

 

6.날짜 데이터에서 필요한 부분 추출하기

=>dt.year, dt.month, dt.day...

=>요일은  dt.weekday_name은 문자열로 dt.weekday하면 숫자로 리턴 (월요일이 0)

화면에 출력할 때는 문자열로 하고 머신러닝을 사용할 때는 숫자로 리턴 받습니다.

ts_year = df['newDate'].dt.year

print(ts_year)

 

df['year'] = df['newDate'].dt.year

print(df['year'])

 

 

7.python에서는 날짜는 datetime패키지의 datetime으로 제공

=>날짜 형식의 문자열을 가지고 날짜 형식의 데이터를 생성

 

 

8.shift함수를 이용하면 기존 날짜를 이동시키는 것이 가능

=>freq 매개변수에 간격을 설정할 수 있습니다.

 

 

#python의날짜 패키지

from datetime import datetime

dates = [datetime(2017,1,1),datetime(2017,1,4),datetime(2017,1,7)]

ts = pd.Series(np.random.randn(3) , index = dates)

print(ts)

print(ts.shift()) #데이터를 하나씩 민다. 아래쪽으로

print(ts.shift(1)) #데이터를 하나씩 민다. 아래쪽으로

print(ts.shift(-1)) #데이터를 하나씩 반대로 민다. 위로

 

 

9.resampling

=>시계열의 빈도를 변환하는 것

=>상위 빈도의 데이터를 하위 빈도의 데이터로 변환하는 것을 다운 샘플링이라고 하고 반대의 과정을 asampling이라고 한다.

=>resampling(freq, how, fill, method, closed, label , king)

freq: 리샘플링 빈도(M,Q, A)

how: 집계함수를 지정하는 것으로 기본은 mean(평균을 구한다.) first, last, max, median ,min

데이터가 있으면  합계등 골라내다.

fill_method: 업 샘플링할 때 데이터를 채우늠 옵션이므로 기본은 None인데 fill이나 bfill을 설정해서 이전값이나 이후값으로 채울 수 있음

closed: 다운 샘플링을 할 때 왼쪽과 오른쪽 어느쪽을 호팜시킬지 설정

label: 다운 샘플링을 할 때 레이블을 왼쪽 또는 오른쪽을 사용할 것인지 여부

 

 

 

#일정한 조건으로 집계

ran = pd.date_range('11/3/2010',periods = 20, freq ='T')

print(ran)

 

ts = pd.Series(np.arange(20),index = ran)

print(ts)

#5개씩 하면 5분단위로 할 수 있다.

#실데이터는 다르다. 10분마다

#label 0분이나 4분이나 할 것이다

 

#5분 단위로 합게

print(ts.resample('5T').sum())

 

print(ts.resample('5T').mean())

 

 

10.날짜 데이터가 데이터프레임에 존재하는 경우 날짜 데이터를 인덱스로 설정하면 특정 시간단위로 집계를 하는 것이 쉬워집니다.

 

**이동시간 윈도우

=>통계적 수치를 계산을 할 때 최근의 데이터에 가중치를 부여해야 한다라는 개념

평균을 구할 때 데이터 전체의 평균을 구하는 것 보다는 최근의 데이터 몇 개의 평균을 구하는 것이 미래를 예축할 때는 더 잘 맞을 가능성이 높다.

이전 데이터와 최근의 데이터를 같이 사용할 거라면 최근의 데이터에 가중치를 부여하는 것이 미래를 예측할 때는 더 잘 맞을 가능성이 높다.

 

 

1.rolling 함수

=>단순 이동 평균을 계산해주는 함수

=>winodw 매개변수에 데이터 개수를 설정하면 데이터 개수 단위로 연산을 수행

 

 

2.ewm함수

=>지수 이동 평균을 계산해주는 함수

=>지수 이동 평균은 최근의 데이터에 가중치를 부여하는 방식의 평균

주식 데이터는 이 평균을 사용합니다.

=>기간(span)을 설정하면 아래 수식으로 평균

데이터가 3개인 경우

x1, x2, x3(가장 최근 데이터)

1-span을 알파라고 합니다.

 

x3+(1-(1-span)) x2 +(1-(1-span) )제곱 x3  / 1 + (1-알파) +(1-알파)제곱

숫자를 줄인다.

 

 

500 2000 2300 2700

3

2000 +2500+2700 / 3

반영율을 조정한다.

 2500 + (1-1/3) * 2000 + (1-1/3)2 의 제곱 * 2000

 

지수 이용 평균

어느 속도를 기준해서 낮아진다. 불량율 , 숙련도 주식등에서 많이 사용한다.

 

시간에 따라 변경되는

데이터를 가지고 계속 할 때는 최근의 데이터

가중치를 부여해야 한다.

에이징 커브 -전년도 데이터를 해서 하는 것

최근에 얼마 사용했는지에 따라 가중치를 준다.

휴대폰이 2100시간 최근에는 2시간

 

 

python문법 ->데이터 가공 numpy pandas ->

sklearn

회귀 군집 알고리즘 등

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-8  (0) 2020.11.14
데이터분석-8  (0) 2020.11.12
데이터분석-6  (0) 2020.11.10
데이터분석-5  (0) 2020.11.09
데이터분석-4  (0) 2020.11.08
반응형

**단계구분도(choropleth)

=>지도에 색상을 추가해서 시각화하는 것

=>데이터와 영역의 경계를 나타내는 json파일이 필요

=>우리나라 영역의 경계는  southkorea-maps에서 확인이 가능

=>단계구분도 각 영역의 크기를 왜곡해서 모두 동일한 크기로 보여주도록 하는 것은 엑셀이나 svn를 이용해서 작업합니다.

=>우리나라 경계 관련 데이터 : http://github.com/southkorea/southkorea-maps

 

southkorea/southkorea-maps

South Korea administrative divisions in ESRI Shapefile, GeoJSON and TopoJSON formats. - southkorea/southkorea-maps

github.com

 

#작업 디렉토리 확인

import os

print(os.getcwd())

 

##경기도인구데이터.xlsx 파일과 경기도행정구역경계.json

#파일을 이용한 단계구분도 만들기

import pandas as pd

 

#데이터 읽기

#index_col->인덱스로 된다;

df = pd.read_excel('./Desktop/data/경기도인구데이터.xlsx',index_col ='구분')

#인덱스에 str함수를 적용해서 문자열로 자료형을 변경

#인덱스를 숫자 자료형으로 만들면 인덱스가 행의 위치인지

#인덱스인지 혼동이 올수 있습니다.

#loc[인덱스],iloc[행의위치]

#컬럼의 이름들도 문자로 만드는 것이 좋습니다.

#컬럼의 접근: 데이터프레임[컬럼이름], 데이터프레임.컬럼이름

#컬럼의 이름이 숫자이면 데이터프레임.컬럼이름은 사용할 수 없습니다.

#이름은 문자열로 만드는 것이 좋다.

 

#컬럼의 이름들을 문자열로 변경

df.columns = df.columns.map(str)#데이터 자체는 특별한 변화가 없다.

print(df.head())

 

 

#json파일 읽기

import json

 

#UnicodeDecodeError: 'cp949' codec can't decode byte 0xec in position 149: illegal multibyte sequence

#cp949 utf-8로 변경할 수 없다.

#파일의 경우는 open 함수에 파일의 경로를 대입해야하고 url이면 바로 입력해도 됩니다.

geo_data = json.load(open('./Desktop/data/경기도행정구역경계.json',encoding='utf-8-sig'))

print(geo_data)

 

 

#지도 만들기 -기본 패키지가 이님 그래서 설치를 해야 한다.

import folium

#zoom_start 작으면 축수 한다.

g_map = folium.Map(location=[37.550,126.9800],zoom_start=9)

 

 

 

#단계구분도 만들기

#fill_opacity 1.0은 안부이고 0.0은 투명이 된다. 찐하게 하면 도시이름이 안보인다.

#line_opacity 경계선

#threshold_scale 숫자구분하기 위한 숫자 리스트

#key_on json파일에서 각 영역의 이름을 나타내는 프로퍼티를 지정한다 .데이터  feature.properties.name 만드는 사람이 정한다.

#YlOrRd . YlGn

folium.Choropleth(geo_data=geo_data, data=df['2017'] , fill_color= 'YlGn',fill_opacity=0.5,

                  line_opacity=0.3,

                  threshold_scale=[10000,100000,300000,500000,700000],

                  key_on='feature.properties.name').add_to(g_map)

 

g_map.save('g_map.html')

 

**pandas의 시각화

=>pandasmatplotlib의 기능 일부분을 소유

=>Dataframe이나 Series객체를 가지고 plot이라는 메소드를 호출하면 그래프를 그릴 수 있습니다.

=>kind 옵션에 그래프 종류를 설정하면 됩니다.

line:선그래프

bar: 수직 막대 그래프

barh:수직 막대 그래프

hist: 히스트그램

box:상자그래프

kde: 커널 밀드 그래프

area: 면적 그래프

pie: 원 그래프

scatter: 산포도 - 산점도

hexbin:고밀도 산점도 그래프

=>세밀한 옵션 조정이 안되서 데이터 탐색을 할 때는 사용하는 경우가 있기는 하지만 시각화하는 용도로는 잘 사용하지 않음

 

 

데이터 없고 + 1 =>NaN

add(NaN, 1, fill_value = 0) NaN0으로 바꾼다.

tatanic은 인터넷에서 가져온다. 보안문제 때문에 외부망에서 못 가져온 경우가 종종 있다.

대기업하고 금융은 폐쇄망이다.

 

**데이터 가공

=>패키지가 제공하는 데이터는 load_dataset('데이터이름')을 이용하면 데이터프레임이나 패키지에서 제공하는 별도의 클래스 타입으로 데이터가 다운로드 됩니다.

인터넷이 안되면 데이터를 사용할 수 없습니다.

=>대기업이나 금융기관은 인터넷은 되지만 데이터는 함부로 다운로드 받거나 설치할 수 없도록 설정된 경우가 있습니다.

이런 경우에도 데이터는 다운로드가 안됩니다.

 

 

 

문자열은 object 로 나온다.

object 99%가 문자열이다.

category 범주형 라디오 버튼을 생각하면 된다. 남자/여자

범주형

None ->info()print()안해도 된다. return 값이 None이여서

<class 'pandas.core.frame.DataFrame'>

RangeIndex: 891 entries, 0 to 890

Data columns (total 15 columns):

survived       891 non-null int64

pclass         891 non-null int64

sex            891 non-null object

age            714 non-null float64

sibsp          891 non-null int64

parch          891 non-null int64

fare           891 non-null float64

embarked       889 non-null object

class          891 non-null category

who            891 non-null object

adult_male     891 non-null bool

deck           203 non-null category

embark_town    889 non-null object

alive          891 non-null object

alone          891 non-null bool

dtypes: bool(2), category(2), float64(2), int64(4), object(5)

memory usage: 80.6+ KB

None

 

1.셀의 데이터 수정

=>replace 이용

=>첫번째 매개변수로 원본 데이터를 대입하고 두번째 매개변수로 수정할 데이터를 설정

=>dict 로 원본 데이터와 수정할 데이터를 설정해도 됩니다.

replace(1,2 )=>12로 바꿔진다.

replace({1:2})

=>원본 데이터에 정규식을 사용할 수 있느데 이 경우에는 regex = True를 추가

텍스트 마이닝을 하고자 하는 경우에는 정규식을 학습할 필요가 있습니다.

=>여러 개의 데이터를 수정하고자 하는 경우에는 list로 대입해도 됩니다.

 

 

 

2.결측치 연산

=>결측치: 존재하지 않는 데이터로 파이썬에서는 None이고 numpy에서는 numpy.NaN으로 표현

=>결측치와이 연산 결과는 None입니다.

=>read_csv메소드에는 na_values 옵션을 이용해서 None으로 처리를 list를 대입할 수 있습니다.

 

 

1)Dataframenull관련 메소드

=>isnull(): None데이터인 경우는 True 그렇지 않으면 False

notnull()은 반대

=>dropna():  NaN값을 소유한 행을 제거하고 axis = 1 옵션을 추가하면 열을 제거

how매개볒ㄴ수에  all을 대입하면 모든 데이터가 None경우만 제거

thresh 매개변수에 정수를 대입하면 이 개수보다 많은 None을 가진 경우만 제거

=>fillna():NaN값을 소유한 데이터를 다른 값으로 치환하는 함수

값을 직접 입력할 수 있고 methon매개변수에 ffill등과 같은 값을 설정해서 앞이나 뒤의 값으로 채울 수 있습니다.

 

2)결측치 처리 방식

=>결측치가 많은 열의 경우는 열을 제거합니다.

=>결측치가 아주 많지 않은 경우는 결측치를 가진 행만 제거합니다.

=>결측치를 가진 데이터를 삭제하기 애매한 경우(결측치가 몇개 안되거나 어쩔수 없이 결측치가 발생하는 경우)에는 결측치를 다른 값으로 치환을 합니다.

설문조사

mcar,mar- >지워도 된다.

nmar->누락된 경우가 있어서 함부로 삭제하면 안된다.

 

#수치연산 과 선형대수 그리고 ndarray라는 자료구조를 가진 패키지

import numpy as np

#Series Dataframe이라는 자료구조를 가진 패키지

import pandas as pd

#샘플 데이터와 시각화를 위한 패키지

import seaborn as sns

 

#titanic데이터 가져오기

titanic = sns.load_dataset('titanic')

 

#데이터 탐색

print(titanic.head())

print()

print(titanic.info())

 

 

#NaN이 존재하는 지 확인

#titatnic에서 앞 쪽 10개의 데이터가 NaN을 포함하는 지 확인

print(titanic.head(10).isnull())

 

#titanic에서 NaN을 포함함 행의 개수를 파악

print(titanic.isnull().sum(axis = 0))

print(titanic['age'].isnull().sum(axis = 0))

 

 

#NaN 300개 이산인 열을 제거

#axis = 1 0은 행

#NaN이 넘 많아서 제거

titanic.dropna(thresh = 300, axis = 1 , inplace = True)

print(titanic.info())

 

 

#age 열의값이 NaN인 행을 제거 - 아주 많지 않으면 행을 제거

titanic.dropna(subset=['age'],how='any', axis= 0, inplace = True)

print(titanic.info())

 

다른 값으로 치환하는 경우에는 최빈값(가장 자주 나오는 값),평균, 중간값 등을 사용하는 방식이 있고 머신러닝을 이용해서 가장 비슷한 데이터의 값으로 채우는 방법이 있습니다.

머신러닝을 이용해서 값을 채우는 것이 가장 좋지만 이 방법은 시간이 오래 걸리기 때문에 데이터가 아주 많은 경우는 사용하기가 곤란합니다.

범주형 데이터는 평균, 중간값 사용할 수 없다.

평균, 중간값 숫자 사용한다.외곡값이 있을 수 있다.

 

 

3)결측값 대치

=>사이킷 런의 SimpleImputer클래스를 이용해서 최빈값이나 평균 및 중간값 등으로 채울 수 있습니다.

 

#titanic데이터 다시 가져오기

titanic = sns.load_dataset('titanic')

print(titanic['embarked'][820:830])

 

#직접 NaN값을 다른 값으로 대체

#inplce = True 주면 그냥하고 안주면 return 받아야 한다.

#표 형태의 데이터를 가져온 경우 셀 병합이 된 경우에 사용

titanic['embarked'].fillna(method= 'ffill',inplace = True)

print(titanic['embarked'][820:830])

 

#사이컷 런을 이용해서 결측치 채우기

features = np.array([[100],[200],[300],[500],[40],[np.NaN]])

 

 

#중간 값으로 채우는 imputer생성  200으로 채워진다.

from sklearn.impute import SimpleImputer

imputers = SimpleImputer(strategy = 'median')

 

features_imputed = imputers.fit_transform(features)

print(features_imputed)

 

fancyimpute 설치 도중 아래와 같은 에러가 발생하면 :

Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": https://visualstudio.microsoft.com/downloads/

 

 

c++은 운영체제마다 소스가 다르다.

 

google.com에서 Visual C++ 14.0 재배포 패키지를 검색해서 다운로드 받은 후 설치하고 다시 설치하면 됩니다.

이 에러는 wINDOWS에서만 발생

패키지를 만들 때 Visual C++에서 만들어서 배포를 해서 이런 현상이 발생

 

#KNN(분류) 알고리즘을 이용한 결측치 세우기

#분류 알고리즘 거리를 계산해서 분류하는 것

#fancyimpute 설치를 하고 실행

#KNN을 사용하지 않고 다른 머신러닝의 분류 알고리즘을 사용해도 됩ㄴ디ㅏ.

#존재하는 값이 나올 수 있고 존재하지 않는 값이 나올 수 있다.

from fancyimpute import KNN

features = np.array([[200,300],[300,500],[400,410],[205,np.NaN]])

features_imputed = KNN(k = 5, verbose = 0).fit_transform(features)

print(features_imputed)

삭제후 2015만 있으면 된다. =>오류 난다.

visual studio 설치후 하기

pip install fancyimpute

 

**windows에서 python실행 시 라이브러리가 설치되지 않는데

visual c++ 14.0 이 설치되어 있어야 하는데 설치되어 있지 않다는 에러 메시지가 출력되는 경우

-visual studio 2015 재배포 패키지 설치 안됨

-visual studio 2015 build 설치 잘 안됨

-visual studio 최신 버전 설치

 

xamanin을 가지고 os등 할 수 있다.

유니티 : 게임

c++ c#이다.

 

cloud-> aws

 

 

3. 중복데이터 처리

=>하나의 데이터 셋에서 중복된 데이터가 존재한다면 제거하는 것이 좋다.

동일한 데이터가 여러개 ㅇ존재하면 머신러닝이나 딥러닝을 수행할 때 결과가 왜곡 될수 있다.

=>관련함수

           duplicated():데이터의 중복여부를 리턴해주는 메소드

           drop_duplciated():중복된 데이터 제거

기본은 모든 컬럼의 값이 같은 경우에 제거

subset은 옵션에 컬럼이름의 list를 대입하면 컬럼이름에 해당하는 값들이 같은 경우에 제거

첫번째 데이터를 남기고 나머지 데이터를 삭제한느데 keep 옵션을 이용하면 다른 데이터를 남길 수 도 있습니다.

=>이런 상황은 여러 개의 데이터셋을 하나로 합칠 때 많이 발생합니다.

 

#중복 데이터 처리

df = pd.DataFrame([['차범근','크루이프','차범근'],['대한민국','네덜란드','대한민국']])

df = df.T

print(df)

 

#중복된 데이터 확인

print(df.duplicated())

 

#중복된 데이터 제거

df.drop_duplicates(inplace = True)

print(df)

 

**데이터 표준화

=>여러 곳에서 수집한 데이터들은 단위나 대소문자 구분 또는 약자 활용등으로 인해 바로 사용하기 어려운 경우가 발생할 수 있습니다.

=>이런 경우에는 단위나 대소문자 구분등을 통일할 필요가 있습니다.

=>이런 작업을 표준화라고 합니다.

 

1.단위가 다른 경우에는 반드시 단위는 통일을 시켜야 합니다.

연로비에서  미국단위와 한국단위가 달라서 통일 해야 한다.

 

 

2.자료현 변환

=>데이터를 수집할 때는 자료형을 고려하지 않고 수집을 하지만 분석이나 머신러닏등에 적용을 할 때 적용하고자 하는 알고리즘에 맞게 데이터의 자료형을 수정을 해야 합니다.

분류를 할 때는 숫자 데이터가 아니라 범주형이 필요하고 머신러닝에서 거리를 계산할려고 하는 경우에는 문자 데이터의 경우는 거리 계산이 안되므로 숫자 데이터로 번환을 해야 합니다.

자료형 변환은 astype('자료형')으로 가능

 

 

#auto-mpg.csv파일의 내용을 가져오기

df = pd.read_csv('./Desktop/data/auto-mpg_1.csv', header = None)

df.columns = ['mpg','cylinders','displacement','horsepower','weight','acceleration','model year','origin','name']

print(df.head())

print(df.info())

 

 

#origin의 경우는 생상 국가

#1 이면 미국 2이면 유럽 3이면 일본

#현재 데이터는 1,2,3 숫자 형태로 존재

#origin데이터를 문자열로 치환하고 자료형을 category로 변환

#자료형 변환은 astype('자료형')으로 가능

 

#문자열로 치환

df['origin'].replace({1:'미국',2:'유럽',3:'일본'},inplace = True)

print(df.head())

print(df['origin'].dtypes)

 

#데이터를 범주형 (category)으로 변환

df['origin'] = df['origin'].astype('category')

print(df['origin'].dtypes)

 

 

#문자열로 변환

df['origin'] = df['origin'].astype('str')

print(df['origin'].dtypes)

 

 

 

 

3.연속형 데이터의 이산화

=>연속적인 데이터를 가지고 분류를 한다면 데이터 변환없이 하게 되면 그룹의 종류가 너무 많아집니다.

이런 경우에는 연속적인 데이터를 몇 개의 구간으로 이산화를 애야 합니다.

이를 구간분할(binning)이라고 합니다.

=>pandascut함수를 이용

x에 데이터 배열을 설정

bins에 경계할 배열을 설정

labels애 변환할 이산 데이터 배열을 설정

include_lowestTrue를 설정하면 첫번째 경계값을 포함

 

 

print(df['horsepower'])

print(df['displacement'])

 

 

#displacement를 대형, 중형, 소형으로 새로운 컬럼 만들기

count, bin_dividers = np.histogram(df['displacement'], bins= 3)

print(bin_dividers)

 

 

#치환할 데이터 배열 만들기

bin_names = ['소형','중형','대형']

 

#치환

df['차량분류'] = pd.cut(x = df['displacement'], bins = bin_dividers, labels = bin_names, include_lowest=True)

print(df['차량분류'])

 

 

2)numpy digitize이용

=>첫번째매개변수는 분할할 데이터

=>bins에 구간을 분할할 값의 list를 대입

=>right 에 구간을 포함할 지 여부를 bool로 설정

=>각 구간에 0,1,2형태 이 일련번호를 배정해서 그 결과를 배열로 리턴

 

age = np.array([[30],[40],[29],[50],[60]])

#40을 기준으로 분할 -경계값이 다음 그룹으로 분할

print(np.digitize(age, bins=[40]))

print(np.digitize(age, bins=[30,50]))

#right를 이용하면 경계값이 아래 그룹으로 분할

print(np.digitize(age, bins=[30,50], right = True))

 

 

3)여러 개의 열로 구성된 데이터를 이산화 해야 하는 경우

=>군집 분석 알고리즘을 이용

 

#여러 개의 열로 구선된 데이터의 이산화

sample = np.array([[30,30],[40,70],[30,60],[25,56],[30,20],[50,60]])

df =  pd.DataFrame(sample)

print(df)

 

#KMeans 군집 분석을 위한 라이브러리

from sklearn.cluster import KMeans

#군집 분석 객체 생성

cluster = KMeans(3,random_state = 0)

#데이터를 가지고 훈련

cluster.fit(sample)

#predict  예측  - 군집

df['group'] = cluster.predict(sample)

print(df)

 

**범주형 데이터의 사용

1.원 핫 인코딩

=>카테고리를 나타내는 문자열 형태의 데이터는 머신러닝에 바로 사용할 수 없습니다.

머신러닝의 대다수 알고리즘은 숫자 데이터에서만 동작ㅇ르 수행하기 때문입니다.

카테고리 형태의 데이터를 특성의 소유 여부만을 나타내는 01로 변환하는 작업을 원핫 인코딩이라고 합니다.

=>pandasget_dummies()라는 함수를 이용해서 원핫 인코딩을 할 수있는데 컬럼에 나올 수 있는 모든 값들을 조사해서 새로운 더미변수()을 만들고 속성을 소유하고 있으면 1 없으면 0으로 포기

 

 

#? 인 데이터를 NaN으로 치환하고 NaN 인 데어트를 제거

df['horsepower'].replace('?',np.NaN, inplace =True)

df.dropna(subset = ['horsepower'], how = 'any', inplace = True)

 

#데이터 형변환

df['horsepower'] = df['horsepower'].astype(float)

 

 

#horsepower 를 저출력 , 보통출력 , 고출력으로 구간 분할

#범주형 목록을 생성

bin_names = ['저출력','보통출력','고출력']

#3개로 나눌 경계값을 생성

print(df['horsepower'])

count, bin_dividers = np.histogram(df['horsepower'], bins= 3) #형변환을 안하면 오류 난다.

 

print(bin_dividers)

 

print(df['horsepower'].dtype)

 

#구간 분할

df['hp_bin'] = pd.cut(x = df['horsepower'] , bins = bin_dividers, labels = bin_names, include_lowest = True)

print(df['hp_bin'])

 

#자료형이나 변경이 안되는 데이터가 있으면 조금씩 고쳐줘야 한다.

 

#hp_bin을 원핫인코딩 - 3개의 컬럼이 생성되고

#컬럼의 이름은 저출력, 보통출력, 고출력이 됩니다.

#자신의 값과 일치하는 컬럼에만 1이 되고 나머지 컬럼에는 0이 대입

dummy = pd.get_dummies(df['hp_bin'])

print(dummy)

 

 

2. 사이킷 런의 원핫 인코딩

=>preprocessing.LabelBinarizer:하나의 특성을 원핫 인코딩

fit_transform메소드에 데이터를 대입하면 원 핫 인코딩을 해주고 그 결과를 가지고 inverse_transform 메소드에 대입하면 원래의 데이터로 환원이 됩니다.

classes_속성을 확인하면 인코딩 순서를 확인할 수 있습니ㅏㄷ.

 

=>preprocessing.MultiLabelBinarizer:여러 개의 특성을 원 핫 인코딩

 

=>preprocessing.LabelEncoder: 0부터 시작하는 정수로 변환

 

 

 

 

된장라면이다라면 된장라면 그림이 있고 크기를 같게 하고 각각 하나하나가 특성이 되서 많이 일치하는 것을 분류로 한다.

회소행렬

0000000001 00000

(10,1) => 10번째 자리만 1이다.

회소행렬 : 압축이다. 0이 아닌 것만 표현

 

검증 검증 검증 검증 검증 검증 (검증, 6)

 

 

구분만 해야 할때

 

 

범주형 데이터를 수치화 사용할 때 원핫 인코딩이라고 한다.

 

 

 

 

#사이킷 런을 이용한 원핫인코딩

from sklearn.preprocessing import LabelBinarizer

 

one_hot = LabelBinarizer()

#데이터를 정렬하기 때문에 순서를 확인

print(one_hot.fit_transform(df['hp_bin']))

#데이터를 정렬하기 때문에 순서를 확인

print(one_hot.classes_)

 

print(one_hot.inverse_transform(one_hot.fit_transform(df['hp_bin'])))

 

#여러 개의 특성을 원핫 인코딩

#1개의 데이터가 여러 개의 특성을 갖는 경우 -tuple, list

#문장의 유사도 나 상품 추천 할 때 사용

from sklearn.preprocessing import MultiLabelBinarizer

 

features = [('Java' ,'C++'),('Java','Python'),('C#','R'),('Python','R')]

        #나온 갓이 5개 종류

#alphabet 순서

one_hot =MultiLabelBinarizer()

print(one_hot.fit_transform(features))

print(one_hot.classes_)

#MultiLabelBinarizer 이 형태로 한다.

 

 

#get_dummies는 하나의 특성을 하나의 컬럼으로 생성

#값의 종류가 15ㄷ가지이면 15개의 컬럼을 생성

#컬럼을 1개로 만들고 0부터 일련번호 형태고 값을 설정

from sklearn.preprocessing import LabelEncoder

one_hot =LabelEncoder()

print(one_hot.fit_transform(df['hp_bin']))

print(one_hot.classes_)

 

 

 

3.순서가 있는 범주형 인코딩

=>순서가 있는 경우에는 replace메소드를 이용해서 수치값으로 변환

=>일반적으로 일련번호처럶 숫자를 부여하지만 특별한 경우에는 일정 비율을 연산해서 부여하기도 합니다.

=>이와 유사한 기능을 sklearnOrdinalEncoder를 이용할 수 있음

 

#순서가 있는 범주형 인코딩

from sklearn.preprocessing import OrdinalEncoder

import numpy as np

 

features = np.array([['대학민국',30],['미국',10],['뉴질랜드',25],['캐나다',20]])

# 각 컬럼의 데이터를 정렬하고 순서대로 가중치를 부여

encoder = OrdinalEncoder()

result = encoder.fit_transform(features)

print(result)

 

 

4. 범주형 데이터에서 누락된 값 대체

=>가장 자주 등장하는 값을 누락된 값에 대해

=>머신러닝 알고리즘을 이용해서 구한 값으로 대체

 

유클리티안 거리 ->

 

 

 

#머신러닝 알고리즘을 이용한 누락된 값 대체 -분류

from sklearn.neighbors import KNeighborsClassifier

 

#훈련할 데이터

X = np.array([[0,2.10,1.45],

              [1,1.18,1.33],

              [0,1.22,1.27],

              [1,-0.10,-1.45]])

 

#NaN을 가진 데이터

X_with_nan = np.array([[np.NaN, 0.87, 1.31],

                        [np.NaN , -0.67, -0.22]])

 

#분류기술 생성

clf = KNeighborsClassifier(3, weights ='distance')

 

#훈련 -1번째 이후 데이터 전체를 가지고 0번째 데이터를 예측

trained_model = clf.fit(X[:,1:], X[:,0])

# ,

#0

 

#데이터 예측

imputed_values = trained_model.predict(X_with_nan[:,1:])

print(imputed_values)

# 뷴류는 나하고 가장 가까운 것 한다. 그래서 숫자로 바꾼다.

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-8  (0) 2020.11.12
데이터분석-7  (0) 2020.11.11
데이터분석-5  (0) 2020.11.09
데이터분석-4  (0) 2020.11.08
데이터분석-3  (0) 2020.11.08
반응형

수집 -> 탐색 -> 가공

탐색     -> 데이터 정보 출력

           -> 시각화

 

선 그래프

시계열 쪽 추이 등 보여주는 것

인구변화 등 추이

 

import pandas as pd

 

#pop = pd.read_excel('./Desktop/data/시도__이동자수.xlsx')

#pop = pd.read_excel('./Desktop//data/시도__이동자수.xlsx',fillna = 0 )

pop = pd.read_excel('./Desktop//data/시도__이동자수.xlsx',fillna = 0,header = 0 )

 

 

print(pop.head())

 

 

#na(None,numpy.NaN...) 값을 앞의 데이터로 채우기

#파이썬의 분석 라이브러리의 수정하는 메소드들은

#대부분 수정해서 복사본을 리턴합니다.

#원본에 반열할 때는 다시 대입하거나

#inplace옵션이 있으면 이 옵션에 True를 대입

pop = pop.fillna(method='ffill')

print(pop.head())

 

 

#전출지별은 서울 특별시 이고 전입지는 서울특별시가

#아닌 데이터만 추출하기 위한 조건 만들기

mask = (pop['전출지별'] =='서울특별시') & (pop['전입지별'] !='서울특별시')

print(pop[mask])

#df_seoul = pop[mask]

 

#전출지별 열을 제거

df_seoul = pop[mask].drop(['전출지별'], axis = 1)

print(df_seoul)

 

 

print(pop)

#전입자별 컬럼이름을 전입지로 수정

#inplace옵션을 이용해서 원본에 반영

#axis = 1 행단위를 열단위로

df_seoul.rename({'전입지별':'전입지'},axis = 1, inplace = True)

print(df_seoul.head())

 

 

 

#인덱스를 기존 컬럼으로 변경하고 컬럼은 제거

df_seoul.set_index('전입지', inplace=True)

print(df_seoul.head())

 

 

#전라남도로 전출간 인원에 대한 선 그래프 그릭

sr_one = df_seoul.loc['전라남도']

 

 

#1970, 1971 제거

sr_one.drop(['1970','1971'], inplace = True)

 

import matplotlib.pyplot as plt

plt.plot(sr_one.index, sr_one.values)

 

 

 

# matplotlib 한글 폰트 오류 문제 해결

from matplotlib import font_manager, rc

import platform

   

#매킨토시의 경우

if platform.system() == 'Darwin':

    rc('font', family='AppleGothic')

#윈도우의 경우

elif platform.system() == 'Windows':

    font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()

    rc('font', family=font_name)

   

#스타일설정

plt.style.use('ggplot')

#이미지 사이즈 설정 - 단위는 인치

plt.figure(figsize = (14,5 )) #데이터 많으면 여기 조정 해야 한다.

#눈금 조정

plt.xticks(size = 10, rotation = 'vertical')

#그래프 그리기

plt.plot(sr_one.index, sr_one.values, marker = 'o' , markersize = 10)

 

#그래프 제목 만들기

plt.title('서울에서 전라남도로의 이동',size = 30)

#축제목 만들기

plt.xlabel('기간',size = 20)

plt.ylabel('인구 수',size = 30)

#범 례

plt.legend(labels=['서울 -> 전라남도'],loc ='best',fontsize = 15)

 

#그래프 위에 글자 작성

plt.annotate('인구이동 감소',xy = (40, 50000), rotation = -11, va = 'baseline',ha = 'center',fontsize = '15')

 

plt.show()         

 

**시각화

=>데이터의 형태를 파악하거나 보고서를 만들 목적으로 그래프나 지도 등을 출력하는 작업

=>matplotlib(기본 시각화),pandas, seaborn(시각적인 효과가 조금 더 뛰어남 ) ,folium(지도 , 단계구분도) 등을 주로 이용

 

1.꺽은선 그래프 -plot

=>날짜나 시간에 따른 변화량 또는 2개의 컬럼을 가지고 데이터의 분포를 알아볼 때 많이 이용

 

 

2. 하나의 화면에 2개의 그래프 그리기

객체 = plt.figure(figsize = (가로크기 , 세로크기))

변수 1 = 객체.add_subplot(행의 개수 , 열의 개수, 자신의  번호 )

변수 2 = 객체.add_subplot(행의 개수, 열의 개수 , 자신의 번호) ..

 

변수1.plot(옵션 ...)

변수2.plot(옵션 ...)

 

 

#기존 데이터에서 전라남도에서 서울로 이동한 인구수 찾기

mask = (pop['전출지별'] == '전라남도') & (pop['전입지별'] != '전라남도')

df_jeo = pop[mask]

#print(pf_jeo.head())

 

#전출지별 컬럼 제거하기

df_jeo = df_jeo.drop(['전출지별'],axis = 1)

#컬럼이름 변경하기

df_jeo.rename({'전입지별':'전입지'},axis = 1, inplace = True)

#인덱스 설정하기

df_jeo.set_index('전입지',inplace = True)

#서울로 이동한 데이터만 가져오기

sr_two = df_jeo.loc['서울특별시']

print(sr_two.head())

 

#여러개의 그래프를 그리기 위해서 그리기 객체를 돌려받음

fig = plt.figure(figsize = (10,10))

#2 1열에서 1

ax1 = fig.add_subplot(2,1,1)

#2 1열에서 2

ax2 = fig.add_subplot(2,1,2)

 

ax1.plot(sr_one, marker='o' , markersize = 10, color='orange',linewidth = 2, label ='서울->전라남도')

ax2.plot(sr_two, marker='o' , markersize = 10, color='green',linewidth = 2, label ='전라남도->서울')

 

#y축 눈금범위 설정

ax1.set_ylim(10000,150000)

ax2.set_ylim(10000,150000)

 

ax1.set_xticklabels(sr_one.index,rotation = 75)

ax2.set_xticklabels(sr_two.index,rotation = 75)

 

plt.show()

 

=>하나의 그래프에 그리기

ax1.plot(sr_one, marker='o' , markersize = 10, color='orange',linewidth = 2, label ='서울->전라남도')

ax1.plot(sr_two, marker='o' , markersize = 10, color='green',linewidth = 2, label ='전라남도->서울')

 

 

3.하나의 영역에 여러개의 그래프 그리기

=>동일한 영역에서 그리는 함수를 여러번 호출

 

4. 막대 그래프

=>빈도 수를 비교할 때 주로 이용

=>bar(수직), barh(수평) 메소드로 그림

=>하나의 영역에 2개의 막대그래프를 그릴 때는 첫번째 막대 그래프의 width를 조정

width1이면 다음 데이터와 붙어서 출력됩니다.

2개면 0.5이하로 설정해서 그리고 3개면 0.33이하로 설정하면 됩니다.

 

 

 

 

##서울에서 전라남도 , 경상남도 ,충청남도

##전출간 인원을 막대 그래프로 비교

#비교는 막대 그래프 추이는 선

#커널을 제시작

import pandas as pd

 

df = pd.read_excel('./Desktop//data/시도__이동자수.xlsx',header = 0,fillna = 0 )

print(df.head())

#헤더 위치

 

#NaN값을 이전 값으로 채우기

df = df.fillna(method='ffill')

print(df.head())

 

#필요한 데이터만 행단위로 뽑고 싶다.

#서울 데이터만 출력

#전출지별이 서울특별시이고  전입별이 서울특별시가 아닌 것

mask = (df['전출지별'] == '서울특별시') & (df['전입지별'] != '서울특별시')

#mask의 결과가 true인 것 만 추출

df_seoul = df[mask]

print(df_seoul.head())

 

 

#불필요한 열 제거

df_seoul.drop(['전출지별'],axis = 1, inplace = True)

print(df_seoul.head())

 

#불필요한 행 제거 -인덱스 설정을 안한 경우는 일련번호로 제거

#df_seoul.drop([0,1,2,3,4,5],axis = 1, inplace = True)

#print(df_seoul.head())

 

#기존 컬럼을 인덱스로 설정

df_seoul.set_index(['전입지별'],inplace =True)

print(df_seoul.head())

 

 

#행단위로 골라내기 - 인덱스를 이용

sr= df_seoul.loc[['경기도','충청남도','경상남도','전라남도']]

print(sr)

 

 

#행과 열을 치환

sr = sr.T #행과 열 치환

print(sr)

T ->행과 열 치환

cross tab

set_index

 

 

#데이터 모임에 동일한 함수를 적용한 후 결과 만들기

#sr.index int라는 함수를 각 요소마다 대입해서 실행 한 후

# 그 결과를 가지고 다시 데이터의 모임을 생성

sr.index = sr.index.map(int)

 

import matplotlib.pyplot as plt

 

 

# matplotlib 한글 폰트 오류 문제 해결

from matplotlib import font_manager, rc

import platform

   

#매킨토시의 경우

if platform.system() == 'Darwin':

    rc('font', family='AppleGothic')

#윈도우의 경우

elif platform.system() == 'Windows':

    font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()

    rc('font', family=font_name)

   

#그래프 그리기

plt.figure(figsize = (15,6))

 

plt.bar(pd.RangeIndex(0,len(sr.index),1),sr['경기도'],width = 1)

 

 

plt.title('서울에서의 인구이동')

#그냥 그리면 한글이 깨진다.

plt.show()

 

#데이터 모임에 동일한 함수를 적용한 후 결과 만들기

#sr.index int라는 함수를 각 요소마다 대입해서 실행 한 후

# 그 결과를 가지고 다시 데이터의 모임을 생성

sr.index = sr.index.map(int)

 

import matplotlib.pyplot as plt

 

 

# matplotlib 한글 폰트 오류 문제 해결

from matplotlib import font_manager, rc

import platform

   

#매킨토시의 경우

if platform.system() == 'Darwin':

    rc('font', family='AppleGothic')

#윈도우의 경우

elif platform.system() == 'Windows':

    font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()

    rc('font', family=font_name)

   

#그래프 그리기

plt.figure(figsize = (15,6))

 

#plt.bar(pd.RangeIndex(0,len(sr.index),1),sr['경기도'],width = 1)

 

plt.bar(pd.RangeIndex(0,len(sr.index),1),sr['경기도'],color = 'orange',width = 0.25,label ='경기도')

plt.bar(pd.RangeIndex(0,len(sr.index),1)+0.25,sr['전라남도'],color = 'green',width = 0.25,label ='전라남도')

plt.bar(pd.RangeIndex(0,len(sr.index),1)+0.5,sr['충청남도'],color = 'red',width = 0.25,label ='충청남도')

plt.bar(pd.RangeIndex(0,len(sr.index),1)+0.75,sr['경상남도'],color = 'blue',width = 0.25,label ='경상남도')

 

#범례 표시

# 색갈에 대해서 구분하기 힘들 다.

plt.legend()

 

plt.title('서울에서의 인구이동')

#그냥 그리면 한글이 깨진다.

plt.show()

 

#경기도 빼면 어느 정도 구분이 된다.

#데이터 모임에 동일한 함수를 적용한 후 결과 만들기

#sr.index int라는 함수를 각 요소마다 대입해서 실행 한 후

# 그 결과를 가지고 다시 데이터의 모임을 생성

sr.index = sr.index.map(int)

 

import matplotlib.pyplot as plt

 

 

# matplotlib 한글 폰트 오류 문제 해결

from matplotlib import font_manager, rc

import platform

   

#매킨토시의 경우

if platform.system() == 'Darwin':

    rc('font', family='AppleGothic')

#윈도우의 경우

elif platform.system() == 'Windows':

    font_name = font_manager.FontProperties(fname="c:/Windows/Fonts/malgun.ttf").get_name()

    rc('font', family=font_name)

   

#그래프 그리기

plt.figure(figsize = (15,6))

 

#plt.bar(pd.RangeIndex(0,len(sr.index),1),sr['경기도'],width = 1)

 

#plt.bar(pd.RangeIndex(0,len(sr.index),1),sr['경기도'],color = 'orange',width = 0.25,label ='경기도')

plt.bar(pd.RangeIndex(0,len(sr.index),1)+0.25,sr['전라남도'],color = 'green',width = 0.25,label ='전라남도')

plt.bar(pd.RangeIndex(0,len(sr.index),1)+0.5,sr['충청남도'],color = 'red',width = 0.25,label ='충청남도')

plt.bar(pd.RangeIndex(0,len(sr.index),1)+0.75,sr['경상남도'],color = 'blue',width = 0.25,label ='경상남도')

 

#범례 표시

# 색갈에 대해서 구분하기 힘들 다.

plt.legend()

 

plt.title('서울에서의 인구이동')

#그냥 그리면 한글이 깨진다.

plt.show()

 

#경기도 빼면 어느 정도 구분이 된다.

막대그래프는 비슷한 것 끼리  비교해야 한다. 아니면 비교가 어렵다.

 

 

 

하나는 마이너스 곱하고 다른 하나는 정상으로

단위가 2개 있으면 하나에 두개 그리기  추이하고 가격

 

 

 

 

5. 히스트그램

=>각 구간의 데이터 개수를 파악하고자 할 때 사용하는 그래프

=>hist메소드를 이용

 

#lovefruits.csv파일의 내용 읽어오기

df = pd.read_csv('./Desktop/data/lovefruits.csv')

print(df)

 

 

 

#lovefruits.csv파일의 내용 읽어오기

df = pd.read_csv('./Desktop/data/lovefruits.csv',encoding = 'cp949')

print(df)

 

#막대 그래프를 이용해서 데이터 개수 출력하기

data= df['선호과일'].value_counts(sort = False)

print(data)

 

plt.bar(range(0,len(data),1),data)

plt.xticks(range(0,len(data),1),data.index)

plt.title('과일 선호도 조사')

plt.show()

 

#히스트그램을 이용해서 데이터 개수 출력하기 -개수 파악ㄱ 작업 필요 없음

plt.hist(df['선호과일'])

plt.show()

 

 

#히스트그램은 bins옵ㄴ션을 이용해서 구간의 개수를 설정해서 그릴 수 있음

#연속형 데이터의 히스트그림은 구간 설정을 해야 합니다.

#점수 등은 문제가 생긴다.

df = pd.read_csv('./Desktop/data/student.csv',encoding = 'cp949')

print(df)

 

#plt.hist(df['수학']) #데이터가 많을 수 있다.

plt.hist(df['수학'],bins= 3) #3개 구간으로 나누어진다.

plt.show()

 

 

#연속적인가 범주이냐 등에서 달라진다.

#선호도는 범주형 이기 때문에 bins를 설정할 필요없다.

#점수는 완전한 연속형이 아니지만 연속형이여서 bins를 설정해야 한다.

 

 

 

 

 

6. 산포도

=>2개 컬럼의 관계를 파악하기 위해서 생성

=>상관여부나 그룹핑할 개수 등을 파악하고자 할 때 먼저 그려보면 효과적입니다.

=>scatter라는 메소드를 이용

=>colorvar를 이용해서 산포도에 그려지는 데이터의 색상에 크기를 적용할 수 있습니다.

한방형으로 줄어들거나 크지면 상관관계가 높다.

상관관계와 두개 이상 그룹핑하면 상관관계와 관계없다.

몇개의 그룹을 만드는지 어떻게 그룹핑하면 좋을지는 산포도를 그래면 된다.

생활비 , 교통비 등 등급 으로 만들고 싶을 때 각각의 2-3개 묶어서 상관관계 높은지 파악할 수 있다.

관계를 파악하고 작업을 해야 한다.

 

 

#2개 컬럼의 관게를 파악하기 위한 산포도

df = pd.read_csv('./Desktop/data/auto-mpg.csv')

 

#열 이름 지정

df.columns = ['mpg','cylinders','displacement','horsepower','weight','accleration','model year','origin','name']

print(df.head())

 

#s는 원의 크기 옵션

plt.scatter(x = df['weight'], y = df['mpg'],s= df['cylinders']*10,alpha = 0.5)

plt.title('중량과 연비의 관계')

plt.xlable('중량',size = 20)

plt.xlable('연비',size = 20)

plt.show()

#반비례 상관관계

 

7.파이 그래프

=>전체에서의 기여도를 파악할 때 주로 이용

=>하나의 열을 가지고 작성

=>메소드이름은 pie

=>explode옵션에 실수 리스트를 대입하면 중앙에서 대입한 숫자 만큼 떨어져서 그려짐 , 0.0~ 1.0사이

=>autopct에 숫자 서식을 설정해서 백분율을 표시할 수 있음 ㅣ '%1.1f%%' -소수 첫째자리 까지의 백분율

 

 

#파이 그래프

df = pd.read_csv('./Desktop/data/korea.csv', encoding = 'cp949')

print(df.head())

 

 

explode = []

for i in range(0,20):

    explode.append(0)

explode[2] = 0.3

# 튀여 나오게 하는 것은 잴 큰것 찾아서 혹은 잴 작은 애

 

plt.figure(figsize = (15,8))

plt.pie(df['점수'],labels=df['이름'],explode = explode, autopct = '%1.1f%%')

plt.title('학생별 기여도')

plt.legend()

plt.show()

#max는 잴 큰것

 

#파이 그래프

df = pd.read_csv('./Desktop/data/korea.csv', encoding = 'cp949')

print(df.head())

 

 

explode = []

for i in range(0,20):

    explode.append(0)

#explode[2] = 0.3

#explode[df['점수'].idxmax(axis = 1)]= 0.3

explode[df['점수'].idxmin(axis = 1)]= 0.3

# 튀여 나오게 하는 것은 잴 큰것 찾아서 혹은 잴 작은 애

 

plt.figure(figsize = (15,8))

plt.pie(df['점수'],labels=df['이름'],explode = explode, autopct = '%1.1f%%')

plt.title('학생별 기여도')

plt.legend()

plt.show()

#max는 잴 큰것

 

print(df['점수'].idxmax(axis = 1)) #젤 큰 값의 인덱스

 

8.box-plot 그래프

=>데이터의 분포를 확인할 때 사용하는 그래프

=>상자의 중앙선이 중간값 상자의 좌우가 25%, 75%에 해당하는 값

양끝선이 아래쪽 0.75%정도 위끝선은 99.75% 정도에 해당하는 값

작은 원으로 표현되는 극단치(outlier)로 판단

=>중앙선과 양끝단의 선, 상자의 선을 보고 데이터의 분포를 예측

한쪽으로 치우치면 정규분초가 아닌 형태로 판정

 

#상자그래프 그리기

df = pd.read_csv('./Desktop/data/student.csv',encoding = 'cp949')

 

plt.figure()

plt.boxplot((df['국어'],df['영어'],df['수학']),labels=('국어','영어','수학'))

plt.show()

 

 

9.면적 그래프

=>선 그래프의 하단에 색상을 칠한 그래프

=>목적은 막대그래프와 유사

=>fill_between이라는 메소드를 이용

 

**seaborn패키지

=>matplotlib 을 기반으로 해서 여러가지 테마아 통계형 차트가 추가된 패키지

=>numpypandas의 자료구조는 그대로 사용

 

http://seaborn.pydata.org/

문서: http://seaborn.pydata.org/tutorial/aesthetics.html

 

 

set: http://seaborn.pydata.org/generated/seaborn.set.html

set_style: http://seaborn.pydata.org/generated/seaborn.set_style.html

set_color_codes: http://seaborn.pydata.org/generated/seaborn.set_color_codes.html

 

 

 

http://seaborn.pydata.org/examples/index.html

 

pandas는 샘플 데이터 가지지 않는다. 하지만 seaborn부터는 샘플 데이터 몇개 가지고 있다.

 

 

1.regplot이나 lmplot이라는 함수를 이용해서 데이터의 분포와 1차 다항식 그래프를 같이 출력 가능

1차 다항식은 2개의 컬럼의 회귀식입니다.

 

#커널을 재시작 import된 모든 라이브러리 제거

#변수도 모두 제거

import matplotlib.pyplot as plt

#시각적인 효과가 조금더 뛰어난 그래프 패키지

import seaborn as sns

 

#tips라는 데이터 가져오기 -레스토랑에서의 tip에 관련된 데이터

tips = sns.load_dataset('tips')

print(tips.head())

 

 

fig = plt.figure(figsize = (8,6))

#1 2 1번째

ax1 = fig.add_subplot(1,2,1) #위아래

ax2 = fig.add_subplot(1,2,2) #좌우

sns.set_style('darkgrid')#색상 쓰지 않아도 style을 정한다.

 

#data dataframedmf x,y에 컬럼이름을 설정

sns.regplot(x = 'total_bill' , y = 'tip' ,data = tips, fit_reg = True, ax = ax1) #회귀 최소한 2개 있어ㅑ 한다. x y

sns.regplot(x = 'total_bill' , y = 'tip' ,data = tips, fit_reg = False, ax = ax2) #회귀 선이 안나온다.

 

 

 

plt.show()

 

 

 

#3개 컬럼의 관계보기 -lmplot

#x,y,hue옵션 이용

#hue 에는 카테고리(범주) 데이터를 설정

fig = plt.figure(figsize = (8,6))

sns.set_style('darkgrid')#색상 쓰지 않아도 style을 정한다.

#sns.lmplot(x = 'total_bill' , y = 'tip' ,hue = 'sex', data = tips, fit_reg = True)

sns.lmplot(x = 'total_bill' , y = 'tip' ,hue = 'smoker', data = tips, fit_reg = True)

 

plt.show()

 

 

 

밀도추정 데이터가 다를수 있지만 계속 모아다 나면 예측이 가능하다.

밀도는 확률

hist그램은 연속적이지 못한다. bins에 따라 많이 달라진다. 메모리 문제가 생길 수 도 있다. ->kerder density Estinmation

Kernel Density Estimation (커널 밀도 추정)

 

2.단변량 데이터의 분포를 출력

=>히스트그램을 이용하는 경우가 많음 - 쉽다는 장점은 있지만 불연속하게 그려집니다.

=>히스트그램 대신에 커널밀도함수(kde)를 적용해서 연속적으로 그려서 파악하는 경우가 있음

=>seaborndisplot이라는 함수를 이용하면 커널 밀도 함수를 적용한 그래프와 히스트그램을 같이 출력할 수 있음

 

 

#tip컬럼에 분포를 확인

fig = plt.figure(figsize=(8,6))

sns.set_style("darkgrid")

sns.distplot(tips['tip'])

plt.show()

tip을 안주는 사람은 구분하지 못한다.

안준 분이 510불 준 분은 2

1불은 나올수 없는 것이다. 비연속

1불을 줄수 도 있는 것이고  

데이터 예측은 연속적이여야 한다. 없다고 하면 안된다.

 

 

 

#tip컬럼에 분포를 확인

fig = plt.figure(figsize=(8,6))

sns.set_style("darkgrid")

#sns.distplot(tips['tip'])

sns.distplot(tips['tip'],hist=False)

plt.show()

 

이산 :디지털

범주형 -> 불연속성 -> 연속으로 만드는 것이 정밀도

 

3.heatmap

=>크로스 테이블을 시각화할 때 주로 이용

=>2개 항목을 적용해서 분류한 후 데이터를 출력하는 시각화

=>Dataframe에서 pivot이라는 함수를 이용해서 2개로 분류하고 계산할 항목과 함수를 지정(함수는 생략하면 합계)

=>heatmap함수에 데이터를 대입하면 시각화 된다.

fmt = 'd'

=>

#heatmap(2가지로 분류해서 하나의 통계값 출력) 만들기

flights = sns.load_dataset('flights')

print(flights.head())

 

#pivot테이블 만들기

pivot = flights.pivot('month','year','passengers')

print(pivot)

 

 

fig = plt.figure(figsize=(8,6))

#글자는 annotation

#annot 는 데이터를 화면에 출력할 것인지 여부

#fmt는 숫자 출력 포맷으로 d를 설정하면 정수로 출력

sns.heatmap(pivot, annot = True,fmt = 'd')

plt.show()

 

 

4.violinplot

=>boxplot은 데이터 값들의 상한과 하한 , 4분위 수 등을 파악

=>violinplot은 시각형 대신에 커널밀도 함수를 적용해서 데이터 개수도 어느 정도 파악이 가능

 

5.데이터 개수 출력

=>strippot, swarmplot()등이 제공

 

6.막대 그래프 -barplot

 

7.히스트그램-countplot

 

8.데이터프래임의 모든 컬럼의 상관관계를 출력 -pairplot

 

 

9.상관관계를 출력하고 히스트그램까지 출력 -jointplot

 

 

#tips데이터의 모든 컬럼의 산저모를 출력

 

pythoh, r, 에서 시각화

=>탐색

=>보고서

**folium

=>지도나 단계구분도를 위한 시각화 패키지

=>자바스크립트 기반으로  interactive(동적으로 변화)하게 시각화

=>기본패키지가 아니라서 설치를 해야 함

=>jupyter-notebook이 크롬에서 실행중이라면 바로 출력 가능

다른 ide를 사용하는 save('파일 경로.html'로 저장한 후 브라우저에서 확인

ie에서는 자바스크립트 문제로 출력되지 않음

 

=>단계구분도를 만들 때는 각 지역의 경계에 대한 json데이터가 존재해야 합니다.

한국 데이터는 southkorea-maps에서 확인 가능

 

 

 

1지도 생성

folium.Map(location=[위도, 경도], zoom_start = 확대축소비율)

 

 

2.마커 생성

folium.Marker(location=[위도, 경도],popup =출력될 문자열, icon = 이미지).add_to(지도객체)

 

3.출력

-주피터 노프복: 지도 객체

-다른 ide:지도 객체.save('파일경로')

 

크롬으로 변경

 

 

import folium

#지도 생성

m = folium.Map(location = [37.572656, 126.973304], zoom_start = 15)

#zoom_start 숫자가 크면 클수록 축소가 된다.

folium.Marker(location=[37.572656, 126.973304],popup='KB Card',icon = folium.Icon(icon='cloud')).add_to(m)

folium.Marker(location=[37.569027, 126.988000],popup='김떡순 원조',icon = folium.Icon(icon='cloud')).add_to(m)

#여기서는 한글이 때지지만 save하면 한글에 아무 문제도 없다.

#지도 출력

m

#지도 저장

#m.save('map.html')

# spyder에서 하면 m.save해서 봐야 한다.

 

 

semi-project 조 편성

인원은 3 ~ 4 : 5개조

딥러닝 프로젝트를 1개씩 배정

 

취업 분야

-      AI분야

-      개발분야

 

개발 분야로 취업을 생각했으면 프로젝트 하면서 웹 서버 개발  프로젝트를 진행

개발 분야로 취업을 생각한 경우 프로젝트는 웹 서버를 만들어서 데이터를 가지고 홤녀에 출력하고 Open API를 제공해서 모바일(android)에서 출력

 

kaggle

 

개발 일지 만들기

 

 

 

어려운 부분하고

어떻게 극복했는지

 

소스 다하고 소스 올리기 형상관리 여부 확인

 

 

카카오톡 아니고 slack 사용하기

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-7  (0) 2020.11.11
데이터분석-6  (0) 2020.11.10
데이터분석-4  (0) 2020.11.08
데이터분석-3  (0) 2020.11.08
데이터분석-2  (0) 2020.11.08
반응형

**배열의 집합

1.hstack

=>행의 수가 같은 배열을 열 방향으로 결합해주는 함수

 

2.vstack

=>열의 수가 같은 배열을 행 방향으로 결합해주는 함수

 

3.dstack

=>행과 열의 수가 같은 배열을 가지고 위치가 같은 요소들을 가지고 하나의 배열로 묶어서 차원이 1개 늘어난 배열을 만들어주는 함ㅅ

 

4.stack

=>dstack과 비슷하지만 원하는 방향으로 새로운 배열을 만들어서 차원을 늘려주는 함수

 

 

import numpy as np

 

#일련 번호 형태로 배열 만들기

ar = np.arange(1,13)

#3 4열로 변경

ar = ar.reshape(3,4)

 

#일정한 간격을 가지고 만들기

br = np.linspace(101,112, num = 12)

br = br.reshape(3,4)

 

#열 방향으로 합치기

print(np.hstack([ar, br]))

 

 

#  방향으로 합치기

print(np.vstack([ar, br]))

 

**pandas의 자료구조

=>series dataframe

=>numpyndarray는 행이나 열을 구분하는 것이 정수로 된 인덱스인데 pandas의 자료구조들은 index를 직접 설정 가능

 

 

1.Series

1)생성

Series(data, index = None, dtype = None, copy = False)

=>data__iter__가 구현된 객체

=>index는 데이터 별 이름을 부여하는 것인데 생략하면 0부터 시작하는 숫자

=>dtype은 각 요소들이 자료형인데 생략하면 유추해서 설정

=>copy는 복제 여부

 

 

=>datadict를 대입하면 keyindex가 되고 value가 데이터로 설정됩니다.

=>values속성을 호출하면 데이터만 추출해서 numpyndarray로 리턴합니다.

=>index 속성을 호출하면 index들을 리턴하는데 직접 설정도 가능

=>각각의 데이터는 [인덱스]를 이용해서 접근

=>범위에 해당하는 데이터에 접근할 때는 [정수인덱스:정수인덱스]의 경우는 정수 인덱스 앞까지이지만 인덱스를 문자열로 생성해서 대입하는 경우 [문자열인덱스:문자열인덱스]는 마지막 문자열인데덱스를 포함

[0:4] ->0부터 3까지

['apple':'mango'] ->apple부터 mango까지 범위 설정

=>인덱스 자리에 list를 대입해서 list에 포함된 인덱스들의 데이터만 추출 가능

 

#series DataFrame은 현재 모듈에 포함시켜서

from pandas import Series, DataFrame

#series DataFrame 을 제외하고는 pd로 접근

import pandas as pd

 

#Series 만들기

good1 = Series([1000,1500,500])

print(good1)

#이름이 같이 붙는다.

 

#데이터에 접근

print(good1[0]) #1개의 데이터 접근

print(good1[0:2])#연속된 범위의 데이터 접근 2는 포함이 안된다.

print(good1[0,2]) #불연속된 데이터 접근

 

 

#인덱스 설정

good1.index = ['Orange','Apple','Banana']

print(good1)

print(good1['Orange':'Banana'])

#Orange부터 Banana까지

 

 

2)연산

=>SeriesScala Data의 연산은 Broadcast연산(각각의 요소와 연산해서 결과를 다시 Series로 리턴)

=>Series끼리의 연산은 index를 기준으로 연산

None(numpy.nan)과의 연산은 결과가 무조건 None

=>없는 index와의 연산의 결과도 None

good1 = Series([100,200,150] ,index = ['1','2','3'])

good2 = Series([10,20,10],index = ['1','2','4'])

print(good1+200) #모든 요소에 200d을 더함

print(good1+good2)

#인덱스가 동일한 데엍끼리 연산

#1 2번은 양쪽에 같이 있어서 더하기

#3 4번은 한쪽에만 존재하기 깨문 None

 

 

good1 = Series([100,200,150,None, np.nan] ,index = ['1','2','3','5','6'])

good2 = Series([10,20,10],index = ['1','2','4'])

print(good1+200) #모든 요소에 200d을 더함

print(good1+good2)

#인덱스가 동일한 데엍끼리 연산

#1 2번은 양쪽에 같이 있어서 더하기

 

 

 

 

 

2.DataFrame

=>인덱스 컬럼이름을 가진 행렬(2차원 배열) - 테이블

=>통계에서 주로 사용

=>dictlist와 유사

=>외부 데이터를 가지고 생성하느 경우가 많고 직접 생성하는 경우는 dict를 주로 이용

하나의 keylist형태의 value를 실행해서 생성

 

 

 

#딕셔너리를 생성

items = {'name':['orange','mango'],

         'price':[2000,2500],

         'nanufacture':['korea','taiwan']}

#DataFrame을 생성

df = DataFrame(items)

 

print(df)

 

 

1)생성 가능한 데이터

=>dict

=>2차원 ndarray

=>Sereislist

=>dict ,list, tuple ,setlist

 

2)index

=>행에 붙이는 이름

=>직접 설정을 하지 않으면 0부터 시작하는 정수로 된 인덱스가 생성

=>생성할 때 index매개변수를 이용해서 직접 설정 가능

=>생성한 후 index속성을 이용해서 설정 가능

 

3)컬럼이름

=>열에 붙이는 이름

=>직접 설정하지 않으면 디폴트로 생성 :dict의 경우는 key가 컬럼이름으로 설정되고 그 이외는 정수

=>생성할 때 columns매개변수를 이용해서 설정이 가능

=>생성한 후 columns속성을 이용해서 설정 가능

 

4)테이블의 데이터 일부 확인

head(데이터 개수) : 앞에서 부터 데이터 개수 만큼 리턴

tail(데이터 개수): 뒤에서 부터 데이터 개수 만큼 리턴

 

5)info()

=>DataFrame의 개요 리턴

=>외부에서 데이터를 가져와서 DataFrame을 만들 때 headtail을 이용해서 데이터가 제대로 불려져 왔는지 확인하고 데이터의 개요를 확인하기 위해서 info()를 호출해서 사용

 

#딕셔너리를 생성

items = {'name':['orange','mango','apple','banana'],

         'price':[2000,2500,3000,5000],

         'nanufacture':['korea','taiwan','keorea','vetnam']}

#DataFrame을 생성

df = DataFrame(items)

 

#인덱스를 직접 설정

df.index = np.arange(10,50,10)

#3개의 데이터 확인

print(df.head(3))

 

#개요 확인

print(df.info()) #nan이 있으면 개수 가 다른다.

 

<class 'pandas.core.frame.DataFrame'> : 전체 데이터의 자료형

Int64Index: 4 entries, 10 to 40 : 행의 개수와 인덱스

Data columns (total 3 columns): 컬럼의 개수

name           4 non-null object : name이라는 컬럼은 4개의 데이터가 존재하고 자료형은 객체 (문자열)

price          4 non-null int64 : price라는 컬럼은 4개의 데이터가 존재하고 자료행은 정수

nanufacture    4 non-null object : nanufacture 이라는 컬럼은 4개의 데이터가 존재하고 자료형은 객체 (문자열)

dtypes: int64(1), object(2) : 1개의 컬럼은 정수로 되어 있고 2개의 컬럼은 객체

memory usage: 128.0+ bytes :메모리 사용량

None

 

=> 각 컬럼에 None의 개수를 파악할 수 있음

 

 

#sklean에서 제공하는 boston주택 가격 데이터 가져오기

import numpy as np

from pandas import Series, DataFrame

import pandas as pd

 

#sklean에서 데이터를 사용하기 위한 import

from sklearn import datasets

 

#boston 데이터 셋을 가져오기

boston = datasets.load_boston()

 

 

#자료형 확인  head오류

print(type(boston)) #키의 자료형 확인

print(boston.keys)

#<built-in method keys of Bunch object at 0x000001FE523639A8> method라는 것이다.

print(boston.keys())

#실제 데이터의 자료형을 확인

print(type(boston.data))

#DataFrame으로 변환

df = DataFrame(boston.data)

print(df)

 

#DataFrame으로 변환-컬럼이름을 확인해서 컬럼 이름 부여

#자져온 데이터 셋이 ndarray인 경우 데이터를 파악하기 가

#어려울 수 있어서 컬럼이름을 부여한 dataframem으로 가지고 있는 것이

#데이터 파악이 용이합니다.

#머신러닝에 적용할 때 는 df.values로 다시 ndarray로 만들면 된다.

df = DataFrame(boston.data,

columns = ['CRIM','INDUS','NOX','RM','LSTAT','B','PTRATIO','ZN','CHAS','AGE','RAD','DIS','TAX'])

print(df.info())

 

 

7)fwf파일 : 텍트스 파일인데 글자 수가  일정한 형태로 되어있는 파일

pandas.read_fwf(파일경로 ,widths=(글자수를 나열 ),

names=(컬럼이름 나열),

encoding= 인코딩 방식)

=>파일이 windows에서 기본 인코딩으로 만들어진 것이면 cp949(ms949)이고 그 이외의 운영체제에서는 만들어진 것이면 utf-8

 

import os

print(os.getcwd())

 

#data/data_fwf.txt파일의 내용을 가지고 dataFrame만들기

fwf = pd.read_fwf('./data/data_fwf.txt',width = (10,2,5),names =('날짜','종목이름','종가'),encoding = 'utf-8')

print(fwf)

 

 

 

8)csv파일 읽기

=>read_csv: 기본 구분자가 , 로 설정

=>read_table: 기본 구분자가 Tab

=>옵션 설정이 없으면 첫번째 행의 데이터가 컬럼이름 이 됩니다.

 

#item, csv파일을 읽어서 DataFrame 만들기

item = pd.read_csv('./Desktop/data/item.csv')

print(item.head())

print(item.info())

 

 

 

 

 

=>read.csv의 매개변수

path: 파일의 경로

sep: 구분자(기본은 , )

header: 컬럼이름에 행 번호로 기본값은 0, 첫번째 행이 컬럼이름이 아닌 경우는 None으로 설정

index_col: 인덱슬로 사용할 컬럼 번호나 컬럼 이름

names: 컬럼이름으로 사용할 list, header = None과 함께 사용

skiprows: 읽지 않을 행의 개수

nrows: 일부분만 읽는 경우 읽을 행의 개수

skip_footer: 마지막에 읽지 않은 행의 개수

encoding : 인고딩 설정

squeze : 행이 하나인 경우 Series를 만드는데 이 속성의 Trueㄹ 설정하면 DataFrame으로 생성

thousands: 천 단위 구분 기호 설정 ,이 설정을 하지 않은 상태에서 , 가 있는 데이터를 읽으면 문자열로 읽게 됩니다.

na_values :None 처리할 데이터의 list

parse_datas: 날짜 형식의 데이터를 datetime으로 변환할 지 여부

 

0 - 남자

1 - 여자

99 - 예상

[-,'99'] -None

날짜는 빼기 가능하다. 시계열 분석 가능하다.

한글이 있는지 없는지 있으면 encodng이다.

 

#item, csv파일을 읽어서 DataFrame 만들기

item = pd.read_csv('./Desktop/data/item.csv')

print(item.head())

print(item.info())

 

#good.csv파일을 읽어서 dataframe 만들기

good = pd.read_csv('./Desktop/data/good.csv',header = None, names=['제품명','수량','가격'])

print(good.head()) #컬럼 이름 이 되서 별로 보기 좋지 않다. ,header = None, names=['제품명','수량','가격']

print(good.info())

 

 

=>텍스트 파일의 용량이 큰 경우 (데이터가 많은 경우 )

log 분석을 하기 위해서 csv를 읽어오는 경우 실무에서 사용하는 데이터는 아주 큰 용량입니다.

한국 ebay의 경우 하루 로그기록하는 파일의 사이즈가 대략 8GB정도 됩니다.

이런 정도의 파일을 한 번에 읽어서 DataFrame을 만들게 되면 시스템이 멈추거나 아주 느리게 작업이 이루어지게 됩니다.

이런 파일은 분할해서 읽어야 합니다.

 

nrowsskiprows를 이용할 수 있습니다.

 

 

읽을 떄 chunksize(한 번에 읽을 행의 개수)를 설정 - 이 옵션을 설정하면 TextParser객체가 리턴 TextParseriterator(for)를 돌리면 chunksize단위로 데이터를 가져오게 됩니다.

 

 

 

#good.csv파일의 내용을 2개씩 읽어오기

goodchunk = pd.read_csv('./Desktop/data/good.csv',chunksize  =2, header = None)

print(goodchunk)

#TextFileReader

 

for two in goodchunk:

    #print(type(two))

    print(two)

#2개씩 찾아돈다.

 

아주 큰 싸이즈를 들고 올 때는 분할해서 들고 온다.

 

 

=>문자열이 작은 따옴표나 큰 따옴표로 묶여 있는 경우 또는 구분자가 1글자가 아니고 여러 글자인 경우에는 read_csv가 제대로 데이터를 읽지 못하는 경우가 발생할 수 있습니다.

csv모듈의 reader 객체를 이용해서 줄 단위로 읽어서 처리를 해야 한다.

 

 

 

#문자열이 작은 따옴표로 묶여 있는 경우

fruits = pd.read_csv('./Desktop/data/fruit.csv',header = None,sep="|") 

print(fruits)

   

#줄단위로 읽어서 dataframe만들기

import csv

lines = list(csv.reader(open('./Desktop/data/fruit.csv'),delimiter='|'))

print(lines)

 

#줄 단위로 읽어서 DATAFRAME으로 전화하면 된다.

fruits = DataFrame(lines, columns = ['이름','수령','가격'])

print(fruits)

 

 

9)CSV저장

=>SeriesDataFrame 객체가 to_csv함수를 호출

=>첫번째 매개변수는 파일 경로

=>sep는 저장될 때의 구분자를 생성

=>na_repNone값을 어떻게 출력할 것인지를 설정

=>index= None을 설정하면 인덱스는 출력되지 않음

=>header = None을 설정하면 컬럼이름이 출력되지 않음

=>cols에 컬럼이름의 list를 설정하면 설정한 컬럼들만 출력

 

 

#파일제 저장

fruits.to_csv('./Desktop/data/fruits.csv')

 

설정을 바꾸는 게 좋다. index = None해주는게 좋다.

 

 

 

 

 

10) excel파일 읽기

=>anaconda를 설치하지 않은 경우에는 xlrd패키지르 설치해야 합니다.

=>pandas.read_excel(엑셀 파일 경로)

=>pandas.excel.read_excel(엑셀 파일 경로)

=>함수들의 매개변수는 read_csv랑 유사한데 sheet_name옵션에 읽을 sheet이름을 설정해야 합니다.

 

 

11)excel파일 저장

=>ExcelWriter 객체를 만들고 DataFrame.to_excel(ExcelWriter객체 , sheet_name = '시트이름')

 

 

 

실습 - excel .xlsx파일에 읽기

=>한글이 포함되어 있고 첫번째 줄이 컬럼의 이름인 것을 확인

인코딩을 고려

 

#엑셀 파일 읽고 쓰기

excel = pd.read_excel('./Desktop/data/excel.xlsx',sheet_name = 'Sheet1')

print(excel)

 

writer = pd.ExcelWriter('./Desktop/excel.xlsx')

excel.to_excel(writer, sheet_name='연습')

writer.save() #엑셀로 저장

 

 

 

12)html페이지의 table 태그의 내용을 DataFrame으로 변환

pandas.read_html(경로)

=>천단위 구분기호 설정, 인코딩 방식, na 데이터 설정 등의 옵션이 있습니다.

=>하나의 페이지에 table 태그가 여러 개 있을 수 있기 떄문에 DataFramelist로 리턴

#pandas read_html 함수 도움말

help(pd.read_html)

 

 

li = pd.read_html('https://ko.wikipedia.org/wiki/%EC%9D%B8%EA%B5%AC%EC%88%9C_%EB%82%98%EB%9D%BC_%EB%AA%A9%EB%A1%9D',thousands = ',')

for df in li :

    print(df.head())

   

print(li[0])

#list가 와서 다른 형태로 쓰야 한다.

 

 

13)json데이터 읽기

=>pandas.read_json을 이용해서 읽습니다.

=>대다수의 데이터는 배열의 형태가 아니고 일반 객체 형태라서 바로 만들면 나중에 가공 작업이 필요한 경우가 많습니다.

 

 

[1,2,3,4,5,6,7,8,9,10]

list: 익덱스로 구분

dict: key로 구분

 

ndarraydataframe에서 dataframe이 편한다.

 

 

#json 데이터 읽기

movies= pd.read_json("http://swiftapi.rubypaper.co.kr:2029/hoppin/movies?version=1&page=1&count=20&genreId=&order=releasedateasc")

print(movies)

print(movies['hoppin'])

print(movies['hoppin']['movies'])

print(movies['hoppin']['movies']['movie'])

 

for temp in movies['hoppin']['movies']['movie']:

    print(temp['title'])

 

 

 

14.xml읽기

=>pandas에는 xml을 읽어서 만드는 함수는 없습니다.

이 경우에는 xml파싱을 수행한 후 직접 만들어야 합니다.

 

 

15)데이터베이스의 데이터를 가져고 DataFrame만들기

=>sqlalchemy 패키지: 관계형 데이터베이스에 접속해서 sql을 실행시켜서 데이터를 가져오는 패키지

 

=>sqlalchemy 패키지를 이용한 데이터베이스 연결 객체 만들기

from sqlalchemy import create_engine

연결객체 = create_engine(데이터베이스 url)

 

=>sql을 이용한 DataFrameㅇ만들기

pandas.read_sql_query(sql구문 ,연결 객체 ):sql구문 수행 결과를 가져오는 함수

pandas.read_sql_table(table이름 , 연결 객체 ): 테이블의 데디터를 전부 가져오는 함수

 

16)sqlite3pl테이블의 데이터 가져오기

#sqlite3의 데이터 가져오기

import pandas as pd

from sqlalchemy import create_engine

 

#연결 객체 생성

con = create_engine('sqlite:///data/sample.db')

 

#sql을 실행해서 dataframe만들기

pl = pd.read_sql('select * from pl',con)

print(pl)

 

 

17)오라클의 데이터 가져오기

=>cx_Oracle 이라는 패키지가 필요

=>Mac 에서는 바로 접근이 안되서 Oracle홈페이지에서 instant client라는 프로그램을 다운로드 에서 설치한후 /opt디렉토리에 oracle디렉토리르 생성하고 받은 파일의 압축을 해제

압축해제한 디렉토리에서 lib파일들을 /user/loacl/lib디렉토리에 복사를 해야 합니다.

 

=>접속 URL - oracle://유저id:유저비밀번호@ip:port/sid

 

#sqlite3의 데이터 가져오기

import pandas as pd

from sqlalchemy import create_engine

 

#연결 객체 생성

con = create_engine('oracle://유저id:유저비밀번호@ip주소:1521/xe')

dept = pd.read_sql('select * from dept',con )

print(dept)

 

18)mysql에서 데이터 가져오기

=>pymysql이라는 패키지가 필요

=>접속 url : mysql+mysqldb://유저id:유저비밀번호@ip:port/db이름

https://www.mysql.com/downloads/

 

gpl이 무료로 하는것

mysql->oracle인수해서 유료로 만들었다.

mariadbmysql 5점대하고 같다.

 

mysqldl

 

 

c++로 배포를 하게 되면 배포된 자리에 c++나 재배포 패키지가 설치되어 있어야 실행이 가능

mac , linuxc++이 할수 있지만 windows는 설치가 안되여 있다.

visual c++ 설치 를 해야 한다.

 

 

python에서 문제가 생기면 visual c++재배포 가능한것 설피 해야 한다.

 

--데이터베이스 확인

show databases;

--데이터베이스 생성

create database park;

--데이터베이스 설정

use park;

 

 

 

 

 

 

 

 

#mysql+mysqldb://유저id:유저비밀번호@ip:port/db이름

 

#sqlite3의 데이터 가져오기

import pandas as pd

from sqlalchemy import create_engine

import pymysql

 

pymysql.install_as_MySQLdb()

import MySQLdb

 

 

#연결 객체 생성

con = create_engine('mysql+mysqldb://root:1234@localhost:3306/park')

dbms = pd.read_sql('select * from dbms',con )

print(dbms)

 

 

 

 

 

 

3.datafram에서의 선택

1)열 선택

하나의 열은 DataFrame[열이름] 또는 DataFraem.열이름 으로 접근

여러개의 열은 DataFrame[[열이름나열]]

DataFrame[열이름: 열이름 ] ->마지막열이 포함됩니다.

 

2)행 선택

=>iloc[행의 위치]

=>loc[인덱스]

list형태나 :을 이용한 범위 형태 가능

하나의 행인 경우는 Series로 리턴되고 2개 이상인 경우는 DataFrame으로 리턴

 

3) 셀 선택

=>[컬럼이름][행번호]

=>loc[행인덱스,열인덱스]

=>iloc[행번호, 열번호]

 

 

#dATAFRAME에서의 선택

#item.csv파일의 데이터 가져오기

 

import numpy as np

import pandas as pd

 

#item.csv파일의 내용을 가져오기

item = pd.read_csv('./Desktop/data/item.csv')

#컬럼이름 :code, manufacture,name,price

print(item.head())

item.info()

 

#인덱스 설정

item.index = ['사과','수박','참외','바나나','레몬','망고']

 

print(item['name']) #하나의 열 선택

print(item[['name','price']]) #여러 개 열 선택

 

 

#행 선택

print(item.loc['사과'])

print(item.iloc[2])

 

 

 

print(item.loc['사과','망고']) #인덱스 로 접근

print(item.iloc[2,4]) #행의 위치로 접근

 

 

print(item.loc['사과':'망고']) #인덱스 로 접근

print(item.iloc[0:5]) #행의 위치로 접근

 

 

4)boolean indexing

=>locbool자료형의 series를 대입하면 TRUE인 행 만 추출

=>Seriesscala data와 연산을 하게 되면 BROADCAST연산을 수행해서 Series로 결과를 리턴

=>Seriesisin([값 나열])를 대입하면 값에 속한 것들만 True그리고 나머지는 FalseSeries를 리턴

 

 

#price 100 0 이상인 데이터만 추출

print(item[item['price']>= 1000])

 

 

#price 1000이나 1500 인 데이터

print(item[item['price'].isin([1000,1500])])

 

 

 

 

4.DATA탐색 관련 함수

1)head: 정수를 대입해서 정수만큼의 데이터를 앞에서부터 리턴

2)tail:정수를 대입해서 정수만큼의 데이터를 뒤에서부터 리턴

3)shape: 행과 열의 수를 tuple로 리턴

4)info: 데이터의 대략적인 개요

5)dtypes:각 컬럼의 자료형을 리턴

6)describe: 기술 통계 정보를 리턴하는데 include = True옵션을 추가하면 숫자가 아닌 컬럼의 정보도 리턴

7)count: 데이터 개수

8)value_counts: 각 값들의 개수인데 Series에만 사용

9)unique: 고유한 값 리턴

 

#데이터 탐색 함수

df = pd.read_csv("./Desktop/data/auto-mpg.csv")

print(df.head())

 

#기술 통계 정보 확인

print(df.describe())#숫자 데이터의 통계

print(df.describe(include = 'all'))#문잗 포함

 

 

#카테고리 형태의 데이터의 분포 확인

print(df['origin'].value_counts())

 

 

 

 

5.기술통계 함수

=>count, max, min, mean(평균),median(중간값),var(분산),std(표준편차)

=>skew(비대칭도 - 왜도 ),kurt(청도),sem(평균의 표준오차) 잔차 ,mode(최빈값)

왜도 좌우로 얼마나 틀어졌나 ?좌우로 얼마나 움직였나

청도 : 정규분포 내것이 얼마나 위 아래로 퍼졌너나 ? 뽀족함 위 아래

평균의 표준오차: 평균과차이 나는 것  잔차 :

평균 점수의 차이

90 80 85    평균이 85

+5 -5 0 ->잔차  

잔차의 합을 구하면 0으로 될 가능성이 있다. 퍼지는 것이 대해서 그다지 효율적이지 않는다.

거리의 개념으로 찾아서 제곱해서

25 25 0 ->제곱해서 합을 구하는 것이 분산이다.

25+25+0 / 3 = >

통계학에서는 25+25+0/ 3-1 =

빼기 1을 하자

 

 

70 , 85 , 105 -> 평균이 85

 

누가 더 고르냐 ?

25 + 25 /2 = 25

15의 제곱 + 15의 제곱 / 2

분산을 사용하면 편향이 심해진다. 그래서 ROOT를 씌워준다.

225ROOT

편향 때문에 데이터를 줄인다.

 

 

 

보통은 중간값이나 MODE를 하는 것이 많다.

 

 

=>argmin, argmax,idxmin,idxmax,

arg->위치  idx ->인덱스

=>quantile(4분위수 - 25%, 50%, 75%, )

max, min , quantile 같이 보면 대략적인 분포를 볼 수 있다.

=>descrive(요약정보)

=>cumsum, cumprod,cummax, cummin:누락

=>diff(앞 데이터와의 차이)

=>pct_changes(앞 데이터와의 차이를 백분율로 출력)

=>unique: 고유한 데이터들의 배열 리턴

=>DataFrame에서 axis옵션을 0이나 1을 설정하면 행과 열방향 반대

=>skipna 옵션을 True로 설정하면 None값을 제외하고 그렇지 않으면 None값을 포함

 

#cyl 컬럼의 평균

print(df['cyl'].mean())

 

stock = pd.DataFrame({'다음':[1000,1200,1960]})

print(stock['다음'].diff()) #각 행의 차이

print(stock['다음'].pct_change()) #각 행의 차이 를 비율로

# NaN, (1200-1000)/1000 , (1960-1200)/1200

 

6. 공분산과 상관계수

=>공분산은 cov()

=>상관계수는 corr()

=>Series를 이용할 때는 Series객체가 함수를 호출하고 다른 Sereis객체를 매개변수로 대입

=>DataFrame은 함수만 호출하면 모든 컬럼의 공분산이나 상관계수를 출력

 

1)공분산(covariance)

=>2개의 확률 변수의 상관정도를 나타내는 수차

=>분산은 하나의 확률 변수의 이산정도를 나타내는 수치

=>공분산은 2개의 컬럼 사이의 관계를 파악한 수치

하나의 컬럼의 값이 증가하는 추세를 보일 때 같이 증가하면 양수이고 감소하면 음수가 됩니다.

공분산은 하나의 값이 증가할 때 다른 하나의 값이 얼마나 증가하는 지 또는 감소하는 지를 수치화

 

 

 

 

a 100 -> 200

b 5 -> 15

값의 범위에 따라 서 a2b3배 하지만 a100 b10

공분산은 증가한 값

 

 

2)상관계수

=>공분산과 개념은 같은데 값의 범위를 -1~ 1까지으로 제한

하나의 컬럼의 값이 증가할 때 동일한 비율로 증가하면 상관계수는 1

하나의 컬럼의 값이 감소할 때 동일한 비율로 증가하면 상관계수는 -1

절대값 0.6 이상이면 상관이 높다라고 하고 0.4 정도 이상이면 상관이 있다라고 하고 0.4이하면 상관이 없다라고 합니다.

상관계수가 0인 경우는 상관이 없다라는 것이지 관계가 없다라는 표현이 아닙니다.

=>피어슨 상관계수 : 비율을 가지고 구하는 상관계수 - 선형 관계인 경우 적합

=>스피어만 상관계수 : 값의 증가와 감소에만 집중하는 상관계수 - 비선형 관계에 적합

=>캔달 순위 상관계수 : 순위를 가지고 상관계수를 구함

 

피어슨 상관계수는 비율이 1로 차이나야 한다. 늘어난 비율이 달라야 한다.

비율이 안 맞고 하면 캔달 순위 상관계수 : 국어를 잘하면 영어를 잘하더라 점수는 95점이지만 다른 분이 100점 일 경우 국어 , 영어는 같은 비율이 아니다.

잴 먼저 찾아야 하는 것은 상관계수

 

 

 

 

 

 

3)상관계수 대신 사용하는 것들

=>산점도나 선 그래프를 그려서 데이터 간의 관계를 파악할 수 있습니다.

상관관계는 산점도나 등 cor, cov

 

#데이터 탐색 함수

df = pd.read_csv("./Desktop/data/auto-mpg.csv")

print(df.head())

# weight mpg의 상관계수 확인

#둘 다 음수가 나왔고 0.6 이상이므로 음의 상관관계

print(df['weight'].corr(df['mpg']))

#-0.8322442148315753 음의 상관계수

print(df['hp'].corr(df['mpg']))

#-0.7784267838977759

 

#상관관계가 0인데 계속 뽑아내면 의미가 없다.

 

 

 

 

7.정렬(sort)

=>sort_index()호출하면 인덱스 순서대로 오름차순 정렬

axis=1 을 대입하면 컬럼의 이름 순서대로 오름차순 정렬

ascendingTrue을 대입하면 내림차순 정렬

=>Series객체는 sort_values()를 호출

=>DataFrame에서 특정 컬럼을 가지고 정렬을 하고자 하는 경우에는 sort_Values함수에 by 매개변수로 컬럼의 이름을 list로 대입하면 됩니다.

 

 

 

print(df['hp'])

print(df['hp'].sort_values()) #오름 차순 정렬

print(df['hp'].sort_values(ascending= False)) #내림차순 정렬

 

#hp 오름차순 그리고 값이 같으면 cyl 오름차순 정렬

print(df.sort_values(by=['hp','cyl']))

 

 

 

8.rank

=>순위를 구해주는 함수

=>asendingFalse로 설정하면 내림차순으로 순위를 구함

=>동점인 경우의 순서는 method를 이용해서 설정할 수 있는데  max를 대입하면 큰 순위로 min을 대입하면 작은 순위로 그리고 first를 설정하면 먼저 등장한 데이터가 작은 순위로 대입

 

                       max      min   first        기본

100 -1              1          1          1          1

90 -4                4          4          4          4

93 -2                3          2          2          2.5      

93 -2                3          2          3          2.5

87 -5                5          5          5          5

max하면 3으로 하고

min이면 2로 한다.

min은 우리가 보통 사용하는 것

 

 

 

9.rename

=>컬럼이나 인덱스의 이름을 변경할 때 사용하는 함수

=>indexcolumns매개변수에 {기존이름: 새로운이름...} 의 형태로 대입하ㄴ면 indexcolumns를 수정해서 새로운 DataFrame을 리턴

=>axis 꼭 기억하기

inplace = True

=>inplace=True옵션을 추가하면 함수를 호출한 DataFrame을 변경합니다.

메모리 문제 때문에 메모리 사용량을 줄이기 위해서

없으면 새로 만들어진다. 계속 복사본을 만들면 멈출수 있다.

추천 시스템을 만들 경우 R로 하면

 

A B F D

A C F K

A C

옆으로 15 아래로 10

15 * 10 ->r에서 메모리가 8기가 되면 10분 걸린다.

 

 

 

10.인덱스 재구성

=>reindex속성을 이용해서 인덱슬르 재배치 가능

=>set_index('열이름'또는 열이름의 list ) :열로 index로 생성하는데 열은 데이터에서 제거

=>reset_index():인덱스가 제거되고 0부터 시작하는 숫자로 초기화: 그룹화에서 많이 사용

 

 

#item.csv내용 가져오기

item = pd.read_csv('./Desktop/data/item.csv')

print(item)

 

#순위 출력

print(item.rank())

print(item.rank(method = 'min'))

 

 

 

 

 

 

 

 

 

 

print(item['code'].rank(method = 'min'))=>하나의 열

 

#코드를 index로 만들기

item.set_index('코드')

item

 

#코드를 index로 설정   데이터에서는 제거

item.set_index('코드',inplace = True)

print(item)

 

 

item.reset_index('코드')

print(item)#코드를 index로 설정   데이터에서는 제거

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-6  (0) 2020.11.10
데이터분석-5  (0) 2020.11.09
데이터분석-3  (0) 2020.11.08
데이터분석-2  (0) 2020.11.08
데이터 분석-1  (0) 2020.11.08
반응형

데이터 분석이나 머신 러닝에서 많이 사용하는 페키지

=>백터 연산을 수행하기 때문에 요소 각각에 연산을 수행하는 경우 기존의 list,tuple, set에 비해서 연산 속도가 빨라서 머신러닝이나 딥러닝에서 사용

=>자료구조 패키지: numpy, pandas- 데어터를 만들고 수집하고 가공하는 페키지

=>시각화 패키지: maptlotlib, seaborn, pandas, folium(지도 , 단계구분도)

=>통계 : scipy

=>머신러닝: sklearn

=>머신러닝, 딥러닝:tensorflow, keras, pytorch

 

 

=>numpy ndarray가지고 하는 일들은 대부분 list로도 대체 가능

 

ndarray -> 배열이라고 부르기도 한다.

 

python  list 자료구조

list: 순차적 연산

ndarry : 백터 연산 하나하나 씩 연산해서 속도가 빠르다.

 

 

pythoniterator 객체는  __iter__

iterator:순선대로 데이터 접근이 가능한 데이터의 모임

 

**numpy

=>고성능 과학 계산이나 선형대수를 위해서 제공되는 패키지

1.ndarray - numpy가 제공하는 데이터의 모임(자료구조)

=>백터 연산을 수행하기 때문에 요소 각각에 연산을 수행하는 경우 기존의 listtuple, set에 비해서 연산속도가 빨라서 머신러닝이나 딥러닝에서 사용

 

1)기본적인 생성

=>ndarray((행의 수 (,....))):데이터의 개수를 직접 지정해서 생성, 권장하지 않음(생성자)

=>array(iterator):기존의 데이터의 모임을 가지고 생성

생성할 떄 dty[e매개변수를 이용해서 데이터 각각의 자료형을 지정 가능

dtype을 설정하지 않으면 자료형을 유추해서 생성

 

2)구조 파악을 위한 속성

=>dtype : 각 요소의 자료형

=>ndim 배열의 차원

=>shape: 각 차원의 크기를 tuple로 리턴

=>size: 데이터 개수

=>itermsize: 각 요소의 메모리 크기

=>nbytes: 전체 메모리 크기

 

 

3). 실습

#작업 중인 디렉토리

 

import os

print(os.getcwd())

 

#save as해서 다른데로 이동하면 이파일과 상관없이 다른데로 이동한다.

#현재 작업 디렉터리는 변할 수 있다.

 

#numpy import

#numpy np라는 이름으로 사용

import numpy as np

 

#list

li = [100, 300, 200]

#print(dir(li))

ar = np.array(li)

print(ar)

 

tu = (100, 200)

#print(dir(tu))

ar = np.array(tu)

print(ar)

 

#2차원 배열

ar = np.array([[100,200,300],[400,500,600]])

print(ar)

 

#서로 다른 자료형의 데이터가 모여 있으면 동일한 자료형으로 변경합니다.

ar = np.array([['100',200,300],[400,500,600]])

print(ar)

#각 요소의 자료형

print(ar.dtype)

 

#dtyped을 설정해서 정수 배열로 만들기

ar = np.array([['100',200,300],[400,500,600]],dtype=int)

print(ar)

#각 요소의 자료형

print(ar.dtype)

 

 

print(ar.ndim) # 전체 차원을 리턴

print(ar.shape) # 각 차원의 데이터 개수를 튜플로 리턴

 

 

2.일정한 숫자 패턴을 이용한 생성

=>arrange(start, stop, step, dtype)

start부터 stop 바로 앞까지 step간격으로 생성하고 자료형은 dtype으로 설정

start는 생략가능한데 생략하면 0

step은 생략 가능한데 생략하면 1

dtype은 생략하면 정수

 

 

=>linspace(start, stop, num = 50 , endpoint = True, retstep = False, dtype = None, axis = 0)

start부터 stop까지는 num의 개수를 일정한 간격의 배열을 만들어서 리턴

axis는 축 - 01을 변경하면 축의 방향이 변경됩니다.

              0 이 행이면 1은 열 , 0이 열이면 1은 행

 

#linspace는 기본적으로 stop이 포함됩니다.

#마지막 숫자를 제거하고자 하면 endpoint() false로 설정

ar = np.linspace(0,10,num = 11)

print(ar)

 

 

 

행이나 열이나 drop(0 ,axis = 1)

 

3.특수 행렬을 위한 array(배열) 생성

=>zerosones라는 함수를 이용해서 0이나 1로 채워진 함수를 생성할 수 있음

=>zeros_likeones_like함수는 배열을 매개변수로 받아서 그 배열의 모든 요소를 0이나 1로 채워진 배열을 리턴

=>emptyempty_like는 초기화하지 않은 값으로 배열을 생성

 

int a:

java는 변수가 아니다. 동적 실행

 

 

 

int a ; a

a = 10   a=10

공간만 확보해서 의미 없는 값만 넣는 것이다.

 

=>eye함수는 단위행렬 - 대각선 방향으로 1이 채워진 배열

이 함수에 매개변수로 열의 개수 나 k라는 매개변수로 이용해서 대각의 위치를 설정

 

1 0 0

0 1 0

0 0 1

 

k = 1

0 1 0

0 0 1

0 0 0

 

=>행과 열 수 가 같은 행렬(정방행렬)을 매개변수로 받아서 대각 요소만 가지고 다시 배열을 만들어 주는 diag도 있음

 

=>이런 함수들을 이용해서 직접 배열을 생성해야 하는 경우는 드물고 라이브러리들이 내부적으로 이러한 배열들을 생성

 

 

희소 행렬 : 0 이 대부분이고 1이 드문 행렬

 

0 0 0 0 1

0 0 0 0 0

0 0 1 0 0

0 0 0 1 0

 

4* 5 행렬이고 [(0,4), (2,2),(3,3)]

 

 

class 1 2 3 .. ->카테고리(범주형 )

 

원핫 인코딩

1 2 3

1 0 0

0 1 0

0 0 1

 

 

 

#단위 행렬 마들기(대각선 방향의 요소만 1인 행렬)

#정방 행렬 - 1 행과 열의 개수가 같은 행렬

#단위 행렬은 정방행렬이어야 합니다.

 

#크기가 3인 단위 행렬 생성

ar = np.eye(3)

print(ar)

#1의 위치를 1개 증가

ar = np.eye(3, k = 1)

print(ar)

#대각 요소만 뽑아서 1차원 배열을 생성

ar = np.diag(ar)

print(ar)

 

4.희소 행렬(Sparse Matrix)

=>0이 아주 많고 다른 데이터가 드문 행렬

=>반대되는 행렬은 밀집행렬(Dense Matrix) -배열을 Dense List라고 하기도 합니다.

=>scipy패키지의 sparse모듈을 이용해서 생성

csr_matrix라는 함수에 ndarray를 대입하면 됩니다.

=>밀집행렬로 변환하고자 할 때는 toarray()를 호출하면 됩니다.

=>넷플릭스와 같은 곳에서 고객이 본 영화를 행렬로 만든다면 고객은 거의 모든 영화를 보지 않았을 가능성이 큽니다.

밀집행렬로 만들게 되면 메모리 부담이 큼

이런 경우는 고객이 본 영화의 대한 부분만 저장하면 부담이 적습니다.

이런 경우에 희소행렬을 이용합니다.

 

#최소 행렬과 밀집 행렬 변환

import numpy as np

#scipy sparse모듈 가져오기

from scipy import sparse

 

#5 * 5 단위 행렬 생성

ar = np.eye(5)

print(ar)

 

#희소 행렬과 변환 - 0이 아닌 값의 위치와 값을 저장

sp = sparse.csr_matrix(ar)

print(sp)

 

 

 

5.ndarray의 자료형

=>생성할 때 dtype매개변수로 설정 가능

=>dtype속성으로 확인 가능

=>생성한 후 astype 함수를 호출해서 자료형을 변경할 수 있음

=>정수 자료형 : int8 , 16, 32, 64, unint8 , 16, 32, 64

unit는 음수가 없는 자료형

=>실수 자료형 : float 16 , 32, 64, 128

=>복소수 자료형 :complex64,128, 256

=>bool

=>object: 기본 자료형 이외의 클래스로부터 만들어진 인스턴스

=>string_ : 문자열

=>unicode_: 유니코드 문자열

 

 

6. 행렬 변환

1)reshape()행렬의 차원이나 크기를 변경할 떄 사용, 차원을 변경할 때는 튜플로 각 차원의 개수를 설정하면 됩니다.

-1을 대입하면 1차원 배열로 만들어 집니다.

 

2)flattern함수를 이용하면 다차원 배열을 1차원 배열로 변환해주는 함수

 

3)reshape는 배열을 변경하는 것이고 flattern은 새로운 배열을 만들어서 리턴해주는 함수

 

#행렬의 차원 변환

ar = np.arange(0 ,10)

print(ar)

 

#행은 2개열 5개 배열로 변환

print(ar.reshape(2,5))

 

7, 배열의 요소 선택

1)1차원 배열의 경우는 list와 유사

=>배열명[인덱스]를 이용하면 인덱스 번째 데이터 리턴

=>인덱스에 음수를 리턴하면 뒤에서부터 순서대로 접근해서 데이터 리턴

=>배열명[시작위치:종료위치]를 이용하면 시작위치부터 종료위치 앞까지 데이터를 리턴 시작위치를 생략하면 0 종료 위치를 생략하면 len(배열) 처럼 마지막 인덱스 뒤

:만 입력하면 전체

 

 

2. 다차원 배열

=>[인덱스][인덱스] 형태처럼 인덱스를 설정해도 되고 [인덱스 , 인덱스 ]로 설정해도 됩니다.

=>인덱스를 생략하면 전체가 됩니다. [][인덱스]하면 행 전체

[인덱스][]하면 열 전체

 

 

 

3)인덱싱을 이용해서 가져온 데이터들은 링크가 전달

복제를 하고자 하면 copy()를 호출

 

numpy는 분석할려고 하는 것이 아니다. 과학 기술 개선할라고 만들어진 라이브러리이다.

R

그 외의 언어

분석

프로그램 개발

 

복제도 있고 원본에 작업 도 함

데이터 작업이 전부 copy

파이썬의 분석 라이브러리

대표적인 것 : pandas

 

 

 

 

#인덱싱과 copy

import numpy as np

ar = np.array([100,200,300,400])

 

br = ar[0:2]

print(br)

 

#0-1 번 까지 요소를 br에 링크를 전달

br = ar[0:2]

print(br)

 

#원본 데이터를 변경 - ar의 데이터를 변경하면 br의 데이터도 변

ar[0]  = 10000

print(br)

 

 

#데이터를 복사해서 전달

cr = ar[0:2].copy()

print(cr)

 

#원본을 변경하면 br은 변경되지만 cr은 변경 안됨

ar[0] = 1300

print(br)

print(cr)

 

 

 

 

8.Fancy Indexing

=>list를 이용해서 인덱싱

=>Fancy Indexingcopy를 생성

배열명[[인덱스 나열]]의 형태

=>2차원의 경우에는 ix_ 라는 함수를 이용해서 Fancy Indexing 이 가능

배열명.ix_(행의 list,열의 list)

 

#import numpy as np

#쓰게기 값을 가지고 배열을 생성

#ar = np.empty((10,5))

ar = np.empty((10,3))

print(ar)

 

#행들을 선택 - 0,1,3,5 선택-copy

br = ar[[0,1,3,5]]

print(br)

 

 

#현재는 같은 값을 가지고 있음

print(ar[0,0])

print(br[0,0])

 

ar[0,0] = 90

 

#copy 되었으므로 ar 데이터가 변경되더라도

#br 데이터는 영향을 받지 않음

print(ar[0,0])

print(br[0,0])

 

 

#3,5 행과 0,2 열의 데이터 추출

cr = ar[[3,5],[0,2]] #3,0 5,2번만 추출

print(cr)

 

#3,5번행 그리고 0,2 열을 선택

dr = ar[np.ix_([3,5],[0,2])]

print(dr)

 

 

 

 

 

9.행과 열 전치(Transpose)

=>행과 열의 위치 변경하기

=>2차원의 경우는 T라는 속성으로 변경

=>transpose()는 함수를 이용할 수 있는데 이 함수는 매개변수로 축의 순서를 list로 전달 받습니다.

2차원의 경우는 생략하면 행과 열을 변경

3차원 부터는 달라진다.

3차원의 경우는 행, , 면의 순서를 listㄹ 설정할 수 있습니다.

#행과 열의 순서 변경

ar = np.arange(0,16)

print(ar)

 

 

#2차원 배열로 변환

br = ar.reshape(4,4)

print(br)

#행렬 변환

print(br.T)

print(br.transpose())

 

#3차원으로 변환

cr = ar.reshape((2,2,4))

print(cr)

 

#4,2,2 로 변경

print(cr.transpose())

#2,4,2로 변경

print(cr.transpose(0,2,1))

 

10.python에서 함수 생성

1)일반적인 함수 생성

#매개변수 없을 수 있음

def 햠수이름(매개변수 이름 나열):

           함수 내용

           return 데이터 #생략 가능

 

2)람다 함수 - 1줄 짜리 이름없는 함수

lambda매개변수 : 함수 내용

 

 

11.배열의 모든 요소에게 함수를 적용한 후 그 결과를 리턴받기

1)for를 이용해서ㅓ 배열의 모든 데이터를 순회하면서 적용

 

2)numpy vectorize를 이용

=>numpy.verctorize(함수내용)을 호출해서 백터화된 함수를 만들고 이 함수에 배열을 대입하면 함수를 수행한 결과를 가지고 배열을 생성해서 리턴해 줍니다.

=>이 방법은 for를 이용해서 구현 했기 때문에 속도가 빠르지는 않음

 

3)함수는 매개변수가 1개이고 반드시 리턴을 해야 합니다.

매개변수는 배열의 각 요소가 대입되고 리턴을 받을 것을 가지고 새로 배열을 만들어야 하기 때문입니다.

 

java에서는 class안만들고 클래스 하는 것 annonymous ->lambda

 

 

#배열의 모든 요소에게 함수를 적용해서 새로운 배열 만들기

ar = np.arange(0,5)

#위의 배열에  전부 5를 더한 결과를 가지고 새로운 배열을 생성

def plus5(x):

    return x +5

 

#백터화된 함수를 생성

#vec_func = np.vectorize(plus5)

#람다 함수 이용

#람다 사용한 원인 함수 만들고 하는 것보다 람다가 더 좋다.

#쓰기는 어렵지만 더 좋다.

vec_func = np.vectorize(lambda x: x+5)   

 

 

#백터화된 함수를 적용

result = vec_func(ar)

print(result)

 

12.연산자 오버로딩

=>파이썬이 제공하는 연산자를 클래스 안에서 다시 정의 해서 사용하는 것

=>__함수이름__를 재정의를 하면 연산자를 사용할 수 있도록 해줍니다.

대표적인 예가 __add__(a,b)메소들르 재정의하면 +연산을 사용할 수 있습니다.

__sub__ 메소드를 재정의 하면 - 연산을 사용할 수 있습니다.

__iter__메소드를 재정의하면 for를 사용할 수 있습니다.

=>dir로 확인한 속성이나 메소드 중에서 __로 시작하는 것들은 이름을 직접 호출하는 것이 아니고 다른 방시긍로 호출해야 합니다.

python에서 __로 시작하는 것은 객체 지향 언어의 private에 해당합니다.

 

 

13.ndarray 의 연산

1)동일한 차원을 갖는 array의 연산

=> 산술 연산 , 비교연산(>,>=,<. <= ,==, !=) , 할당 연산(+=, -=, *= , /=) 을 수행할 수 있음

=>위치가 동일한 데이터 끼리 연산을 해서 연산을 수행ㅇ한 배열과 동일한 차원의 동일한 크기의 배열을 리턴

 

 

=>numpy.logical_and(a,b) : a 배열의 원소와 b배열의 원소가 모두 true이면 true  지울때

=>numpy.logical_or(a,b): a배열의 원소와 b 배열의 원소가 모두 False이면 False그렇지 않으면 True 삽입할 때

=>numpy.logical_xor(a,b): a배열의 원소와 b 배열의 원소가 같으면 False 다르면 True 비교할 때

=>차원도 같아야 하지만 데이터의 개수도 같아야 합니다.

and , or , not 이 빠르다.

 

 

#동일한 차원에 동일한 크기의 배열 연산

#각 요소마다 연산해서 동일한 크기의 배열로 리턴

import numpy as np

 

ar = np.arange(1,6)

#100부터 105까지 5개로 분할 하는데 마지막 숫자는 미포함

br = np.linspace(100,105, num = 5, endpoint = False)

 

print(ar)

print(br)

 

#덧셈 => 숫자 배열

result = ar + br

print(result)

#두개 다 1 5열 배열로 리턴한다.

 

#크기비교 => bool배열

result = ar > br

print(result)

#논리 연산 0이 아닌 숫자는 True

result = np.logical_xor(ar, br)

print(result)

 

 

2)차원이 다른 크기의 연산 - broadCAST연산

=>배열과 scala data(1)은 배열의 모든 요소와 scala data와 연산을 해서 그 결과를 배열의 차원과 크기가 동일한 배열로 리턴

=>차원이 다른 배열의 연산은 적은 차원의 배열을 큰 차원의 배열에 전부 연산해서 큰 차원의 배열로 리턴 - 차원은 다르지만 연산을 하는 배열끼리의 크기는 같아야 합니다.

 

[10,20,30] + 4 = [14,24, 34]

 

 

 

 

 

 

 

 

  

 

 

 

+ 3 =

 

 

+ 3

+ 3

+ 3

+ 3

+ 3

+ 3

+ 3

+ 3

+ 3

 

 

 

[10,20,30]

+

[[10,30,50]

[20,40,70]]

 

=

[[20,50,50]

[30,60,100]]

 

[10,20,30]

+

[[20,40]

[60,70]]

=>이 경우는 연산을 못한다.\

r은 복제해서 연산한다.

 

 

#차원이 다른 배열의 연산 - broadcast

ar = np.array([100,200,240])

#배열의 각 요소에서 100을 뺀 후 배열로 리턴

result = ar - 100

print(result)

 

br = np.arange(0,6)

cr = br.reshape(2,3)

print(cr)

 

 

result = ar + cr

print(result)

 

dr = br.reshape(3,2)

result = ar + dr

print(result)

 

 

14.boolean indexing

=>인덱스 자리에 bool의 배열을 대입하면 True에 해당하는 인덱스의 데이터만 리턴

 

 

#boolean의 색인

ar = np.array([100,200,301, 28])

 

print(ar % 2 == 0 )

 

#배열의 인덱스 자리에 bool배열을 대입하면 true인 데이터만 리턴한다.

print(ar[ar % 2 == 0 ])

 

 

 

15.난수 (random)

=>seed: 난수표 번호 - 함수들에서는 random_state라는 옵션으로 사용

=>복원 추출 : 뽑아낸 데이터를 다시 집어 놓고 다시 추출하는 (주사위)

=>비복원 추출 : 뽑아낸 데이터를 다시 집어 놓지 않고 남은 데이터에서 추출하는 것

=>numpy.random모듈이 난수를 추출하는 모듈

=>seed라는 함수를 이용해서 seed설정

 

seed == random_state

 

랜덤의 원리

=>난수 표 하나를 선택해서 데이터를 순서대로 가져옵니다.

=>난수표 번호를 sedd가록 합니다.

seed(1)

7,6,4

 

seed(1)

7,6,4

 

시드가 같으면 같은 숫자 나온다.

 

10개 주면 다른 숫자로 나온다.

 

seed(1) ->7,6,4

seed(2) -> ???? 누구도 모른다.

random한것 뽑고 싶어면 seed를 바꿔가면서 해야 한다.

 

샘플 뽑을 떄는 한 번만 하면 안된다.

 

c언어는 seed가 정적이다.

javaseed에 현재 시간이 들어간다. 1000분의 1초가 들어간다. javaseed가 바꾼다.

 

게임의 대부ㄴ분은 random이 아니라 규칙이 있다.

규칙이 없으면 낮은 확률이 앞에 나오면 뒤쪽에 배치한다.

 

선물은 끝날 때 떨구고 마지막에 떨군다.

 

 

 

=>permutation(): 정수를 대입하면 0 부터 정수 이전까지의 배열을 랜덤하게 생성해서 리턴

배열을 대입함녀 배열의 데이터를 랜덤하게 배치해서 리턴 =>화투 섞는 것

비슷한 용도의 함수로 shuffle()이 있음

=>rand(): 균등 분포에서 표본 추출 -seed()를 정해서 순서대로 리턴 =>난수 빼서 하나씩 꺼내는 것

=>randint()범위를 설정해서 범위 내의 정수 중에서 리턴,size.를 이용해서 개수 지정 가능 =>숫자 범위 에 꺼내는 것

=>normal: 균등 분포가 아니라 정규분포 에서 표본을 추출 - size를 이용해서 개수 지정 가능

=>binomial(n,p,size) :n은 데이터의 분포( 10 - 0부터 10까지),p는 확률

 

균일 붙포 : 확률이 똑같다.

 

참 거짓  ->베르노이분포 - 스팸이냐 아니냐 ->감정 분포

 

이항 분포도 참이냐 거짓이냐 하지만 참일 경우는 여러개

 

python에는 random이 있고 기능이 부족해서

numpy random으로 만들어 졌다.

 

 

 

#난수 생성

import numpy as np

#배열 생성

ar = np.arange(0,48)

#print(ar)

#배열의 데이터 순서를 랜덤하게 배치

np.random.shuffle(ar)

print(ar)

 

 

 

#5개의 랜덤한 숫자를 추출

print(np.random.normal(size=5))

#seed고정 - 실행할 때 마다 동일

np.random.seed(seed = 100)

#5개의 랜덤한 숫자를 추출

print(np.random.normal(size = 5))

 

 

 

 

16.numpy의 함수 - pandasSeriesDataframe에서 그대로 사용 가능

1)기본 통계 함수

sum(합계), mean(평균), median(중간값), max(최대값), min(최소값), var(분산), std(표준편차), percentile(데이터와 백분율을 입력받아서 백분율에 해당하는 데이터를 리턴)

=>잔차 :평균과의 차이 - 잔차의 합은 :+-가 존재하기 깨문에 값이 상쇄되서 데이터의 분포를 이해하는데 어려움이 있어서 제곱한 분산을 사용

 

=>분산 : 평균과의 차이를 제곱한 것

=>표쥰편차:분산의 제곱곤

=>표준 편차를 계산 할 때 데이터 개수를 나누지 않고 데이터 개수 -1 로 나눕니다.

=>2차원 이상의 배열일 때 axis옵션을 이용하면 행이나 열 단위로 통계 함수를 적용 가능

 

#기본 통계함수

ar = np.arange(1,10)

ar = ar.reshape(3,3)

print(ar)

#2차원 행렬

 

#모든 데이터를 더한 결

print(np.sum(ar))

 

#행 단위 열 단위로 합계

#axis 옵션은 차후로도 동일한 용도로 사용되므로 기억

print(np.sum(ar, axis = 0)) #열 단위

print(np.sum(ar, axis = 1)) #행 단위

#둘은 항상 반대이다.

 

 

 

2)배열 통계

=>argmin, argmax: 최소값과 최대값의 인덱스를 리턴

=>prod:

=>nansum, nanprod: None01로 간주해서 합과 곱을 구해서 리턴

None과의 연산은 무조건 None

=>cumsum, sumprod: 누적합과 누적곱

=>diff: 앞 요소와의 차이를 배열로 리턴

 

3)Nonenumpy.nan으로 표기

 

 

4)논리 함수

numpy.isnan():nan포함 여부 리턴

 

=>여기 까지는 단항 함수 (Unary -데이터가 1개만 있으면 수행되는 )함수

 

 

 

17.numpy의 이항 함수 - 데이터가 2개 있어야 수행되는 함수

=>add, subtract, multiply, divide, floor, divide

=>power(첫번째 배열의 데이터에 두번째 배열의 데이터만큼 제곱)

=>maximum ,minimum, fmax, fmin

=>mod

=>greater, greater_equal, less, less_equal, equal, not_equal

=>logical_and, logical_or, logical_xor

 

 

 

=>where (bool배열 , true일 때 선택할 데이터 , false일 때 선택할 데이터)

#2개의 배열에서 데이터 골라서 새로운 배열 만들기

ar = np.array([100,200,300,400])

br = np.array([101,201,301,401])

#cond값의 True이 면 or에서 False이면 br;서 출력

cond = np.array([True, False, False, True])

result = np.where(cond,ar,br)

print(result)

 

 

 

 

 

18.집합관련 함수

=>unique :중복 제거

=>intersect1d():교집합

=>union1d():합집합

=>in1d():데이터의 존재 여부를 bool 배열로 리턴

=>setdiff1d():차집합

=>setxor1d(): 어느 한 쪽에만 존재하는 데이터

 

19.배열을 분할해주는 함수

=>split

=>axis옵션을 이용해서 행방향으로 분리할지 열방향으로 분리할 지 설정할 수 있음

=>첫번째 파라미터는 배열이고 두번째 파라미터는 데이터의 개수인데 정수 대신에 list를 사용하면 list에 있는 숫자 대로 데이터를 분할합니다.

 

 

20 .데이터 정렬

=>sort

=>kind옵션에 정렬 방법을 설정

=>numpy.sort에 배열을 대입하면 정렬한 데이터를 리턴

배열.sort를 하게되면 배열자체를 정렬합니다.

 

 

#e데이터 정렬

ar = np.array([30,200,300,400,210,40])

help(np.sort)

#help(ar.sort)

result = np.sort(ar)

print(result)

print(ar)

#기본은 quicksort 잴 빠르다. 분할 하면 서 한다.

#merge는 합쳐가면서 하는 것이고

#heap 부모가 크는 것

 

 

br = ar.reshape(2,3)

print(br)

br.sort()

print(br) #행열이 뒤집어 진다.

#[[ 30 200 300]

# [ 40 210 400]] 아래로 정렬

 

br = ar.reshape(2,3)

print(br)

br.sort(axis = 1)

print(br) #행열이 뒤집어 진다. #열 단위로

 

br = ar.reshape(2,3)

print(br)

br.sort(axis = 0)

print(br) #행열이 뒤집어 진다. 행단위로

 

 

 

21.선형 대수 함수

1)numpy.diag: 2차원 배열 (행렬)을 넘겨주면 대각원소를 가지고 1차원 배열을 만들어주 1차원 배열을 넘겨주면 1차원을 배열을 대각선 요소로 하고 나머지는 0으로 채운 배열을 리턴해주는 함수

1차원 배열을 넘겨줄 때는 k라는 옵션에 대각선으로 채우는 위치를 설정

 

2)diagonal: .2차원 배열을 받아서 대각원소만 꺼내서 1차원 배열을 만드는 함수이고 offset을 이용해서 꺼내는 위치를 수정

 

3)trace: 대각선 원소의 합이고 offset을 이용해서 꺼내느 위치를 수정

 

4)dot: 행렬의 곱셈

 

5)linalg.inv: 역 행렬

 

6)linalg.det: 행렬식

 

7)linalg.eig: 고유값과 고유 백터 계산

=>컬럼의 개수를 줄일 때 이용

 

 

등급

class 1 2 3

1    1 0 0

2    0 1 0

3    0 0 1

원 핫 인코딩

 

역행렬 : 행렬의 곱이 단위 행렬인 정방행렬

수학은 0이 나올수 있지만 프로그램은 없다.

실수가 나오면 문제가 발생할 수 있다.

 

 

 

X =: 100 Y : 200

width : 70 height: 60

고유 백터 : 어떤 값을 연산해도 그 값은 변하지 않는다.

 

차원 축소

 

육상 7종 경기 데이터 분석

 

100m 달리기            멀리 뛰기  

 

 

 

회귀 분석은 방정식을 만드는데 각각 성적에 어떤 영향을 받는지

분류는

 

 

머신로닝을 돌리면 과적합 될 가능성이 높다.

다중공선성

 

합쳐서 하나 만들기 =>줄여서 차원 축소

두개를 줄여서 하나를 만드는 것 : 성질은 변하면 안된다.

 

행렬 데이터가 있다. 이미지가 있다.

 

행렬 * 고유값 =>동일한 성질을 갇는 고유값들이 있다.

값이 변함에 따라서 고유백터 결정이 되더라

2차원은 2차 방적식이니깐

 

1차방적식은 고유값은 하나밖에 안나온다.

 

행렬에서 고유값(eigenvalue)과 고유백터 (eigenvetor)

:차원 축소 ->변수를 줄인다. 컬럼의 개수를 줄인다.

1)    영향이 적은 컬럼을 제거

2)    상관관계가 있는 컬럼 합치기

 

차원 축소를 하는지 알아야 한다.

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-6  (0) 2020.11.10
데이터분석-5  (0) 2020.11.09
데이터분석-4  (0) 2020.11.08
데이터분석-2  (0) 2020.11.08
데이터 분석-1  (0) 2020.11.08
반응형

** 웹 요청 시 필요한 데이터

=>url: 주소

=>parameter: 서버에게 넘겨주는 데이터 - dict로 만들어서 부착

=>header: 서버에게 넘겨주는 데이터(보이지 않습니다.) - dict로 만들어서 부착

=>method: 전송방식(GET, POST, DELETE, PUT)

 

**requests 패키지

=>웹에서 데이터를 가져올 때 많이 사용하는 패키지 - 정적인 데이터만 가져올 수 있습니다.

ajax를 이용하지 않는 데이터나 프레임을 사용하지 않는 데이터만 가져올 수 있습니다.

=>이 패키지는 python의 기본 패키지가 아닙니다.

=>pip install requests 로 설치

 

1.데이터를 가져오기 위한 구문

requests.전송방식(url)을 호출하면 Response 객체가 리턴됩니다.

 

2.Response 클래스

status_code 속성: 상태 정보

text: 가져온 데이터를 문자열로 저장

content: 가져온 데이터를 바이트 배열로 저장 - 이미지나 음성 데이터

 

3.parameter heade가 존재하는 경우

requests.전송방식(url, data={파라미터}, headers={헤더})

 

4.실습

http://httpbin.org/get 사이트에 get 방식 요청

get put delete 방식으로 요청

post는 파라미터를 설정해서 요청

Kakao Open API 데이터를 가져오기

 

1)requests 설치 - anaconda를 설치했으면 할 필요가 없습니다.

pip install requests

 

2)get 요청을 위한 코드를 작성

import requests

#requests가 가지고 있는 것들을 현재 커널에 requests 라는 이름으로 가져옴

 

#get 요청을 해서 텍스트를 확인

resp = requests.get('http://httpbin.org/get')

 

#help(requests.get) #함수의 도움말 확인

 

#print(type(resp)) #리턴된 결과의 자료형을 확인

#print(dir(requests.models.Response)) #Response 자료형은 어떤 속성들을 가졌는지 확인

 

print(resp.text) #가져온 문자열을 확인

 

3)put delete 요청을 수행

=>서버에서 지원을 해야 가능

#put delete 요청

 

4)post 방식으로 요청하는 파라미터와 함께 전송

#help(requests.post)

#requests 모듈을 사용하면 파라미터 인코딩을 할 필요가 없습니다.

 

 

5)Open API를 사용하다 보면 header cookie를 이용해야 하는 경우가 있습니다.

headers 옵션이나 cookies 옵션에 dict 형태로 만들어서 추가해주면 됩니다.

 

 

#Kakao Open API 도서 검색 사용

addr = 'https://dapi.kakao.com/v3/search/book'

params = {'query':'삼국지', 'target':'title'}

headers = {'Authorization': ''}

resp = requests.get(addr, params=params, headers=headers)

print(resp.text)

 

6)읽어온 텍스트가 현재 기본 인코딩과 맞지 않아서 텍스트가 깨지는 경우

=>받아온 Response 객체의 encoding 속성에 None을 대입해서 인코딩을 유추하게 만들거나 직접 문자열로 인코딩을 설정하면 됩니다.

utf-8: 전 세계 모든 글자를 인코딩하는 방식 - 3byte 1글자

euc-kr: 예전에 웹에서 한글만을 표현하기 위한 인코딩 방식

cp949(ms949): windows에서 한글만을 표현하기 위한 인코딩 방식

 

cp949 euc-kr은 거의 비슷합니다.

 

iso-8859-1: iso-latin-1 이라고도 하는데 서유럽 문자 표시를 위한 인코딩 방식 - 한글 안됨

 

5.이미지 파일 다운로드

=>Response text 속성 대신에 content 속성을 사용

=>파일 객체를 생성해서 write content 속성의 값을 기록하면 파일로 생성

 

#이미지를 다운로드 받아서 파일로 만들기

 

#이미지를 가져올 URL을 생성

imgurl = 'http://www.onlifezone.com/files/attach/images/962811/376/321/005/2.jpg'

 

resp = requests.get(imgurl)

 

#파일 객체를 만들고 이름은 f로 사용 - close를 할 필요가 없습니다.

with open('2.jpg', 'wb') as f:

    f.write(resp.content)

   

#현재 작업디렉토리 확인

import os

print(os.getcwd())

   

**JSON Parsing

1.JSON

=>속성과 값의 쌍으로 이루어진 데이터 오브젝트를 전달하기 위해 텍스트를 사용하는 개방형 표준 포맷

=>javascript python에서 객체(dictionary) 와 배열(list)의 표현 방법을 가져와서 사용

=>최근의 프로그래밍 언어들은 내장 또는 별도의 라이브러리를 이용해서 이 데이터를 객체로 변환해서 사용합니다.

javascript python은 내장

=>최근의 Open API 그리고 스마트 기기 들의 통신은 대부분 JSON 포맷을 사용

=>[ ]: list, { }: dict

 

2.Python에서의 JSON 파싱

json.loads(json 문자열)

=>문자열을 python 객체로 변환해 줍니다.

 

3.실습

=>카카오 카테고리 검색을 이용해서 음식점 이름과 주소를 list로 만들어서 출력

 

headers = {'Authorization': ''}

 

#웹에서 정적인 데이터를 가져오기 위한 라이브러리를 import

import requests

 

#다운로드 받을 URL 만들기

 

 

#header 만들기

headers = {'Authorization': ''}

 

#데이터 가져와서 출력

resp = requests.get(addr, headers=headers)

text = resp.text

#print(text)

 

#json 파싱 모듈을 가져오기 - 내장 모듈

import json

jsondata = json.loads(text)

#print(type(jsondata)) #맨 처음 시작이 {} 이므로 dict

 

#print(jsondata['documents']) #documents 키의 데이터 가져오기 - list

li = []

#가져온 배열을 행 단위로 읽어서

for imsi in jsondata['documents']:

    #print(imsi['address_name'], ':', imsi['place_name'])

    #place_name address_name을 가지고 dict를 생성

    d = {'장소':imsi['place_name'], '주소':imsi['address_name']}

    #dict list에 추가

    li.append(d)

 

#확인

for temp in li:

    print(temp)

 

 

**HTML Parsing

=>open api가 제공되면 json 이나 xml 형태의 데이터를 받아서 파싱해서 사용하면 됩니다.

=>web site에 보여는 주지만 open api 형태로 제공되지 않는 데이터의 경우 html을 수집해서 파싱을 해서 원하는 데이터를 가져오게 됩니다.

html을 무단 수집하는 것은 법적으로 문제가 되는 경우가 있습니다.

 

1.사용되는 패키지: beatifulsoup4

=>이 패키지는 python에는 없고 anaconda에는 존재

=>이 패키지의 bs4 라는 모듈을 이용

=>bs4.BeautifulSoup(html 텍스트, 'html.parser') 를 호출하면 BeautifulSoap 객체를 리턴

이 객체는 html의 내용을 편리하게 찾을 수 있도록 메모리 트리 형태로 펼쳐놓은 객체 입니다.

 

2.태그로 찾는 경우는 find  findall 이용

find(tag, attributes, recursive, text, limit, keyword)

=>tag가 찾고자 하는 태그

=>attributes 는 태그 안에 속성이 있는 경우 속성명=값 의 형태로 대입해서 속성의 값까지 일치하는 것을 찾습니다.

 

<div id='1'></div>

<div id='2' align='center'></div>

<span id='3'></span>

 

div 다 찾기: find('div')

id 2번인 div 찾기: find('div', align='center')

=>find_all은 사용법은 같은데 find 1개만 찾고 find_all 은 전부 찾아옵니다.

 

3.선택자로 찾는 경우는 select()

=>Tag list로 리턴

 

4.찾은 데이터에서 정보를 추출

1)태그 안의 내용을 가져오기: getText()

2)속성의 값을 가져오기:get('속성명')

 

5.실습1 : https://ko.wikipedia.org/wiki/%EA%B8%B0%EA%B3%84_%ED%95%99%EC%8A%B5

에서 하이퍼링크 태그의 url과 텍스트를 수집

하이퍼링크가 /wiki/로 시작하는 것만 출력

 

 

#위키피디아에서 하이퍼링크(a) 태그의 내용 가져오기

import requests

 

addr = 'https://ko.wikipedia.org/wiki/%EA%B8%B0%EA%B3%84_%ED%95%99%EC%8A%B5'

resp = requests.get(addr)

#print(resp.text)

 

#html 파싱을 위한 라이브러리 가져오기

import bs4

 

#DOM 객체로 만들기

bs = bs4.BeautifulSoup(resp.text, 'html.parser')

#print(type(bs))

 

#a 태그의 내용 가져오기

li = bs.find_all('a')

#print(li)

 

#정규식(문자열 패턴을 조회하기 위한 식) 모듈 import

import re

for temp in li:

    #print(temp.getText()) #태그 안의 내용 가져오기

    #print(temp.attrs['href']) #key 에러 - href가 없는 경우도 있음

    if 'href' in temp.attrs: #href 속성이 temp.attrs에 있는 경우에만

        #href 속성에 /wiki/로 시작하는 링크의 텍스트와 링크만 출력

        href = temp.attrs['href']

        #정규식 생성 - /wiki/ 로 시작하는

        p = re.compile('^(/wiki/)')

        if p.search(href) != None:

            print(temp.getText(), ':', href)

   

6.실습2: https://tv.naver.com/에서 상위 항목의 제목과 링크 가져오기

=>선택자 이용

=>선택자를 찾는 방법은 소스 보기를 해서 직접 찾아도 되고 chrome의 검사 기능에서 필요한 부분을 선택하고 copy selector를 이용해서 찾아도 됩니다.

 

#네이버 tv 팟에서 하이퍼링크(a) 태그의 내용 가져오기

import requests

 

addr = 'https://tv.naver.com/'

resp = requests.get(addr)

#print(resp.text)

 

#html 파싱을 위한 라이브러리 가져오기

import bs4

 

#DOM 객체로 만들기

bs = bs4.BeautifulSoup(resp.text, 'html.parser')

#선택자를 이용해서 선택

tvlist = bs.select('dl > dt > a > tooltip')

for temp in tvlist:

    print(temp.getText())

 

7.태그 속성

태그(중복 가능 - 웹 브라우저에서의 모양) : 선택자로 사용할 때는 tag이름

클래스(중복 가능 - 태그들을 그룹화하기 위한 속성) : 선택자로 사용할 때는 .class이름

아이디(중복 불가능 - 태그를 다른 것과 구별하기 위한 속성) : 선택자로 사용할 때는 #id

 

name(중복 가능 - 서버에게 전송할 때 사용할 파라미터 이름)

xpath(중복 불가능 - 브라우저가 태그를 구분하기 위해서 사용하는 경로)

 

8.실습3

http://www.weather.go.kr/weather/observation/currentweather.jsp 에서 도시이름과 온도, 습도를 가져와서 꺽은선 그래프로 출력

=>찾고자 하는 데이터는 class 이름이 table_develop3

 

#오늘 날씨를 가져와서 그래프 그리기

import requests

 

#필요한 html 가져오기

resp = requests.get('http://www.weather.go.kr/weather/observation/currentweather.jsp')

text = resp.text

#print(text)

 

import bs4

bs = bs4.BeautifulSoup(text, 'html.parser')

#class 속성의 값이 table_develop3 인 데이터 찾아오기

table = bs.select('.table_develop3')

#print(table)

 

#도시이름, 온도, 습도를 저장할 list를 생성

loc = []

temp = []

hum = []

 

#가져온 테이블 중에서 첫번째 테이블로부터 줄(tr) 단위로 읽기

for tr in table[0].find_all('tr'):

    tds = tr.find_all('td') #tr 태그에서 td를 전부 찾아서 tds에 대입

    for td in tds:

        if td.find('a'): #a 태그가 있으면 도시이름이 있는 행입니다.

            #도시이름을 loc 추가

            loc.append(td.find('a').text)

            #온도를 temp에 추가

            temp.append(tds[5].text)

            #습도를 temp에 추가

            hum.append(tds[10].text)

 

#데이터 확인

#인덱싱은 번호1개만 작성해서 하나의 데이터만 추출

print(loc[0:5]) #0-4 번행 까지 확인 - 슬라이싱(범위를 가지고 추출)

print(temp[0:5])

print(hum[0:5])

 

#필요한 도시의 데이터만 추출

cities = ['서울', '부산', '인천', '대구', '대전', '광주', '울산', '창원', '흑산도']

#위 도시들의 온도와 습도를 저장할 list

temperatures = []

humidities = []

 

#cities에 있는 데이터만 추출해서 저장

for city in cities:

    j = 0

    for c in loc:

        if c == city:

            temperatures.append(temp[j])

            humidities.append(hum[j])

            break

        j = j + 1

 

print(cities)

print(temperatures)

print(humidities)

 

#파이썬에서 시각화를 하는 기본 패키지

import matplotlib.pyplot as plt

#한글 폰트 사용을 위한 패키지

from matplotlib import font_manager, rc, rcParams

import platform #운영체제 확인을 위한 패키지

 

#주피터 노트북에서 그래프를 셀 안에 출력해주는 설정

%matplotlib inline

 

#음수를 제대로 표현하기 위한 설정

rcParams['axes.unicode_minus'] = False #이 설정을 하지 않으면 음수가 네모로 출력

 

#한글 폰트 설정

if platform.system() == 'Windows': #윈도우즈라면

    font_name = font_manager.FontProperties(fname='c:/windows/Fonts/ahn_b.ttf').get_name()

    rc('font', family=font_name)

elif platform.system() == 'Darwin': #매킨토시라면

    rc('font', family='AppleGothic')

else:

    print('알 수 없는 운영체제')

   

   

#그래프 그리기

plt.figure(figsize=(12,4), dpi=300) #그래프 크기 설정 - 가로 12inch 세로 4인치

#꺽은선 그래프 - plot

plt.plot(temperatures, label='온도', lw=3, color='r', linestyle='-', marker='s')

#plt.plot(humidities, label='습도', lw=3, color='g', linestyle='-', marker='s')

 

#x

plt.xticks(range(0,len(cities),1), cities, rotation='vertical')

#범례

plt.legend()

plt.savefig('graph.png', dpi=300)

#출력

plt.show()

 

**XML 파싱

=>XML: 데이터를 태그 형식으로 표현하는 표준 데이터 포맷

=>예전에 거의 모든 데이터 포맷이 XML

지금은 우리나라 공공기관 Open API 와 실시간 뉴스를 전송해주는 RSS 그리고 프로젝트 설정 파일에 주로 이용

=>BeautifulSoup xml 패키지를 이용해서 파싱 가능

=>BeautifulSoup를 사용하는 경우 html.parser 대신에 lxml-xml 을 사용하면 됩니다.

 

http://www.hani.co.kr/rss/ 에서 item 태그 안의 title 만 전부 조회

 

#XML 파싱

#http://www.hani.co.kr/rss/ 에서 item 태그의 title만 추출

 

#데이터 가져오기

import requests

resp = requests.get('http://www.hani.co.kr/rss/')

text = resp.text

#print(text)

 

import bs4

#트리로 펼쳐내기

bs = bs4.BeautifulSoup(text, 'lxml-xml')

 

items = bs.find_all('item')

 

for item in items:

    title = item.find('title')

    print(title.getText())

 

 

**Selenium

=>web에서 동적으로 생성되는 데이터는 requests 모듈을 가지고 가져올 수 없습니다.

requests 모듈은 처음 접속했을 때 출력되는 데이터만 가져옵니다.

ajax 처럼 비동기적으로 데이터를 가져오거나 로그인을 한 후 보여지는 데이터들은 requests 모듈로는 가져올 수 없습니다.

이처럼 동적으로 만들어지는 데이터는 브라우저를 직접 실행시켜서 동작시키는 Selenium 이라는 웹 앱 테스트 프레임워크를 이용해야 합니다.

=>웹 애플리케이션을 테스트하기 위한 프레임워크

=>기본 패키지가 아니므로 설치를 해야 합니다.

pip install selenium

 

1.브라우저 동작

=>동작시킬 브라우저의 드라이버를 다운로드

=>브라우저를 동작시키지 않고 가져오고자 하는 경우에는 pantom.js를 이용 - Deprecated

=>크롬을 이용할 것이라서 크롬 드라이버를 다운로드

1)chrome 에서 크롬 정보 확인 - chrome 79 버전

 

2)https://chromedriver.chromium.org/downloads 에서 자신의 버전에 맞는 드라이버를 다운로드

=>압축을 해제하고 exe 파일을 찾기 쉬운곳에 배치 : c:/chromedriver.exe

 

3)브라우저 실행

selenium.webdriver.Chrome("크롬 드라이버 경로")

 

4)실습

#크롬 실행하기

from selenium import webdriver

driver = webdriver.Chrome('c:/chromedriver')

 

2.webdriver 의 메소드

=>implicitly_wait(시간): 초 단위 대기 - 여러 사이트에 데이터를 크롤링 하는 경우 또는 첫 화면에 ajax로 데이터를 호출하는 경우 일정시간 대기시켜서 데이터를 읽어옵니다.

 

=>get(url): 브라우저가 url에 접속

 

=>페이지 내의 element에 접근하는 메소드

find_element_by_name(name을 가지고 접근)

find_element_by_id(id를 가지고 접근)

find_element_by_xpath(xpath를 가지고 접근)

 

find_element_by_css_selector(선택자를 가지고 접근)

find_element_by_class_name(class name을 가지고 접근)

find_element_by_tag_name(tag를 가지고 접근)

 

=>element를 찾으면 입력도구 인 경우는 send_keys() 을 호출하면 값을 입력

=>click()을 호출하면 클릭한 효과

 

앞의 3개는 1개의 데이터를 리턴하고 뒤의 3개는 list 형태로 리턴

 

=>quit(): 브라우저 종료

 

=>execute_script(자바스크립트 코드): 자바스크립트 코드 수행

 

=>page_source 속성: html 가져오기

3.실습

1)실습1. daum 카페 페이지에 접근

 

#다음 카페 목록에 접근하기

#크롬 실행하기

from selenium import webdriver

driver = webdriver.Chrome('c:/chromedriver')

#3초대기

driver.implicitly_wait(3)

 

#다음 카페 목록에 접근 - 로그인 되어 있지 않으면 로그인 페이지로 이동

driver.get('url 주소')

 

2)다음 웹 사이트에 로그인을 한 후에 카페 목록 페이지로 이동

다음 로그인 페이지: url주소

 

#다음에 로그인을 하고 카페 목록으로 이동

from selenium import webdriver

driver = webdriver.Chrome('c:/chromedriver')

#3초대기

driver.implicitly_wait(3)

 

#다음 로그인 페이지로 이동

driver.get('url 주소')

 

#아이디와 비밀번호 입력받기

username = input('아이디를 입력하세요')

userpw = input('비밀번호를 입력하세요')

 

#다음 로그인 페이지에 아이디와 비밀번호 입력

#driver.find_element_by_id('id').send_keys(username)

driver.find_element_by_xpath('//*[@id="id"]').send_keys(username)

driver.find_element_by_xpath('//*[@id="inputPwd"]').send_keys(userpw)

 

#로그인 버튼을 클릭한 후 카페 목록 페이지로 이동

driver.find_element_by_xpath('//*[@id="loginBtn"]').click()

driver.find_element_by_xpath('//*[@id="loginBtn"]').click()

 

#여러 페이지를 이동할 때는 중간에 잠시 대기 시간을 주어야 할 필요가 있습니다.

import time

time.sleep(3) #3초 대기

 

#카페 목록으로 이동

driver.get('http://top.cafe.daum.net/_c21_/my_cafe')

 

#접속한 사이트의 html 가져오기

html = driver.page_source

 

4.frame

=>frame html 페이지 내에서 다른 html 페이지의 내용을 출력하기 위해 사용하는 객체

=>스크래핑을 하다보면 화면에 출력이 되고 페이스 소스에서도 확인이 되는데 접근이 안되는 경우가 있습니다.

이런 경우는 ajax로 나중에 불려졌거나 아니면 프레임을 이용해서 다른 파일에서 출력한 경우입니다.

ajax 의 경우는 딜레이를 주고 데이터를 읽으면 가능합니다.

프레임의 경우는 프레임에 직접 접근해서 데이터를 읽어야 합니다.

 

1)현재 페이지에서 frame 조회

변수 = driver.find_element_by_css_selector('iframe')

for 임시변수 in 변수:

           print(임시변수.get_attribute('name')

 

=>현재 페이지의 모든 iframe의 이름을 조회

 

2)프레임 이동

=>driver.switch_to_frame('프레임이름') : 프레임이름에 해당하는 곳으로 이동

=>driver.switch_to_default_content() :  상위 프레임으로 전환

 

5. 프레임 사용 실습

=>이전 것에 이어서 작성

 

#카페 목록 중에서 첫번째 페이지로 이동

#driver.find_element_by_xpath('//*[@id="mArticle"]/div/div[1]/div/div[2]/ul/li/a/div[1]/div[2]/div/div/strong').click()

 

#직접 카페로 이동 - 카페 글쓰기 페이지로 이동

driver.get('http://cafe.11111daum.net/samhak7/_memo')

 

#특정 프레임으로 이동

driver.switch_to_frame('down')

 

#글작성 란에 텍스트를 입력

driver.find_element_by_xpath('//*[@id="memoForm"]/div/table/tbody/tr[1]/td[1]/div/textarea').send_keys('파이썬에서의 매크로')

driver.find_element_by_xpath('//*[@id="memoForm"]/div/table/tbody/tr[1]/td[2]/a[1]/span[2]').click()

 

6.크롬을 화면에서 출력시키지 않고 데이터 가져오기

=>웹 드라이버를 옵션을 추가해서 생성

#크롬을 화면에 출력하지 않고 실행하기

options = webdriver.ChromeOptions()

options.add_argument('headless')

options.add_argument('window-size=1920x1080')

options.add_argument("disable-gpu")

# 혹은 options.add_argument("--disable-gpu")

 

driver = webdriver.Chrome('c:/chromedriver', chrome_options=options)

 

 

7.20번 스크롤 한 데이터 가져오기

#20번 스크롤 하기

from selenium import webdriver

import time

from selenium.webdriver.common.keys import Keys

import bs4

 

driver = webdriver.Chrome('c:/chromedriver')

 

driver.get('')

time.sleep(5)

 

body = driver.find_element_by_tag_name('body')#스크롤하기 위해 소스 추출

num_of_pagedowns = 20

#10번 밑으로 내리는 것

while num_of_pagedowns:

    body.send_keys(Keys.PAGE_DOWN)

    time.sleep(2)

    num_of_pagedowns -= 1

   

html = bs4.BeautifulSoup(driver.page_source,'html.parser')

print(html)

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

반응형

'Study > 데이터 분석' 카테고리의 다른 글

데이터분석-6  (0) 2020.11.10
데이터분석-5  (0) 2020.11.09
데이터분석-4  (0) 2020.11.08
데이터분석-3  (0) 2020.11.08
데이터 분석-1  (0) 2020.11.08

+ Recent posts