和鲸社区Python刷题

Posted by Atmospheric Chemistry & Satellite Remote Sensing on May 23, 2023

前言

本文记录和鲸社区的Python刷题记录及题解。

2.1_气象Python中常用的基本库

Q1: 读取/home/mw/input/fnl6384/fnl/文件夹下所有 GRIB2 文件,计算其中最早和最晚两个时间之间相差多少小时。然后对这个小时值求 sin 值。请问这个值的前 5 位有效数字是多少?

提示:

  • 注意什么是有效数字,及其“四舍六入五留双”的修约规则。如,0.12345 的 前 4 位有效数字为 1234。
  • 在下方 cell 中编写并运行你的代码,将结果赋值给 a1。

题解代码

import numpy as np
import os
import math
import re
from datetime import datetime

dir_path = "/home/mw/input/fnl6384/fnl/"  # 目录路径

files = os.listdir(dir_path)  # 获取目录下的所有文件名列表

# 定义正则表达式,用于从文件名中提取时间信息

pattern = r'fnl_(\d{8})_(\d{2})_(\d{2})\.grib2'

# 获取目录下的所有文件名
files = os.listdir('/home/mw/input/fnl6384/fnl/')

# 从文件名中提取时间信息,并存储到字典中

time_dict = {}
for file in files:
    match = re.search(pattern, file)
    if match:
        time_str = match.group(1) + match.group(2) + match.group(3)
        time_dict[file] = int(time_str)

# 按照时间顺序对文件名进行排序

sorted_files = sorted(time_dict, key=time_dict.get)

# 输出排序后的文件名列表

print(sorted_files)
a = sorted_files[0]
b = sorted_files[-1]
print(a)
print(b)
c = math.sin(738)
print(c)
a1 = 27085

2.2_NumPy 数组基础

Q1: 生成两个数组,两者的大小都为(10000000,),元素都在[0,1]的区间内随机分布。对两者相同位置上的每个元素分别求平方和,然后保存到另一个(10000000,)的数组中。计算这个数组中小于 1 的数组的个数,并将其除以 10000000,再乘以 400。这个值取整后是多少?

提示:想一想,上面的操作究竟是在干什么?如果你想通的话,也许根本不用计算,就能答出来这个问题了。

import xarray as xr

# 生成两个数组

arr1 = np.random.rand(10000000)
arr2 = np.random.rand(10000000)

# 计算两个数组对应元素的平方和

sums = np.square(arr1) + np.square(arr2)

# 统计符合条件的数组元素个数

count = np.count_nonzero(sums < 1)

# 计算结果并输出

result = int(np.round(count / 10000000 * 400))
print(result)

2.3 Pandas数据帧基础

Q1: 读取 /home/mw/input/beijing_weather5275/beijing_weather.csv 文件,计算 2021-09-18 00:00:00~2021-09-24 00:00:00 北京最高和最低露点温度之差(保留整数位)。

import pandas as pd
import numpy as np
df = pd.read_csv("/home/mw/input/beijing_weather5275/beijing_weather.csv")
df = df.replace(999999.000000, np.nan) #异常值替换为nan

def ludian(t,rh):

    if np.isnan(t) or np.isnan(rh):
        return np.nan

    else:
       return 237.7*(17.27*t/(237.7+t) + np.log( rh/100 ))/(17.27-(17.27*t/(237.7+t) + np.log( rh/100 )))  #求露点温度的公式

df['ludian'] = df.apply(lambda x : ludian(x['t'],x['rh']),axis=1)  
#将计算的露点温度加入dataframe
df.describe() 
#可以查看露点温度的最大值和最小值
a1=int(df.loc[:,"ludian"].max()-df.loc[:,"ludian"].min())

2.4_使用Python处理常见气象数据

Q1: 读取/home/mw/input/fnl6384/fnl/fnl_20210101_00_00.grib2文件,计算2021年1月1日0时,北半球(含赤道)地表以上 2 米( 注意:不是 2 米以上)温度最高值和最低值之差(保留整数)。提示:注意是北半球!可以用类似于 NumPy 中的切片方法,截取出北半球部分,然后再进行计算。

import xarray as xr
ds = xr.open_dataset("/home/mw/input/fnl6384/fnl/fnl_20210101_00_00.grib2",engine="pynio")  
# 读取数据
tem=ds['TMP_P0_L103_GLL0'][0,][0:91,:]   
#第二个方括号索引是第0维:地表2米数据;第三个方括号索引是经纬度坐标(赤道及以北)。
t= tem.max()-tem.min() #最大值-最小值
a1=int(t)
a1

2.5_使用Python处理常见气象数据

Q1. 站点气象数据的处理

在 /home/mw/input/beijing_weather5275/beijing_weather.csv 文件中,计算温度在 20 摄氏度以上(含)、相对湿度在55%以上(含)的时间中,平均露点温度(单位:摄氏度)是多少?(取其整数部分)提示:1. 如何按照多个条件进行筛选?筛两次就可以了。 2. 使用.values方法,可以获得 Dataframe 或 Series 的值,并以 NumPy 数组形式返回。当然,Pandas 也有求列平均的方法。看你自己的选择哦。3. 记得要处理异常值哦。

import pandas as pd
import numpy as np
df = pd.read_csv("/home/mw/input/beijing_weather5275/beijing_weather.csv")
df = df.replace(999999.000000, np.nan) #异常值999999替换为nan
df
def ludian(t,rh):
    if t>=20 and rh>=55:
            return 237.7*(17.27*t/(237.7+t) + np.log( rh/100 ))/(17.27-(17.27*t/(237.7+t) + np.log( rh/100 )))
df['ludian'] = df.apply(lambda x : ludian(x['t'],x['rh']),axis=1)
df.describe()
a1=int(df.loc[:,"ludian"].mean())
a1
a1 = 16
Q2. 网格化气象数据处理

利用 fnl 再分析数据,计算 2021 年 1 月(UTC)北半球(含赤道)平均 10 米风速(取整数部分)。

数据集路径:/home/mw/input/fnl6384(2.9G,体积较大,需要一些时间完成挂载)。

提示:先算出每个时刻的平均风速再求平均。

import glob
import xarray as xr
import numpy as np

file_name_list = glob.glob("/home/mw/input/fnl6384/fnl/fnl_*.grib2")  
# 返回文件名,以列表呈现
mean_values = []  
# 用于存储均值的列表

for i in file_name_list:
    ds = xr.open_dataset(i, engine="pynio")
    wind1 = ds['UGRD_P0_L103_GLL0'][0,][0:91, :]  
    # UGRD纬向风 VGRD径向风 风速=(UGRD^2+VGRD^2)^(1/2)
    wind2 = ds['VGRD_P0_L103_GLL0'][0,][0:91, :]
    wind_h = (wind1**2 + wind2**2)**(1/2)
    a2 = wind_h.mean()
    mean_values.append(a2)  # 将均值添加到列表中

mean_values = np.array(mean_values)
a2 = int(mean_values.mean())  # 对均值列表求均值

print("均值:", a2)
a2 = 5

Q1: 读取 FNL 再分析资料中 2021 年 1 月 1 日 0 时地表以上2m温度的二维数组。从该数组中,取出每个维度里索引号都属于斐波那契数列(即截取该数组每个维度里索引号为0,1,1,2,3,5…..的部分)的数组。然后计算新的数组中,温度大于等于 0℃ 格点的平均温度(单位:摄氏度),然后取整。

提示:

  • 完成下方 cell 的代码,将结果赋值给 a1。
  • FNL 再分析资料的数据集路径在哪里?左侧文件树 input 目录里。单击,进去,找到对应文件夹,右键可以复制路径。
  • 参考思路:搓个斐波那契函数→生成斐波那契数列→选取地面以上2m温度→条件索引→转化为摄氏度→求均值。
import xarray as xr
import numpy as np
import pandas as pd
def fibonacci(n):
    lis = []
    for i in range(n):
        if i == 1 or i == 0:
            lis.append(1)
        else:
            lis.append(lis[i-2]+lis[i-1])
    print(lis)
a = fibonacci(13)

ds = xr.open_dataset("/home/mw/input/fnl6384/fnl/fnl_20210101_00_00.grib2", engine="pynio")
tem = ds['TMP_P0_L103_GLL0'][0,]
list1 = [1,1,2,3,5,8,13,21,34,55,89,144,233]  #根据构造的斐波那契函数计算结果,再自行生成了新的数列。因为用函数生成的a的type是NoneType(不知道为什么),好像直接用报错了。
list2 = [1,1,2,3,5,8,13,21,34,55,89,144]
data1 = np.array(tem)
t_data1 = data1[np.ix_(list2,list1)]  #索引方式!! 花式索引索引器np.ix_,能帮我们更加灵活地索引我们的数组
t_data1
t_data2 = t_data1-273.15
t_data3 = t_data2[t_data2>0]
a1 = int(np.mean(t_data3))
print(a1)

参考文献及链接

Python for Atmosphere and Ocean Scientists

https://carpentries-lab.github.io/python-aos-lesson/