我有一个日常温度的数据集,我想用20年计算。数据如下所示:
1974 1 1 5.3 4.6 7.3 3.4
1974 1 2 3.3 7.2 4.5 6.5
...
2005 12 364 4.2 5.2 3.3 4.6
2005 12 365 3.1 5.5 2.6 6.8
文件中没有标题,但第一列包含年份,第二列包含月份,第三列包含一年中的日期。其余列是温度数据。
我想计算20年内每天的平均温度。我认为最好的方法是按天分组数据并计算特定年份范围内每天的平均值。这是我的代码:
import pandas as pd
hist_fn = 'tmean_daily_1974_2005.txt'
twenty_year_fn = '20_yr_mean_1974_1993.txt'
start = 1974
end = 1993
hist_mean = pd.read_csv(hist_fn, sep='\s+', header=None)
# Limit dataframe to only the 20 years for which I want the mean calculated
interval_mean = hist_mean[(hist_mean[0]>=start) & (hist_mean[0]<=end)]
# Rename the first column to reflect what mean this file is displaying
interval_mean.iloc[:, 0] = ("%s-%s" % (start, end))
# Generate mean for each day spread across all the years in the dataframe
interval_mean.iloc[:, 3:] = interval_mean.groupby(2, as_index=False).mean().iloc[:, 2:]
# Write multiyear mean to txt
interval_mean.to_csv(twenty_year_fn, sep='\t', header=False, index=False)
数据集的使用时间超过20年,我使用的方法在前20年的时间间隔内工作,但是对于我输入的任何其他年份,我给出了一个(大部分)空文本文件。
因此,当我使用这些输入时,它可以工作:
start = 1974
end = 1993
并生成一个如下所示的文件:
1974-1993 1 1 4.33 5.25 6.84 3.67
1974-1993 1 2 7.23 6.22 5.65 6.23
...
1974-1993 12 364 5.12 4.34 5.21 2.16
1974-1993 12 365 4.81 5.95 3.56 6.78
但是当我将输入更改为:
start = 1975
end = 1994
它生成一个没有温度的.txt文件:
1975-1994 1 1
1975-1994 1 2
...
1975-1994 12 364
1975-1994 12 365
我不明白为什么这种方法适用于前20年的间隔,但没有后续的间隔。这与数据的组织方式或切片方式有关吗?
答案 0 :(得分:0)
现在,当这个问题解决时,我们可以谈谈您提出的问题:
奇怪的行为是由于 pandas匹配赋值时的索引,切片保留了原始索引。这意味着在设置时
interval_mean.iloc[:, 3:] = interval_mean.groupby(2, as_index=False).mean().iloc[:, 2:]
请注意interval_mean.groupby(2, as_index=False).mean()
有索引0, ... , 30
(因为as_index=False
使groupby操作创建新索引。否则,它将是天数。)另一个,interval_mean
1}}具有来自hist_mean
的原始索引,这意味着第一次(前20年)它具有索引0, ..., ~20*365
,第二次具有从arround 20*365
开始并且向上计数的索引
起初这有点令人困惑,但是大熊猫提供了很好的documentation,人们很快发现它为何如此有用。 我将用一个例子来解释会发生什么:
假设我们有以下DataFrame
:
df = pd.DataFrame(np.reshape(np.random.randint(5, size=30), [-1,3]))
df
0 1 2
0 1 1 2
1 2 1 1
2 0 1 2
3 0 2 0
4 2 1 0
5 0 1 2
6 2 2 1
7 1 0 2
8 0 1 0
9 1 2 0
请注意,列名称为0,1,2
,行名称(索引)为0, ..., 9
。
当我们预先形成groupby
时,我们获得了
df.groupby(0, as_index=False).mean()
0 1 2
0 0 1.250000 1.000000
1 1 1.000000 1.333333
2 2 1.333333 0.666667
(索引等于仅因为0
到2
之间的绘制数字而分组的列)。现在,何时将对df.loc
进行分配,如果存在此类单元格,它将替换受让人中相应单元格的每个单元格。否则,它将离开NA
。
df.loc[:,:] = df.groupby(0, as_index=False).mean()
df
0 1 2
0 0.0 1.250000 1.000000
1 1.0 1.000000 1.333333
2 2.0 1.333333 0.666667
3 NaN NaN NaN
4 NaN NaN NaN
5 NaN NaN NaN
6 NaN NaN NaN
7 NaN NaN NaN
8 NaN NaN NaN
9 NaN NaN NaN
当您将NA
写入csv时,它会将单元格留空。
最后一个难题是interval_mean
如何保留原始索引,但这是因为切片保留了原始索引:
df[df[1] > 1]
0 1 2
3 0 2 0
6 2 2 1
9 1 2 0