统计连续几天的温度数据
Counting consecutive days of temperature data
所以我有一些海面温度异常数据。这些数据已被过滤掉,因此这些是低于特定阈值的值。但是,我正在尝试识别寒潮 - 即隔离持续时间超过连续 5 天的事件。下面是我的数据示例(我一直在 xarray datasets/dataarrays 和 pandas 数据帧之间工作)。请注意,'day' 是我正在查看的月份的天数(最终将扩展到全年)。我一直在 SO/the 互联网上搜索基于 'day' 列提取这些 5 天或更长时间事件的方法,但我没有得到任何工作。我对编码还是比较陌生,所以我的第一个想法是遍历 'day' 列的行,但我不确定。任何见解表示赞赏。
下面是我的一些数据 pandas df:
lat lon time day ssta
5940 24.125 262.375 1984-06-03 3 -1.233751
21072 24.125 262.375 1984-06-04 4 -1.394495
19752 24.125 262.375 1984-06-05 5 -1.379742
10223 24.125 262.375 1984-06-27 27 -1.276407
47355 24.125 262.375 1984-06-28 28 -1.840763
... ... ... ... ... ...
16738 30.875 278.875 2015-06-30 30 -1.345640
3739 30.875 278.875 2020-06-16 16 -1.212824
25335 30.875 278.875 2020-06-17 17 -1.446407
41891 30.875 278.875 2021-06-01 1 -1.714249
27740 30.875 278.875 2021-06-03 3 -1.477497
64228 rows × 5 columns
作为过滤后的 xarray:
xarray.Dataset
Dimensions: lat: 28, lon: 68, time: 1174
Coordinates:
time (time) datetime64[ns] 1982-06-01 ... 2021-06-04
lon (lon) float32 262.1 262.4 262.6 ... 278.6 278.9
lat (lat) float32 24.12 24.38 24.62 ... 30.62 30.88
day (time) int64 1 2 3 4 5 6 7 ... 28 29 30 1 2 3 4
Data variables:
ssta (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
Attributes: (0)
TLDR;我想识别连续 5 天以上的事件(并保留其信息),即是否有第 3 天到第 8 天,或第 21 天到第 30 天等
我认为与其过滤您的原始数据,不如尝试以 pandas 的方式进行过滤,在这种情况下,这意味着根据您的条件获得一系列具有真假值的序列。
您的数据似乎不包括温度,所以这是我的示例:
import pandas as pd
import numpy as np
df = pd.DataFrame(data={'temp':np.random.randint(10,high=40,size=64228,dtype='int64')})
将生成一个 DataFrame,其单列包含 10 到 40 度之间的随机温度。请注意,我可以只使用自动生成的索引,但您可能必须使用 .set_index
将其切换到时间或日期之类的列。假设我们对连续超过 30 度的日子感兴趣。
is_over_30 = df['temp'] > 30
将为我们提供一个包含该信息的 True/False 数组。请注意,这种格式非常有用,因为我们可以使用它进行索引。例如。 df[is_over_30]
将为我们提供 dataframe
中温度超过 30 度的日子的行。现在我们想将 is_over_30
中的 True/False 值向前移动一个位置,并生成一个新的系列,如果两者都为真,则为真
is_over_30 & np.roll(is_over_30, -1)
基本上我们到这里就完成了,可以再写 3 个这样的 & rolls。但是有一种方法可以写得更简洁。
from functools import reduce
is_consecutively_over_30 = reduce(lambda a,b: a&b, [np.roll(is_over_30, -i) for i in range(5)])
请记住,即使过去 4 天不能连续超过 30 度,这仍然可能发生在这里,因为滚动将第一个值移到与之相关的位置。但是您可以将最后 4 个值设置为 False 来解决这个问题。
is_consecutively_over_30[-4:] = False
您可以使用这种方法拉出法术的日期范围:
min_spell_days = 6
days = {'day': [1,2,5,6,7,8,9,10,17,19,21,22,23,24,25,26,27,31]}
df = pd.DataFrame(days)
查找连续条目之间的天数:
diff = df['day'].diff()
标记法术的最后一天:
df['last'] = (diff == 1) & (diff.shift(-1) > 1)
累计每个咒语的天数:
df['diff0'] = np.where(diff > 1, 0, diff)
df['cs'] = df['diff0'].eq(0).cumsum()
df['spell_days'] = df.groupby('cs')['diff0'].transform('cumsum')
如果适用,将最后一个条目标记为法术的最后一天:
if diff.iat[-1] == 1:
df['last'].iat[-1] = True
Select所有排位法术的最后一天:
df_spells = (df[df['last'] & (df['spell_days'] >= (min_spell_days-1))]).copy()
确定每个法术的开始、结束和持续时间:
df_spells['end_day'] = df_spells['day']
df_spells['start_day'] = (df_spells['day'] - df['spell_days'])
df_spells['spell_days'] = df['spell_days'] + 1
结果df
:
df_spells[['start_day','end_day','spell_days']].astype('int')
start_day end_day spell_days
7 5 10 6
16 21 27 7
此外,使用日期算法 'day' 您可以表示相对于某个基准日期的序列号 - 例如 1/1/1900。这样就可以处理跨越月份和年份边界的咒语。然后使用日期算法和该序列号转换回日期将是微不足道的。
所以我有一些海面温度异常数据。这些数据已被过滤掉,因此这些是低于特定阈值的值。但是,我正在尝试识别寒潮 - 即隔离持续时间超过连续 5 天的事件。下面是我的数据示例(我一直在 xarray datasets/dataarrays 和 pandas 数据帧之间工作)。请注意,'day' 是我正在查看的月份的天数(最终将扩展到全年)。我一直在 SO/the 互联网上搜索基于 'day' 列提取这些 5 天或更长时间事件的方法,但我没有得到任何工作。我对编码还是比较陌生,所以我的第一个想法是遍历 'day' 列的行,但我不确定。任何见解表示赞赏。
下面是我的一些数据 pandas df:
lat lon time day ssta
5940 24.125 262.375 1984-06-03 3 -1.233751
21072 24.125 262.375 1984-06-04 4 -1.394495
19752 24.125 262.375 1984-06-05 5 -1.379742
10223 24.125 262.375 1984-06-27 27 -1.276407
47355 24.125 262.375 1984-06-28 28 -1.840763
... ... ... ... ... ...
16738 30.875 278.875 2015-06-30 30 -1.345640
3739 30.875 278.875 2020-06-16 16 -1.212824
25335 30.875 278.875 2020-06-17 17 -1.446407
41891 30.875 278.875 2021-06-01 1 -1.714249
27740 30.875 278.875 2021-06-03 3 -1.477497
64228 rows × 5 columns
作为过滤后的 xarray:
xarray.Dataset
Dimensions: lat: 28, lon: 68, time: 1174
Coordinates:
time (time) datetime64[ns] 1982-06-01 ... 2021-06-04
lon (lon) float32 262.1 262.4 262.6 ... 278.6 278.9
lat (lat) float32 24.12 24.38 24.62 ... 30.62 30.88
day (time) int64 1 2 3 4 5 6 7 ... 28 29 30 1 2 3 4
Data variables:
ssta (time, lat, lon) float32 nan nan nan nan ... nan nan nan nan
Attributes: (0)
TLDR;我想识别连续 5 天以上的事件(并保留其信息),即是否有第 3 天到第 8 天,或第 21 天到第 30 天等
我认为与其过滤您的原始数据,不如尝试以 pandas 的方式进行过滤,在这种情况下,这意味着根据您的条件获得一系列具有真假值的序列。
您的数据似乎不包括温度,所以这是我的示例:
import pandas as pd
import numpy as np
df = pd.DataFrame(data={'temp':np.random.randint(10,high=40,size=64228,dtype='int64')})
将生成一个 DataFrame,其单列包含 10 到 40 度之间的随机温度。请注意,我可以只使用自动生成的索引,但您可能必须使用 .set_index
将其切换到时间或日期之类的列。假设我们对连续超过 30 度的日子感兴趣。
is_over_30 = df['temp'] > 30
将为我们提供一个包含该信息的 True/False 数组。请注意,这种格式非常有用,因为我们可以使用它进行索引。例如。 df[is_over_30]
将为我们提供 dataframe
中温度超过 30 度的日子的行。现在我们想将 is_over_30
中的 True/False 值向前移动一个位置,并生成一个新的系列,如果两者都为真,则为真
is_over_30 & np.roll(is_over_30, -1)
基本上我们到这里就完成了,可以再写 3 个这样的 & rolls。但是有一种方法可以写得更简洁。
from functools import reduce
is_consecutively_over_30 = reduce(lambda a,b: a&b, [np.roll(is_over_30, -i) for i in range(5)])
请记住,即使过去 4 天不能连续超过 30 度,这仍然可能发生在这里,因为滚动将第一个值移到与之相关的位置。但是您可以将最后 4 个值设置为 False 来解决这个问题。
is_consecutively_over_30[-4:] = False
您可以使用这种方法拉出法术的日期范围:
min_spell_days = 6
days = {'day': [1,2,5,6,7,8,9,10,17,19,21,22,23,24,25,26,27,31]}
df = pd.DataFrame(days)
查找连续条目之间的天数:
diff = df['day'].diff()
标记法术的最后一天:
df['last'] = (diff == 1) & (diff.shift(-1) > 1)
累计每个咒语的天数:
df['diff0'] = np.where(diff > 1, 0, diff)
df['cs'] = df['diff0'].eq(0).cumsum()
df['spell_days'] = df.groupby('cs')['diff0'].transform('cumsum')
如果适用,将最后一个条目标记为法术的最后一天:
if diff.iat[-1] == 1:
df['last'].iat[-1] = True
Select所有排位法术的最后一天:
df_spells = (df[df['last'] & (df['spell_days'] >= (min_spell_days-1))]).copy()
确定每个法术的开始、结束和持续时间:
df_spells['end_day'] = df_spells['day']
df_spells['start_day'] = (df_spells['day'] - df['spell_days'])
df_spells['spell_days'] = df['spell_days'] + 1
结果df
:
df_spells[['start_day','end_day','spell_days']].astype('int')
start_day end_day spell_days
7 5 10 6
16 21 27 7
此外,使用日期算法 'day' 您可以表示相对于某个基准日期的序列号 - 例如 1/1/1900。这样就可以处理跨越月份和年份边界的咒语。然后使用日期算法和该序列号转换回日期将是微不足道的。