python中的模块化算法迭代pandas数据帧

时间:2016-05-19 15:58:46

标签: python pandas numpy dataframe

好的,我有一个很大的数据框,例如:

      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中执行模运算来迭代数据帧列。

非常感谢。

2 个答案:

答案 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