行式DataFrame分段

时间:2017-02-09 17:38:51

标签: python pandas boolean-expression

鉴于以下数据框:

    df = pd.DataFrame(data={'item': [1, 2, 3, 4], 'start':[0.0, 2.0, 8.0, 6.0], 
                            'end': [2.0, 6.0, 8.0, 14.0]})

如何通过将间隔“开始” - “结束”分段为2的倍数来快速扩展上述数据帧?

对于上面的示例,结果数据框应为

    Out=
       item  start   end    
       1     0.0     2.0
       2     2.0     4.0
       2     4.0     6.0
       3     8.0     8.0
       4     6.0     8.0  
       4     8.0     10.0  
       4     10.0    12.0  
       4     12.0    14.0  

性能对我来说至关重要,因为我需要检查数百万行。 对于那些不需要分段的行,我已经使用布尔索引过滤了整个数据帧。这是一个很好的加速但是,在其余的行上我应用了'for循环'并使数据帧具有正确的长度,我一直在追加。不幸的是,数百万行的性能还不够。

期待专家解决方案!

2 个答案:

答案 0 :(得分:0)

您可以编写一个返回扩展开始和结束时间的DataFrame的函数。在此示例中,我将item分组,因为我不确定您是否可以从apply返回DataFrame,而不会先将其分组。

def convert(row):
    start = row.start.values[0]
    end = row.end.values[0]
    if start == end:
        return pd.DataFrame([[start, end]], columns=['start', 'end'])
    else:
        return pd.DataFrame({'start': np.arange(start, end, 2),
                            'end':np.arange(start + 2, end + 2, 2)},
                           columns=['start', 'end'])

df1=df.groupby('item').apply(convert)
df1.index = df1.index.droplevel(1)
df1.reset_index()

    item  start   end
0     1    0.0   2.0
1     2    2.0   4.0
2     2    4.0   6.0
3     3    8.0   8.0
4     4    6.0   8.0
5     4    8.0  10.0
6     4   10.0  12.0
7     4   12.0  14.0

答案 1 :(得分:0)

从原始数据框开始:

    import pandas as pd
    import numpy as np
    df = pd.DataFrame(data={'item': [1, 2, 3, 4], 'start':[0.0, 2.0, 8.0, 6.0], 
                            'end': [2.0, 6.0, 10.0, 14.0]})

然后,运行以下代码:

    lengths = pd.Series([1, 2, 1, 4]) #  For the example, I just created this array, 
                                      #  but obviously I would use the mod function to 
                                      #  determine the number of segments to create

    # Row below elongates the dataframe according to the array 'lengths'

    df = df.reindex(np.repeat(df.index.values, lengths), method='ffill')
    df['start'] += pd.Series(df.groupby(level=0).cumcount()*2.0)
    df['end'] = df['start'] + 2.0
    print df

请注意,初始数据框包含错误。项目'3'需要'start = 8.0'和'end = 10.0'。

我相信这种方法非常快,因为使用了pandas Cython函数。当然,仍然可以接受其他可能性。