如何在熊猫中有效展开日期范围?

时间:2014-09-17 15:42:53

标签: python pandas

我有一个Pandas数据帧(attendance_records)。它包含当地学校的出勤记录。

每行有4列:1)缺席的学生姓名(姓名),2)学生的地址(地址),3)缺席的第一天(开始),以及4)最后一天缺席日(结束)。

例如,一行可以是:

Bobby   101 1st Street  9/1/2014     9/3/2014

这意味着Bobby每天都在9/1和9/3(含)之间缺席。

我想按照以下方式展开表格:

Bobby 101 1st Street 9/1/2014
Bobby 101 1st Street 9/2/2014
Bobby 101 1st Street 9/3/2014

到目前为止,我有一些代码(下面)可以完成这项工作,但是对于大型表来说它实际上很慢,因为它基本上是逐行遍历表。关于如何让事情变得更快的任何想法?

import pandas as pd
def full_data(dataframe):
    allframe = pd.DataFrame()
    for i in dataframe.index:
        newframe = pd.DataFrame()
        newframe['dates'] = pd.date_range(dataframe.iloc[i].start, dataframe.iloc[i].end, freq = 'D')
        newframe['name'] = dataframe.iloc[i]['name']
        newframe['address'] = dataframe.iloc[i]['address']            
        allframe = allframe.append(newframe)
        if i%1000 == 0:
            print i
    return allframe

attendance_records = full_data(attendance_records)

2 个答案:

答案 0 :(得分:2)

对于较大的数据帧,pandas函数append可能会很慢。相反,我建议将newframes存储在python列表中,而不是使用concat函数将所有帧仅附加一次。

import pandas as pd
def full_data(dataframe):
    allframes = []
    for i in dataframe.index:
        newframe = pd.DataFrame()
        newframe['dates'] = pd.date_range(dataframe.iloc[i].start, dataframe.iloc[i].end, freq = 'D')
        newframe['name'] = dataframe.iloc[i]['name']
        newframe['address'] = dataframe.iloc[i]['address']            
        allframes.append(newframe)
    return concat(allframes)

请注意,这尚未经过测试。

答案 1 :(得分:0)

对日期执行日期算术,您不需要填写缺失的日期。然后按名称分组并总计天数。

from datetime import timedelta

data = pd.read_csv(StringIO('''Bobby,   101 1st Street,  9/1/2014,     9/3/2014'''), 
                   names=['Name', 'Address', 'Start', 'End'], parse_dates=[2, 3])
#add a day to get the number of days inclusive
data["Days"] = (data.End - data.Start) + timedelta(days=1)
data.groupby('name').sum()["Days"]