92 lines
5.0 KiB
Python
92 lines
5.0 KiB
Python
import pandas as pd
|
||
from tqdm import tqdm
|
||
import os
|
||
df = pd.read_parquet("./data/flash/FLASH_2024.parquet")
|
||
|
||
'''
|
||
时间 微秒 纬度 经度 电流 回击 ... 误差椭圆长半轴方向 标志 陡度 时间差 RawID GUID
|
||
0 1/1/2024 03:16:40 5888618 25.850505 106.476598 -17.1 1 ... 118 0 0 0 1050961381,1050961380; 165612266
|
||
1 1/1/2024 03:42:33 7173002 25.684971 106.972500 73.1 1 ... 104 0 0 0 1050979230,1050979226,1050979231;1050979227,10... 165612269
|
||
2 1/1/2024 04:11:28 1344128 25.544373 106.873714 45.7 1 ... 87 0 0 0 1050991636,1050991653,1050991654;1050991651,10... 165612271
|
||
3 1/1/2024 04:37:00 2312000 26.191353 105.803525 -12.9 1 ... 118 0 0 0 1051001690,1051001680; 165612285
|
||
4 1/1/2024 05:22:22 1754035 26.291300 106.622184 -29.1 1 ... 0 0 0 0 1051017776,1051017786,1051017785; 165612299
|
||
'''
|
||
# 只保留需要的列并解析时间
|
||
df = df[['时间', '微秒', '纬度', '经度', '电流']].copy()
|
||
|
||
# 解析时间列,只保留日期和时分秒(不需要微秒)
|
||
# 先将'时间'列转换为datetime对象,格式为日/月/年 时:分:秒
|
||
df['时间'] = pd.to_datetime(df['时间'], format='%d/%m/%Y %H:%M:%S')
|
||
|
||
|
||
df_station_id = pd.read_csv("station_id.csv")
|
||
EFID = df_station_id["EFID"].to_list()
|
||
Longitude = df_station_id["Longitude"].to_list()
|
||
Latitude = df_station_id["Latitude"].to_list()
|
||
|
||
for id,lat,lon in zip(EFID,Latitude,Longitude):
|
||
|
||
# 2. 定义目标点和范围 (与之前相同)
|
||
target_lon = lon
|
||
target_lat = lat
|
||
degree_range = 0.15
|
||
|
||
# 3. 筛选在指定经纬度范围内的点 (与之前相同)
|
||
df_filtered = df[
|
||
(df['经度'] >= target_lon - degree_range) &
|
||
(df['经度'] <= target_lon + degree_range) &
|
||
(df['纬度'] >= target_lat - degree_range) &
|
||
(df['纬度'] <= target_lat + degree_range)
|
||
].copy()
|
||
|
||
# 4. 核心逻辑修正:使用 resample 和 rolling
|
||
if df_filtered.empty:
|
||
# 输出未找到雷电数据的提示,并显示经纬度范围
|
||
lon_min: float = target_lon - degree_range # 计算经度下限
|
||
lon_max: float = target_lon + degree_range # 计算经度上限
|
||
lat_min: float = target_lat - degree_range # 计算纬度下限
|
||
lat_max: float = target_lat + degree_range # 计算纬度上限
|
||
print(f"{id}在指定范围内(经度: {lon_min:.5f}~{lon_max:.5f}, 纬度: {lat_min:.5f}~{lat_max:.5f})没有找到雷电数据。")
|
||
else:
|
||
# 将时间设置为索引
|
||
df_filtered.set_index('时间', inplace=True)
|
||
|
||
# 创建一个表示雷电事件的 Series,每个事件计为 1
|
||
# 然后按5秒的间隔重采样,并对每个间隔内的事件求和
|
||
# 这会得到一个时间序列,其中索引是每5秒,值是该5秒内发生的雷电次数
|
||
lightning_counts_per_5s = df_filtered.resample('5S').size()
|
||
|
||
# 使用滚动窗口计算未来30分钟的雷电数
|
||
# window='30min' 定义了窗口大小
|
||
# 为了实现“未来”30分钟的计数,我们使用一个技巧:
|
||
# 1. 将时间序列反转 (iloc[::-1])
|
||
# 2. 使用一个标准的向后看的滚动窗口
|
||
# 3. 再将结果反转回来
|
||
# 这样就等效于一个向前看的滚动窗口
|
||
# closed='right' 确保窗口包含其起始点(在反转前)
|
||
future_counts = lightning_counts_per_5s.iloc[::-1].rolling(window='30min', closed='right').sum().iloc[::-1]
|
||
|
||
# 上一步的结果只包含有雷电的5秒间隔。现在我们需要创建一个完整的时间范围。
|
||
# 定义我们关心的完整时间范围的开始和结束
|
||
start_time = df_filtered.index.min().floor('D') # 从数据第一天的零点开始
|
||
end_time = df_filtered.index.max().ceil('D') # 到数据最后一天的零点结束
|
||
|
||
# 创建一个从开始到结束,每隔5秒一个点的完整时间索引
|
||
full_time_index = pd.date_range(start=start_time, end=end_time, freq='5S')
|
||
|
||
# 将我们计算出的结果填充到这个完整的时间索引上
|
||
# reindex 会自动对齐索引,没有值的地方会填充为 NaN,我们再用 fillna(0) 填充为 0
|
||
final_result = future_counts.reindex(full_time_index).fillna(0).astype(int)
|
||
|
||
# 重命名列并计算flash_count的分布
|
||
result_df = final_result.reset_index()
|
||
result_df.columns = ['time', 'flash_count']
|
||
|
||
# 计算flash_count列中每个数值的数量
|
||
flash_count_distribution = result_df['flash_count'].value_counts().sort_index()
|
||
print("\nflash_count列中每个数值的数量:")
|
||
print(flash_count_distribution)
|
||
|
||
# 您也可以将结果保存到文件
|
||
os.makedirs(f'data/preprocessed_flash/{id}/',exist_ok=True)
|
||
result_df.to_parquet(f'data/preprocessed_flash/{id}/flash_{id}.parquet') |