- 개요
한국에서 기상 관측 자료라 하면 보통 ASOS/AWS 기상 관측 자료를 말합니다.
기상청뿐만 아니라 다른 기관이 설치한 ASOS/AWS 관측소의 수는 전국에 500개가 넘는데요.
다른 나라와 비교해서 우리나라 정부가 정말 기상 관측소를 정말 촘촘히 설치한 겁니다.
심지어 국가가 관리하기 때문에 관측품질도 좋죠.
이렇게 촘촘히 설치했지만 서울에 설치되어있는 기상청 ASOS/AWS 관측소 숫자는 약 30개입니다.
서울에 25개 행정구가 있으니 1구에 1개 정도 있는 셈이죠.

이외에도 2020년부터 서울에서는 IoT 센서가 설치되어 기상 변수가 측정되고 있습니다.
서울 곳곳에 약 1000개의 IoT 센서가 설치되어 있고, 기상 변수 외에 다른 변수도 측정합니다.

기간은 2020년 4월부터 현재까지 시간은 1시간 간격으로 다음의 링크에서 S-DoT 자료를 다운로드 받을 수 있습니다.
https://data.seoul.go.kr/dataList/OA-15969/S/1/datasetView.do
서울 내에서라면 최고의 공간해상도를 자랑하는 관측 자료입니다.
(AWS의 시간해상도는 1분이라 시간해상도 측면에서는 좀 많이 부실합니다.)
제가 알기로 아직 기상 분야에서 연구목적으로 S-DoT 자료를 많이 쓰지 않으므로 S-DoT 온도 자료 자체를 확인하는 것 자체에 의의가 있고, 간단하게 다른 자료(AWS, 레이더)와도 비교해보겠습니다.
- 사례 선정
S-DoT 자료를 봄철, 여름철, 가을철, 겨울철처럼 계절 별로, 아니면 오전, 오후처럼 시간별로 나눠서 온도의 분포가 어떻게 나타나는지 보는 것은 충분히 의미있지만 재미가 없죠.
그래서 전 공간 규모가 작은, 그래서 공간 해상도가 높은 S-DoT 자료를 써야 확인할 수 기상현상을 선별해서 분석해볼까 합니다.
2024년 8월 13일 잠실구장의 야구경기가 취소되었는데 이 때 서울 전역에서 비가 온 것이 아니라 잠실구장에 폭우가 쏟아졌다고 합니다.
다음 링크는 당시 상황을 설명하는 뉴스입니다. https://cm.asiae.co.kr/article/2024081319230371254
이 날 비가 잠실에만 비가 온 것은 아니고 지역마다 다른 시간에 비가 온듯합니다.
그러므로 2024년 8월 13일 집중호우 사례에 대해 S-DoT 기온장의 1시간 변화를 살펴보고자 합니다.
- S-DoT 자료 전처리
S-DoT 자료를 다운로드 받아서 실제로 열어보면 이걸 어떻게 분석해야하나?라는 고민이 생길 겁니다.
ASOS/AWS처럼 분석하기 쉽게 정리가 되어있지 않거든요.
이 부분에서 막히시는 분이 많을 것 같아 제가 사용한 전처리 과정을 순서대로 설명하겠습니다.
1. 다운로드 받기 & 읽기
다운로드 링크로 들어가면
2020, 2021, 2022, 2023년은 1년 단위로 정리가 되어있고 2024년은 1주일 단위로 정리되어있습니다.
2024년 8월 13일 집중호우 사례를 분석할 것이기 때문에
"전체파일 보기"를 누른 뒤
"S-DoT_NATURE_2024.08.12-08.18.csv" 파일을 다운로드 받습니다.
다음으로 메타파일인 "서울시 도시데이터 센서(S-DoT) 환경정보 설치 위치정보.xlsx"을 받습니다.
IoT 센서의 위도, 경도를 알아야 위치에 따른 기온 산포도를 그릴 수 있습니다.
자료를 읽는 코드는 아래와 같습니다.
import os
import pandas as pd
# 메타 파일 읽기
inpath = './data'
fn = '서울시 도시데이터 센서(S-DoT) 환경정보 설치 위치정보.xlsx'
df_meta = pd.read_excel(os.path.join(inpath, fn))
# S-DoT 자료 읽기
inpath = './data/2024'
fn = "S-DoT_NATURE_2024.08.12-08.18.csv"
df = pd.read_csv(os.path.join(inpath, fn), encoding="cp949")
pandas로 엑셀파일을 읽을 수 없다면 openpyxl 라이브러리를 설치해주세요. (pip install openpyxl)
그리고 이유는 모르겠는데 "S-DoT_NATURE_2024.08.12-08.18.csv"를 다운로드 받은 이후에 바로 pandas 라이브러리로 열면 이상하게 읽힙니다.

이 경우 엑셀로 연 다음 다른 이름으로 저장을 했더니 잘 읽힙니다.
왜 그런지 이유는 모르겠네요.
2. 메타 파일과 자료 파일 병합
다음으로 메타 파일(df_meta)와 자료 파일(df)을 합칩시다.
메타 파일에는 위도, 경도, 자료 파일에는 온도 자료가 있습니다.
병합하는 과정에서 해결해야하는 문제 세 개가 있습니다.
문제1: 측정시간의 문제
자료 파일에서 "측정시간" 열의 값을 확인해보면 13~23시가 없습니다.
아마 기록을 잘못하고 있는 것 같습니다.
그러므로 "등록일시" 열을 사용합시다.
다만 등록일시는 1시 07분, 1시 08분처럼 딱 1시간 간격이 아닙니다.
1시 7분, 1시 8분 자료는 둘 다 1시 자료이므로 이를 맞춰줍시다.
문제2: 메타 파일과 자료 파일 열 이름이 불일치함
메타 파일의 "모델 시리얼(*)"열은 자료 파일에서 "시리얼"에 해당합니다.
이름을 바꿔줍시다.
문제3: 메타 파일 위도, 경도 오류
아래 그림을 보면 은평구 IoT 센서의 위도, 경도가 반대로 되어있습니다.
위도가 경도보다 크면 둘을 바꿔줍시다.

varname = '온도 평균(℃)'
# 문제1: 등록일시 기반 1시간 자료로 전환
df = df[['시리얼', '등록일시', varname]]
df['등록일시_hour'] = pd.to_datetime(df['등록일시']).dt.strftime('%Y%m%d%H')
df['hour'] = pd.to_datetime(df['등록일시']).dt.strftime('%H')
df_grouped = df.groupby(['시리얼', '등록일시_hour'])[varname].mean().reset_index()
# 문제2: 열 이름을 같게 설정
df_meta['시리얼'] = df_meta['모델 시리얼(*)']
df_merged = df_grouped.merge(df_meta, on='시리얼', how='left')
# 문제3: 위도가 경도보다 클 때 위도, 경도 바꾸기
df_merged.loc[df_merged['위도'] > df_merged['경도'], ['위도', '경도']] = df_merged.loc[df_merged['위도'] > df_merged['경도'], ['경도', '위도']].values
3. 전처리 결과 확인
전처리 결과를 그림으로 간단하게 확인해봅시다.
이 날 잠실구장에서 비가 왔다고 하니 강남구, 송파구의 온도가 낮을 것입니다.
전 2024년 8월 13일 19시 온도를 확인하겠습니다.
그림의 최솟값은 20 최댓값은 40입니다.
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
fig, ax = plt.subplots(
figsize=(10, 6),
subplot_kw={'projection': ccrs.PlateCarree()}
)
# 2024년 8월 13일 19시만 추출
valid_data = df_merged[df_merged['등록일시_hour'] == '2024081319']
df_merged
scatter= ax.scatter(valid_data['경도'].values, valid_data['위도'].values, c=valid_data[varname].values,
cmap='coolwarm', s= 5, vmin=20, vmax=40)
ax.set_extent([126.73, 127.27, 37.4, 37.7], crs=ccrs.PlateCarree())

강남, 송파구 뿐만 아니라 서울의 남쪽 모든 지역의 온도가 다른 지역보다 낮습니다.
온도장이 합리적으로 보이긴 하는데 엄청나게 파란점들이 있습니다.
제가 값을 확인해보니 -40도입니다. 아마 결측을 -40도로 찍는듯합니다.

혹시 모르니 온도의 빈도를 bar 그래프로 그려봅시다.

-40도가 결측인 것은 알겠는데 0~10도 사이에도 값이 있습니다.
제 생각에는 이건 센서의 문제입니다.
아무래도 품질관리와 비슷한 알고리즘을 써서 자료 처리를 해야겠습니다.
저는 평균에서 +3 * 표준편차보다 크거나 -3 * 표준편차보다 작은 경우를 제외했습니다.
관측 자료의 품질검사를 할 때 특정 표준편차만큼 벗어난 값을 제거하긴 하지만 3배라는 기준은 제가 임의적으로 고른 것입니다.
혹시 연구나 분석에 S-DoT 자료를 사용할 분들은 좀 더 정밀한 자료 처리 과정을 쓰시길 바랍니다.
# 결측값 제거
valid_data_ = df_merged.dropna(subset=['경도', '위도', varname])
# -40 값 제거
valid_data_ = valid_data_[valid_data_[varname] > -40]
# 평균에서 3 표준편차보다 크거나 작은 경우 제거
mean_value = valid_data_[varname].mean()
std_value = valid_data_[varname].std()
lower_bound = mean_value - 3 * std_value
upper_bound = mean_value + 3 * std_value
valid_data_ = valid_data_[(valid_data_[varname] >= lower_bound) & (valid_data_[varname] <= upper_bound)].reset_index()
# 아래는 이전 그림에서 쓴 코드와 같음
valid_data = valid_data_[valid_data_['등록일시_hour'] == '2024081319']
import matplotlib.pyplot as plt
import cartopy.crs as ccrs
fig, ax = plt.subplots(
figsize=(10, 6),
subplot_kw={'projection': ccrs.PlateCarree()}
)
scatter= ax.scatter(valid_data['경도'].values, valid_data['위도'].values, c=valid_data[varname].values,
cmap='coolwarm', s= 5, vmin=20, vmax=40)
ax.set_extent([126.73, 127.27, 37.4, 37.7], crs=ccrs.PlateCarree())

좀 아직 좀 많이 파란 점이 있긴 하지만 이 정도면 훨씬 봐줄만한 것 같습니다.
다음 포스트에서는 시간별로 S-DoT 온도장이 어떻게 변하는지 레이더 자료와 비교해보겠습니다.
'대기과학 > 프로그래밍' 카테고리의 다른 글
[python] 스마트서울 도시데이터 센서(S-DoT)로 보는 집중호우 발생시 온도장: 2. 온도장 확인 및 레이더 에코와 비교 (0) | 2025.01.08 |
---|---|
[python, html/css] 안개 속보 화면 만들기: 4. html 파일 만들기 (1) | 2024.12.09 |
[python, html/css] 안개 속보 화면 만들기: 3. 시정 자료로 그림 그리기 (0) | 2024.12.05 |
[python, html/css] 안개 속보 화면 만들기: 2. 자료 다운로드와 처리 (4) | 2024.12.04 |
[python, html/css] 안개 속보 화면 만들기: 1. 흐름 및 계획 (0) | 2024.12.03 |