好的,我有一个很大的数据框,例如:
hour value
0 0 1
1 6 2
2 12 3
3 18 4
4 0 5
5 6 6
6 12 7
7 18 8
8 6 9
9 12 10
10 18 11
11 12 12
12 18 13
13 0 14
让我们不要迷失在这里。列hour
表示一天中的小时数,从6到6小时。列values
很好,确切地说,这里的值是一个例子,而不是实际值。
如果仔细查看hour
列,可以看到缺少时间。例如,第7行和第8行之间存在间隙(缺少小时0的值)。还有更大的差距,例如在第10行和第11行之间(00和06年)。
我需要什么?我想检查一个小时(当然)缺少一个值的时间,并完成数据框插入一行,其中包含相应的小时和{{1作为价值。
我有什么想法?我认为这很容易使用模运算来解决,在这种情况下使用mod 24,例如np.nan
时。因此,将计数器初始化为零并添加6 ,并注意计数器在模块化算术模型24中定义,您可以验证每个18 + 6 = 24 = 0 mod 24
是否为相应的小时,如果不是,则插入带有相应小时的新行,其值为hour
。
我不知道如何在python中执行模运算来迭代数据帧列。
非常感谢。
答案 0 :(得分:6)
group_hours = (df.hour <= df.hour.shift()).cumsum()
def insert_missing_hours(df):
return df.set_index('hour').reindex([0, 6, 12, 18]).reset_index()
df.groupby(group_hours).apply(insert_missing_hours).reset_index(drop=1)
看起来像:
hour value
0 0 1.0
1 6 2.0
2 12 3.0
3 18 4.0
4 0 5.0
5 6 6.0
6 12 7.0
7 18 8.0
8 0 NaN
9 6 9.0
10 12 10.0
11 18 11.0
12 0 NaN
13 6 NaN
14 12 12.0
15 18 13.0
16 0 14.0
17 6 NaN
18 12 NaN
19 18 NaN
为了应用reindex
,我需要确定要分组的行。我检查了行的小时是否小于或等于前一行的小时。如果是,则标记一个新组。
insert_missing_hours
正是具有reindex
的{{1}}子组。
答案 1 :(得分:4)
尽管此解决方案更复杂,但它应该更加高效,尤其是对于较大的数据帧。此解决方案创建一个小时和值列表(包括任何填充小时),然后使用此列表生成数据帧。
def hour_checker(hours, values):
def check_hour(hour):
if hour not in (0, 6, 12, 18):
raise ValueError('Invalid hour')
[check_hour(hour) for hour in hours]
result = []
valid_hours = np.arange(0, 24, 6)
while valid_hours[-1] != hour:
# Initialize.
valid_hours = np.roll(valid_hours, -1)
result.append([hours.iat[0], values.iat[0]])
for hour, value in zip(hours.iloc[1:], values.iloc[1:]):
while hour != valid_hours[0]:
result.append([valid_hours[0], None])
valid_hours = np.roll(valid_hours, -1)
result.append([hour, value])
valid_hours = np.roll(valid_hours, -1)
return pd.DataFrame(result, columns=['hour', 'value'])
hour_checker(df['hour'], df['value'])
Out[33]:
hour value
0 0 1
1 6 2
2 12 3
3 18 4
4 0 5
5 6 6
6 12 7
7 18 8
8 0 NaN
9 6 9
10 12 10
11 18 11
12 0 NaN
13 6 NaN
14 12 12
15 18 13
16 0 14
<强>计时强>
df_test = pd.concat([df] * 100)
%%timeit
group_hours = (df_test.hour <= df_test.hour.shift()).cumsum()
df_test.groupby(group_hours).apply(insert_missing_hours).reset_index(drop=1)
1 loops, best of 3: 611 ms per loop
%timeit hour_checker(df_test['hour'], df_test['value'])
100 loops, best of 3: 12.4 ms per loop