# 2012년에서 2016년에 걸쳐 계절별로 강수량의 평균(mean)과 표준 편차(std)를 구함.
df3.mean()
'''
봄 254.54
여름 554.24
가을 303.42
겨울 98.66
dtype: float64
'''
df3.std() # 계절별 강수량 표준편차
'''
봄 38.628267
여름 148.888895
가을 67.358496
겨울 30.925523
dtype: float64
'''
📌 연도별로 평균 강수량과 표준 편차를 구할 경우엔 연산의 방향 설정을 위해 axis인자를 추가 📌 인자 axis가 0이면 DataFrame의 values에서 열별로 연산을 수행하고, 1이면 행별로 연산
🍯 표 Table와 2차원 데이터 처리를 위해 DataFrame을 제공 ▶️ 데이터 Data를 담는 틀 Frame이라는 뜻
1) 데이터 생성
df = pd.DataFrame(data [, index = index_data, columns = columns_data])
🐰 data 인자에는 리스트와 형태가 유사한 데이터 타입은 모두 사용 가능 🥕 리스트, 딕셔너리, numpy의 배열 데이터, Series나 DataFrame 타입의 데이터 입력 가능 🐰 세로축 라벨을 index라 하고, 가로축 라벨을 columns 라고 함 🐰 index와 columns를 제외한 부분을 values라고 함
import pandas as pd
d1 = pd.DataFrame([[1,2,3], [4,5,6], [7,8,9]])
d1
🥕 values 부분에는 입력한 data가 순서대로 입력 돼 있고 가장 좌측의 열과 가장 윗줄의 행에는 각각 숫자가 자동으로 생성되어 index, columns를 구성 ▶️ 명시적으로 입력하지 않더라도 자동으로 index, columns가 생성
🍯 pandas 라이브러리 : 파이썬에서 데이터 분석과 처리를 쉽게 처리할 수 있게 도와준다 🍯 pandas는 numpy를 기반으로 만들어졌지만 좀 더 복잡한 데이터 분석에 특화 🍯 numpy가 같은 데이터 타입의 배열만 처리할 수 있는데 반해 pandas는 데이터 타입이 다양하게 섞여 있을 때도 처리 가능
# 어느 가게의 날짜별 판매량을 pandas의 Series 형식으로 입력. 하루는 데이터가 없어서 np.nan을 입력
index_data = ['2018-10-07', '2018-10-08', '2018-10-09', '2018-10-10']
s4 = pd.Series([200, 195, np.nan, 205], index=index_data)
s4
👾 start는 시작날짜, end는 끝날짜 👾 periods는 날짜 데이터 생성 기간 = 생성 갯수 👾 freq는 날짜 데이터 생성 주기 👾 start는 필수이고, end나 periods는 둘 중 하나만 있어도 됨 👾 freq는 입력하지 않으면 'D' 옵션이 설정돼 달력날짜 기준으로 하루씩 증가
# 시작 날짜와 끝 날짜를 지정해 날짜 데이터를 생성. 하루씩 증가한 날짜 데이터가 생성.
pd.date_range(start='2019-01-01', end='2019-01-07')
'''
DatetimeIndex(['2019-01-01', '2019-01-02', '2019-01-03', '2019-01-04',
'2019-01-05', '2019-01-06', '2019-01-07'],
dtype='datetime64[ns]', freq='D')
'''
1) 날짜 데이터 형식
🚀 날짜 데이터를 입력할 때 yyyy-mm-dd yyyy/mm/dd, yyyy.mm.dd, mm-dd-yyyy, mm/dd/yyyy, mm.dd.yyyy
# 2일씩 증가하는 날짜를 생성
pd.date_range(start='2019-01-01', periods=4, freq='2D')
# DatetimeIndex(['2019-01-01', '2019-01-03', '2019-01-05', '2019-01-07'],
# dtype='datetime64[ns]', freq='2D')
# 달력의 요일을 기준으로 일주일씩 증가하는 날짜를 생성.
pd.date_range(start='2019-01-06', periods=4, freq='W')
# DatetimeIndex(['2019-01-06', '2019-01-13', '2019-01-20', '2019-01-27'],
# dtype='datetime64[ns]', freq='W-SUN')
# 업무일 기준 2개월 월말 주기로 12개 날짜를 생성.
pd.date_range(start='2019-01-01', periods=12, freq='2BM')
'''
DatetimeIndex(['2019-01-31', '2019-03-29', '2019-05-31', '2019-07-31',
'2019-09-30', '2019-11-29', '2020-01-31', '2020-03-31',
'2020-05-29', '2020-07-31', '2020-09-30', '2020-11-30'],
dtype='datetime64[ns]', freq='2BM'
'''
# 분기 시작일을 기준으로 4개의 날짜를 생성
pd.date_range(start='2019-01-01', periods=4, freq='QS')
# DatetimeIndex(['2019-01-01', '2019-04-01', '2019-07-01', '2019-10-01'],
# dtype='datetime64[ns]', freq='QS-JAN')
[ 시간 생성 ]
# 1시간 주기로 10개의 시간을 생성한 예
pd.date_range(start='2019-01-01 08:00', periods=10, freq='H')
'''
DatetimeIndex(['2019-01-01 08:00:00', '2019-01-01 09:00:00',
'2019-01-01 10:00:00', '2019-01-01 11:00:00',
'2019-01-01 12:00:00', '2019-01-01 13:00:00',
'2019-01-01 14:00:00', '2019-01-01 15:00:00',
'2019-01-01 16:00:00', '2019-01-01 17:00:00'],
dtype='datetime64[ns]', freq='H')
'''
# 업무 시간을 기준으로 1시간 주기로 10개의 시간을 생성하는 예
# 업무 시간은 9시 부터 17시까지이므로 start시간을 9시 이전으로 설정해도 9시 부터 표시.
pd.date_range(start='2019-01-01 08:00', periods=10, freq='BH')
'''
DatetimeIndex(['2019-01-01 09:00:00', '2019-01-01 10:00:00',
'2019-01-01 11:00:00', '2019-01-01 12:00:00',
'2019-01-01 13:00:00', '2019-01-01 14:00:00',
'2019-01-01 15:00:00', '2019-01-01 16:00:00',
'2019-01-02 09:00:00', '2019-01-02 10:00:00'],
dtype='datetime64[ns]', freq='BH')
'''
# date_range()를 이용해 Series의 index를 지정한 예.
index_date = pd.date_range(start='2019-03-01', periods=5, freq='D')
s = pd.Series([51, 62, 55, 49, 58], index=index_date)
s
'''
2019-03-01,51
2019-03-02,62
2019-03-03,55
2019-03-04,49
2019-03-05,58
'''
👾 1차원 배열에서 여러 개의 원소를 선택 ▶️ 배열명[위치1, 위치2, ..., 위치n]
👾 2차원 배열에서 특정 위치의 원소를 선택하려면 행과 열의 위치를 지정 ▶️ 배열명[행_위치, 열_위치]
👾 2차원 배열의 여러 원소를 선택하기 위해서 아래와 같이 지정 ▶️배열명[[행_위치1, 행_위치2, ..., 행_위치n], [열_위치1, 열_위치2, ..., 열_위치n]]
# 1차원 배열
print(a1[[1, 3, 4]]) # [10 30 40]
# 2차원 배열
# 10부터 99까지 10씩 증가하는 1차원 배열을 생성한 후에 3행 3열의 2차원 배열로 모양을 바꿈.
a2 = np.arange(10, 100, 10).reshape(3, 3)
print(a2)
# [[10 20 30]
# [40 50 60]
# [70 80 90]]
# 2차원 배열 원소 선택
# 행 위치가 0이고, 열 위치가 2인 원소를 반환.
print(a2[0, 2]) # 30
print(a2[0][2]) # 30
# 2차원 배열의 행과 열의 위치를 지정해서 원소를 선택한 후 값을 변경할 수 있음
a2[2, 2] = 95
print(a2)
# [[10 20 30]
# [40 50 60]
# [70 80 95]]
# 2차원 배열 여러 원소 선택
print(a2[[0, 2], [0, 1]]) # [10 80]
# 문자열이 원소인 배열 생성 예
a1 = np.array(['1.5', '0.62', '2', '3.14', '3.141592'])
print(a1) # ['1.5' '0.62' '2' '3.14' '3.141592']
print(a1.dtype) # <U8. 데이터 형식이 유니코드이며 문자의 수는 최대 8개라는 의미
4) NumPy 데이터의 형식
b
불. bool
i
기호가 있는 정수. (signed) integer
u
기호가 없는 정수. unsigned integer
f
실수. floating-point
c
복소수. complex-floating point
M
날짜. datetime
O
파이썬 객체. (Python) objects
S or a
바이트 문자열. (byte) string
U
유니코드. Unicode
👾 배열이 문자열(숫자 표시)로 돼 있다면 연산을 위해서는 문자열을 숫자(정수나 실수)로 변환해야 함 👾 형 변환은 astype()로 가능
num_arr = str_arr.astype(dtype)
# 실수가 입력된 문자열을 원소로 갖는 배열을 실수 타입으로 변환하는 예.
str_a1 = np.array(['1.567', '0.123', '5.123', '9', '8'])
num_a1 = str_a1.astype(float)
print(num_a1) # [1.567 0.123 5.123 9. 8. ]
print(str_a1.dtype) # <U5
print(num_a1.dtype) # float64
# 정수를 문자열 원소로 갖는 배열을 정수로 변환하는 예.
str_a2 = np.array(['1', '3', '5', '7', '9'])
num_a2 = str_a2.astype(int)
print(str_a2.dtype) # <U1
print(num_a2) # [1 3 5 7 9]
print(num_a2.dtype) # int64
5) 난수 배열의 생성
👾 rand() 함수를 이용하면 실수 난수를 요소로 갖는 배열을 생성 👾 randint() 함수를 이용하면 정수 난수를 요소로 갖는 배열을 생성
📌 rand() 함수는 [0, 1) 사이의 실수 난수를 갖는 배열을 생성 ▶️ [a, b)의 표현은 배열 크기 📌 randint() 함수는 [low, high) 사이의 정수 난수를 갖는 배열을 생성 ▶️ size는 배열의 형태 지정 ▶️ low를 입력하지 않으면 0으로 간주 ▶️ size를 입력하지 않으면 1로 간주
import requests
from bs4 import BeautifulSoup as bs
import pprint
# 1. 이미지 태그 가져오기
url = 'https://images.search.yahoo.com/search/images;_ylt=Awrg1fJPpOplRwQAMU5XNyoA;_ylu=Y29sbwNncTEEcG9zAzEEdnRpZAMEc2VjA3BpdnM-?p=bts&fr2=piv-web&fr=yfp-t'
resp = requests.get(url)
soup = bs(resp.text, 'html.parser')
tag_images = soup.select('li.ld a > img')
pprint.pprint(tag_images)
# 2. 이미지 저장
dir_save = './output_image/yahoo/' # 저장 경로
for idx, tag in enumerate(tag_images):
#print(tag.get('data-src'))
resp = requests.get(tag.get('data-src'))
with open(f'{dir_save}{idx + 1}.png', 'wb') as image_file:
image_file.write(resp.content)
#print(f'{idx+1} / {len(tag_images)}') # 진행 상황 확인