반응형

서울 열린 데이터 광장의 공공 데이터(에코 마일리지 에너지 사용량 통계 정보)를 수집하고 분석해 보자.

 

인증키는 쉽게 발급 받을 수 있으니 알아서 하자.

 

 주의 할 점은 Open API 사용 정보에 요청인자 목록이 자세히 적혀 있어 파이썬 requests.get(url, param) 과 같은 명령으로 데이터를 불러 올 수 있을거 같지만 제대로 실행되지 않는다. url에 필요한 모든 요청인자를 넣어서 데이터를 불러와야 한다.

 

1-1. Python을 사용해 2015.01~2024.12 기간의 개인 현년 전기, 가스, 수도, 지역난방 에너지 사용량 데이터를 수집해 보자.

import requests

year_months = []  # 마지막 출력에 사용하기 위해 전역변수로 선언

def get_year_months():
    for year in range(2015, 2024+1):
        for month in range(1, 12+1):
            year_months.append(f"{year}/{month:02d}")
    return year_months

start_index = 1
end_index = 7
url1 = "http://openapi.seoul.go.kr:8088/"
url2 = f"/json/energyUseDataSummaryInfo/{start_index}/{end_index}/"
api_key = "your_api_key"

count = 0
missing = 0
responses = []

for year_month in get_year_months():
    response = requests.get(url1 + api_key + url2 + year_month)
    if response.status_code == 200:
        found = False

        for i in range(end_index):
            if response.json()['energyUseDataSummaryInfo']['row'][i]['MM_TYPE'] == '개인':
                data = []
                data.append(response.json()[
                            'energyUseDataSummaryInfo']['row'][i]['EUS'])
                data.append(response.json()[
                            'energyUseDataSummaryInfo']['row'][i]['GUS'])
                data.append(response.json()[
                            'energyUseDataSummaryInfo']['row'][i]['WUS'])
                data.append(response.json()[
                            'energyUseDataSummaryInfo']['row'][i]['HUS'])

                responses.append(data)
                found = True
                count += 1
                break

        if not found:
            missing += 1
            print(
                f"\n{response.json()['energyUseDataSummaryInfo']['row'][i]['YEAR']}/{response.json()['energyUseDataSummaryInfo']['row'][i]['MON']}: No 개인 data found.")
    else:
        print(
            f"Failed to retrieve data.\nStatus code: {response.status_code}\nReason: {response.reason}")

print(f"■ Total months with 개인 data: {count}")
print(f"■ Total months without 개인 data: {missing}\n")
for ym, row in zip(year_months, responses):
    print(f"{ym}: {row}")

 

2016년 12월 이후의 데이터는 생략

 

 

API로 받고 JSON으로 변환한 데이터 형태는 아래 '더보기'를 클릭하면 확인 할 수 있다.

더보기

{'energyUseDataSummaryInfo': {'list_total_count': 7, 'RESULT': {'CODE': 'INFO-000', 'MESSAGE': '정상 처리되었습니다'}, 'row': [{'YEAR': '2015', 'MON': '01', 'MM_TYPE': '개인', 'CNT': '767791', 'EUS': '193784708', 'EUS1': '194781915', 'EUS2': '204969429', 'ECO2_1': '-6090964', 'ECO2_2': '-2582568.736', 'GUS': '59133720', 'GUS1': '57163993', 'GUS2': '68297619', 'GCO2_1': '-3597086', 'GCO2_2': '-8057472.64', 'WUS': '12819757.886', 'WUS1': '12723680.426', 'WUS2': '12899476.73', 'WCO2_1': '8179.308', 'WCO2_2': '2715.530256', 'HUS': '22740838.937', 'HUS1': '23400055.303', 'HUS2': '27090493.875', 'HCO2_1': '-2504435.652', 'HCO2_2': '-33660084.213069', 'REG_DATE': '2015-06-04 17:03:55.0'}, {'YEAR': '2015', 'MON': '01', 'MM_TYPE': '학교', 'CNT': '1382', 'EUS': '134955565', 'EUS1': '128707423', 'EUS2': '145561511', 'ECO2_1': '-2178902', 'ECO2_2': '-923854.448', 'GUS': '9107197', 'GUS1': '8410968', 'GUS2': '10745416', 'GCO2_1': '-470995', 'GCO2_2': '-1055028.8', 'WUS': '2075819.2', 'WUS1': '2097433.8', 'WUS2': '2133200.8', 'WCO2_1': '-39498.1', 'WCO2_2': '-13113.3692', 'HUS': '0', 'HUS1': '0', 'HUS2': '0', 'HCO2_1': '0', 'HCO2_2': '0', 'REG_DATE': '2015-06-04 17:03:55.0'}, {'YEAR': '2015', 'MON': '01', 'MM_TYPE': '종교단체', 'CNT': '32', 'EUS': '372270', 'EUS1': '363376', 'EUS2': '411363', 'ECO2_1': '-15099.5', 'ECO2_2': '-6402.188', 'GUS': '53331', 'GUS1': '45727', 'GUS2': '63312', 'GCO2_1': '-1188.5', 'GCO2_2': '-2662.24', 'WUS': '5945', 'WUS1': '4548', 'WUS2': '4519', 'WCO2_1': '1411.5', 'WCO2_2': '468.618', 'HUS': '0', 'HUS1': '0', 'HUS2': '0', 'HCO2_1': '0', 'HCO2_2': '0', 'REG_DATE': '2015-06-04 17:03:55.0'}, {'YEAR': '2015', 'MON': '01', 'MM_TYPE': '소상공인', 'CNT': '2058', 'EUS': '10249618', 'EUS1': '9927610', 'EUS2': '11039593', 'ECO2_1': '-233983.5', 'ECO2_2': '-99209.004', 'GUS': '536119', 'GUS1': '523810', 'GUS2': '642921', 'GCO2_1': '-47246.5', 'GCO2_2': '-105832.16', 'WUS': '147273', 'WUS1': '146480.6', 'WUS2': '147325.6', 'WCO2_1': '369.9', 'WCO2_2': '122.8068', 'HUS': '0', 'HUS1': '0', 'HUS2': '0', 'HCO2_1': '0', 'HCO2_2': '0', 'REG_DATE': '2015-06-04 17:03:55.0'}, {'YEAR': '2015', 'MON': '01', 'MM_TYPE': '공동주택관리소', 'CNT': '1747', 'EUS': '327102096', 'EUS1': '329852334', 'EUS2': '351694752', 'ECO2_1': '-13671447', 'ECO2_2': '-5796693.528', 'GUS': '22834274', 'GUS1': '21141017', 'GUS2': '25338506', 'GCO2_1': '-405487.5', 'GCO2_2': '-908292', 'WUS': '12844807.5', 'WUS1': '12763070', 'WUS2': '12979835.8', 'WCO2_1': '-26645.4', 'WCO2_2': '-8846.2728', 'HUS': '0', 'HUS1': '0', 'HUS2': '0', 'HCO2_1': '0', 'HCO2_2': '0', 'REG_DATE': '2015-06-04 17:03:55.0'}, {'YEAR': '2015', 'MON': '01', 'MM_TYPE': '기업', 'CNT': '16751', 'EUS': '583090528', 'EUS1': '586779350', 'EUS2': '632471031', 'ECO2_1': '-26534662.5', 'ECO2_2': '-11250696.9', 'GUS': '37835680', 'GUS1': '35765271', 'GUS2': '47713673', 'GCO2_1': '-3903792', 'GCO2_2': '-8744494.08', 'WUS': '6581017', 'WUS1': '6591203.4', 'WUS2': '6684708.2', 'WCO2_1': '-56938.8', 'WCO2_2': '-18903.6816', 'HUS': '0', 'HUS1': '0', 'HUS2': '0', 'HCO2_1': '0', 'HCO2_2': '0', 'REG_DATE': '2015-06-04 17:03:55.0'}, {'YEAR': '2015', 'MON': '01', 'MM_TYPE': '공공기관', 'CNT': '2981', 'EUS': '247059373', 'EUS1': '242471579', 'EUS2': '261884067', 'ECO2_1': '-5118450', 'ECO2_2': '-2170222.8', 'GUS': '11524542', 'GUS1': '10057837', 'GUS2': '13760048', 'GCO2_1': '-384400.5', 'GCO2_2': '-861057.12', 'WUS': '1522465.2', 'WUS1': '1495786.6', 'WUS2': '1522178.8', 'WCO2_1': '13482.5', 'WCO2_2': '4476.19', 'HUS': '0', 'HUS1': '0', 'HUS2': '0', 'HCO2_1': '0', 'HCO2_2': '0', 'REG_DATE': '2015-06-04 17:03:55.0'}]}}

 

문제와는 다르지만 Pandas를 쓰면 조금 더 간단히 필터링 할 수 있다. 아래 '더보기'를 클릭하면 확인 할 수 있다.

더보기
import requests
import pandas as pd

def get_year_months():
	year_months = []
	for year in range(2015, 2024+1):
		for month in range(1, 12+1):
			year_months.append(f"{year}/{month:02d}")
	return year_months

start_index = 1
end_index = 7
url1 = "http://openapi.seoul.go.kr:8088/"
url2 = f"/json/energyUseDataSummaryInfo/{start_index}/{end_index}/"
api_key = "your_api_key"

df = pd.DataFrame()

for year_month in get_year_months():
	response = requests.get(url1 + api_key + url2 + year_month)
	if response.status_code == 200:
		data = pd.DataFrame(response.json()['energyUseDataSummaryInfo']['row'])
		data = data[data['MM_TYPE'] == '개인']
		df = pd.concat([df, data], ignore_index=True)

	else:
		print(
			f"Failed to retrieve data.\nStatus code: {response.status_code}\nReason: {response.reason}")

df = df[['YEAR', 'MON', 'EUS', 'GUS', 'WUS', 'HUS']]
print(df)

  

 

2-1. 수집한 JSON 형태의 데이터를 Pandas DataFrame으로 변환하자.

 

import requests
import pandas as pd

def get_year_months():	
	year_months = []
	for year in range(2015, 2024+1):
		for month in range(1, 12+1):
			year_months.append(f"{year}/{month:02d}")
	return year_months

start_index = 1
end_index = 7
url1 = "http://openapi.seoul.go.kr:8088/"
url2 = f"/json/energyUseDataSummaryInfo/{start_index}/{end_index}/"
api_key = "your_api_key"

df = pd.DataFrame()

for year_month in get_year_months():
	response = requests.get(url1 + api_key + url2 + year_month)
	if response.status_code == 200:
		for i in range(end_index):
			if response.json()['energyUseDataSummaryInfo']['row'][i]['MM_TYPE'] == '개인':
				data = pd.DataFrame([response.json()['energyUseDataSummaryInfo']['row'][i]])
				df = pd.concat([df, data], ignore_index=True)
				break

	else:
		print(f"Failed to retrieve data.\nStatus code: {response.status_code}\nReason: {response.reason}")

df.info()

 

 

2-2. 연도별, 계절별 분석을 위해 계절(season) 칼럼을 추가하자.

 

import requests
import pandas as pd

def get_year_months():
	year_months = []
	for year in range(2015, 2024+1):
		for month in range(1, 12+1):
			year_months.append(f"{year}/{month:02d}")
	return year_months

start_index = 1
end_index = 7
url1 = "http://openapi.seoul.go.kr:8088/"
url2 = f"/json/energyUseDataSummaryInfo/{start_index}/{end_index}/"
api_key = "your_api_key"

df = pd.DataFrame()

for year_month in get_year_months():
	response = requests.get(url1 + api_key + url2 + year_month)
	if response.status_code == 200:
		for i in range(end_index):
			if response.json()['energyUseDataSummaryInfo']['row'][i]['MM_TYPE'] == '개인':
				data = pd.DataFrame(
					[response.json()['energyUseDataSummaryInfo']['row'][i]])
				df = pd.concat([df, data], ignore_index=True)
				break
	else:
		print(f"Failed to retrieve data.\nStatus code: {response.status_code}\nReason: {response.reason}")

df['SEASON'] = df['MON'].apply(lambda x: '겨울' if x in ['01', '02', '12'] else (
	'봄' if x in ['03', '04', '05'] else ('여름' if x in ['06', '07', '08'] else '가을')))

print(df)

 

 

 

3-1. 연도별 에너지 총사용량(전기+가스+수도+지역난방) 변화량을 선 그래프로 시각화 하자.

 

import requests
import pandas as pd
import matplotlib.pyplot as plt

def get_year_months():
	year_months = []
	for year in range(2015, 2024+1):
		for month in range(1, 12+1):
			year_months.append(f"{year}/{month:02d}")
	return year_months

start_index = 1
end_index = 7
url1 = "http://openapi.seoul.go.kr:8088/"
url2 = f"/json/energyUseDataSummaryInfo/{start_index}/{end_index}/"
api_key = "your_api_key"

df = pd.DataFrame()

for year_month in get_year_months():
	response = requests.get(url1 + api_key + url2 + year_month)
	if response.status_code == 200:
		for i in range(end_index):
			if response.json()['energyUseDataSummaryInfo']['row'][i]['MM_TYPE'] == '개인':
				data = pd.DataFrame(
					[response.json()['energyUseDataSummaryInfo']['row'][i]])
				df = pd.concat([df, data], ignore_index=True)
				break
	else:
		print(f"Failed to retrieve data.\nStatus code: {response.status_code}\nReason: {response.reason}")

df['SEASON'] = df['MON'].apply(lambda x: '겨울' if x in ['01', '02', '12'] else (
	'봄' if x in ['03', '04', '05'] else ('여름' if x in ['06', '07', '08'] else '가을')))

df = df.astype({'EUS': 'float', 'GUS': 'float','WUS': 'float', 'HUS': 'float'})

year_group = df.groupby('YEAR')[['EUS', 'GUS', 'WUS', 'HUS']].sum().reset_index()
year_group['에너지 총사용량'] = year_group[['EUS', 'GUS', 'WUS', 'HUS']].sum(axis=1)

plt.rc('font', family='GULIM')
plt.plot(year_group['YEAR'], year_group['에너지 총사용량'], marker='o', color='red')
plt.xlabel('연도')
plt.ylabel('에너지 사용 총액')
plt.title('연도별 에너지 사용 총액 변화')
plt.show()

 

 

3-2. 계절별 가스 사용량 평균을 막대 그래프로 시각화 하고 각 막대의 수치를 표시하자.

 

import requests
import pandas as pd
import matplotlib.pyplot as plt

def get_year_months():
	year_months = []
	for year in range(2015, 2024+1):
		for month in range(1, 12+1):
			year_months.append(f"{year}/{month:02d}")
	return year_months

start_index = 1
end_index = 7
url1 = "http://openapi.seoul.go.kr:8088/"
url2 = f"/json/energyUseDataSummaryInfo/{start_index}/{end_index}/"
api_key = "your_api_key"

df = pd.DataFrame()

for year_month in get_year_months():
	response = requests.get(url1 + api_key + url2 + year_month)
	if response.status_code == 200:
		for i in range(end_index):
			if response.json()['energyUseDataSummaryInfo']['row'][i]['MM_TYPE'] == '개인':
				data = pd.DataFrame(
					[response.json()['energyUseDataSummaryInfo']['row'][i]])
				df = pd.concat([df, data], ignore_index=True)
				break
	else:
		print(f"Failed to retrieve data.\nStatus code: {response.status_code}\nReason: {response.reason}")

df['SEASON'] = df['MON'].apply(lambda x: '겨울' if x in ['01', '02', '12'] else (
	'봄' if x in ['03', '04', '05'] else ('여름' if x in ['06', '07', '08'] else '가을')))

df = df.astype({'GUS': 'float'})
season_group = df.groupby('SEASON')['GUS'].mean().reset_index()

plt.rc('font', family='GULIM')
plt.bar(season_group['SEASON'], season_group['GUS'])
plt.xlabel('계절')
plt.ylabel('가스 사용량 평균')
plt.title('계절별 가스 사용량 평균')
plt.bar_label(plt.gca().containers[0])
plt.show()

 

 

 

4. 연도별 에너지 사용량 변화에서 나타나는 주요 트랜드를 찾아 분석하고 그 원인을 추론해 보자.

 

import requests
import pandas as pd
import matplotlib.pyplot as plt

def get_year_months():
	year_months = []
	for year in range(2015, 2024+1):
		for month in range(1, 12+1):
			year_months.append(f"{year}/{month:02d}")
	return year_months

start_index = 1
end_index = 7
url1 = "http://openapi.seoul.go.kr:8088/"
url2 = f"/json/energyUseDataSummaryInfo/{start_index}/{end_index}/"
api_key = "your_api_key"

df = pd.DataFrame()

for year_month in get_year_months():
	response = requests.get(url1 + api_key + url2 + year_month)
	if response.status_code == 200:
		for i in range(end_index):
			if response.json()['energyUseDataSummaryInfo']['row'][i]['MM_TYPE'] == '개인':
				data = pd.DataFrame(
					[response.json()['energyUseDataSummaryInfo']['row'][i]])
				df = pd.concat([df, data], ignore_index=True)
				break
	else:
		print(f"Failed to retrieve data.\nStatus code: {response.status_code}\nReason: {response.reason}")

df = df.astype({'EUS': 'float', 'GUS': 'float','WUS': 'float', 'HUS': 'float'})

year_group = df.groupby('YEAR')[['EUS', 'GUS', 'WUS', 'HUS']].sum().reset_index()
year_group['에너지 총사용량'] = year_group[['EUS', 'GUS', 'WUS', 'HUS']].sum(axis=1)

plt.rc('font', family='GULIM')
plt.bar(year_group['YEAR'], year_group['에너지 총사용량'], color='blue', alpha=0.5, label='총사용량')
plt.plot(year_group['YEAR'], year_group['EUS'], color='red', marker='o', label='전기')
plt.plot(year_group['YEAR'], year_group['GUS'], color='green', marker='o', label='가스')
plt.plot(year_group['YEAR'], year_group['WUS'], color='orange', marker='o', label='수도')
plt.plot(year_group['YEAR'], year_group['HUS'], color='purple', marker='o', label='난방')

plt.legend(loc='upper left')
plt.xlabel('연도')
plt.ylabel('에너지 사용량 X 1e9')
plt.ylim(0, 5000000000)

plt.grid(True, axis='y', alpha=0.5)
plt.title('연도별 에너지 사용량 변화')
plt.show()

 

 

 연도별 에너지 사용량 변화 원인을 추론하고 트렌드를 찾기 조금 더 자세한 그래프를 그려 보았다. 기후변화나 에너지 요금 등의 다양한 요인들로 인해...

이하 생략.

 

반응형
Posted by J-sean
:
반응형

비주얼 스튜디오에서 코드를 자동 완성 시켜주는 기능을 사용해 보자.

 

 

 

 

 

 

 

※ 참고

Visual Studio IntelliCode

 

반응형
Posted by J-sean
:
반응형

Visual Studio Debugging Breakpoint

 

Use the right type of breakpoint

 

 

Log to Output window

 

 

반응형
Posted by J-sean
:
반응형

 PDF파일을 인쇄하다 보면 종종 몇 페이지 되지도 않는 작은 문서인데 한 페이지 인쇄에 몇 분씩 걸리는 경우가 있다.

 하루 종일 걸리는 PDF 파일 인쇄를 해결해 보자.

 

1MB도 되지 않는 작은 문서다. 하지만 인쇄하면 한 페이지에 5분씩 걸리는거 같은 느낌이다.

 

프린터 상태를 확인해 보면 파일 크기가 23.5MB로 늘어나 있는걸 볼 수 있다.

 

프린트를 중지하고 '인쇄' - '고급' 을 클릭한다.

 

'이미지로 인쇄'를 선택하고 확인을 클릭한다.

 

 이제 다시 프린트하면 빠르게 진행된다.

 

반응형
Posted by J-sean
:
반응형

GIMP를 이용해 투명 배경을 만들어 보자.

 

Mario.png
0.00MB

투명 배경이 필요한 그림을 준비한다.

 

GIMP로 불러온다.

 

Layer - Transparency - Color to Alpha... 를 선택한다.

 

Color의 컬러 픽커를 이용하면 정확히 한 픽셀을 선택하기가 어렵다. 위 그림과 같이 여러 픽셀이 선택되면 평균값이 계산 되는거 같다.

 

Color를 선택해 원하는 색을 직접 입력하자. [0..100], [0..255] 선택에 주의한다.

 

투명하게 만들 색을 입력하고 확인하면 Alpha Channel이 생성되고 배경이 투명하게 바뀐다.

 

File - Export As... 를 선택하고 PNG 파일로 저장한다.

 

반응형
Posted by J-sean
:
반응형

픽셀 이미지(JPG, PNG)를 벡터(AI) 이미지로 바꿔보자.

 

일러스트레이터를 실행하고 변환할 이미지를 불러온다.

 

snoopy.jpg
0.09MB

 

 

Tracing으로 바꾼다.

 

변환할 이미지를 선택하고 Image Trace 탭에서 Auto-Color를 선택한다. 필요하다면 다른 옵션을 조절하고 Expand 버튼을 클릭한다.

 

픽셀 이미지가 벡터 이미지로 변환된다.

 

반응형
Posted by J-sean
:
반응형

MAME 화면을 칵테일 모드로 바꿔보자.

 

MAME를 실행한다.

 

원하는 게임을 실행하고 TAB 키를 누른다. Video Options를 선택한다.

 

Screen #0을 선택한다.

 

Cocktail을 선택한다. 칵테일 모드가 바로 적용된다.

 

 

게임을 플레이 할 때도 계속 적용된다.

 

다른 게임도 마찬가지 방법으로 칵테일 모드를 적용할 수 있다.

 

반응형
Posted by J-sean
:
반응형

한텍 오실로스코프 2D42의 배터리를 교환해 보자.

 

몇 달 만에 켜보니 반응이 없다. 이럴 줄 알았다.

 

두꺼운 고무 케이스를 분리한다. 힘이 많이 들어간다.

 

뒷면 나사 4개만 풀면 쉽게 열 수 있다.

 

원래 들어 있던 배터리.

 

 

전압을 측정해 본다. 역시 죽기 직전이다. 다시 충전해서 살려도 금방 죽는다.

 

밸런싱한 새 배터리를 준비한다.

 

새 배터리를 넣어준다.

 

충전단자 옆 USB 포트는 아무것도 연결되어 있지 않다. 다른 모델을 위한 포트인 듯.

 

 

다시 조립하고 켜본다. 잘 된다.

 

사실 뒷면 거치대를 열고 나사 2개만 풀면 배터리 커버를 제거할 수 있다. 하지만 저 배터리 커버가 잘 안빠진다.

 

반응형
Posted by J-sean
: