传统netCDF4解析nc文件的思路:
提取出各个要素值
# 读取文件
dataset = nc.Dataset(file)
# 提取要素
lon = dataset.variables['longitude'][:]
lat = dataset.variables['latitude'][:]
obstime = dataset.variables['time'][:]
mwd_dataset = dataset.variables['mwd'][:]
mwp_dataset = dataset.variables['mwp'][:]
swh_dataset = dataset.variables['swh'][:]
之后通过循环的方式,获取具体要素值
for i in range(len(obstime)):
print(i)
for j in range(1):
for k in range(len(lat)):
for l in range(len(lon)):
d = datetime.datetime(1900, 1, 1, 0, 0, 0)
d += datetime.timedelta(hours=float(obstime[i]))
geoId = geo.encode(lat[k], lon[l])
mwd_str = str(mwd[i][0][k][l])
mwp_str = str(mwp[i][0][k][l])
swh_str = str(swh[i][0][k][l])
(这里转成str格式是为了拼接sql)
拼接sql或者生成csv导入数据库,此类方法可以实现数据的入库和提取,但是耗费的时间也是很大的。文件越大,循环的耗时越严重。
新的思路是,减少循环或者尽量不循环,将提取的要素(不论是几维数组)均转换为1维数组,同理配置好其他要素数组的长度,
使得值与值之间仍是一一对应的关系。
最后存入dict中,使用pandas的方法生成csv,从而达到不经过循环直接保存数据的效果。
def readDs():
t1 = time.time()
file = 'F:/data/nc/wave/2018-2021/wave_chinasea_2018_2021.nc'
# 读取文件
dataset = nc.Dataset(file)
# 提取要素
lon = dataset.variables['longitude'][:]
lat = dataset.variables['latitude'][:]
obstime = dataset.variables['time'][:]
mwd_dataset = dataset.variables['mwd'][:]
mwp_dataset = dataset.variables['mwp'][:]
swh_dataset = dataset.variables['swh'][:]
t2 = time.time()
print('读文件耗时:', t2 - t1)
lat_list = []
lon_list = []
geohash_fuc = geohash.geoHash()
geo_list = []
for i in range(len(lat)):
for j in range(len(lon)):
lat_list.append(lat[i])
lon_list.append(lon[j])
geoId = geohash_fuc.encode(lat[i], lon[j])
geo_list.append(geoId)
for i in range(len(obstime)):
t3 = time.time()
d = datetime.datetime(1900, 1, 1, 0, 0, 0)
d += datetime.timedelta(hours=float(obstime[i]))
time_temp = np.array([d for _ in range(len(lat_list))])
mwd_2D = mwd_dataset[i][0][:][:]
mwp_2D = mwp_dataset[i][0][:][:]
swh_2D = swh_dataset[i][0][:][:]
# 将数组规整为一维数组
mwd_1D = mwd_2D.reshape(-1)
mwp_1D = mwp_2D.reshape(-1)
swh_1D = swh_2D.reshape(-1)
dicts = {"geoId": geo_list,"obstime": time_temp, "lon": lon_list, "lat": lat_list, "mwd": mwd_1D,
"mwp": mwp_1D,
"swh": swh_1D}
df = pd.DataFrame(dicts)
outfile = 'F:/data/nc/wave/2018-2021/product/'
if not os.path.exists(outfile):
os.mkdir(outfile)
df.to_csv(outfile + 'wave_' + str(i) + '.csv', index=False)
t4 = time.time()
print("输出一个文件耗时 : ", (t4 - t3))
t55 = time.time()
print("总耗时:", (t55 - t1))
生成csv后再存入数据库
def toCk():
path = 'F:/data/nc/wave/2018-2021/product'
file_list = os.listdir(path)
# 循环导入数据库
for file in file_list:
try:
sh = 'clickhouse-client -m --host xxx.xxx.xxx.xx --port 9000 --user xxxxxx --password xxxxxx --query=\"insert into xxx.xxx format CSVWithNames\" < ' + file
os.system(sh)
except Exception as e:
print(file+' 异常:'+str(e))
重点部分在于将多维数组转成一维数组,直接生成文件,避免循环的耗时
平均生成csv文件耗时:
输出一个文件耗时 : 0.06984543800354004
输出一个文件耗时 : 0.07875680923461914
输出一个文件耗时 : 0.0728306770324707
欢迎讨论。