2014-09-17 3 views
4

У меня есть кадр данных Pandas (attendance_records). Он содержит записи о посещаемости в местной школе.Как эффективно развернуть диапазон диапазонов дат в Pandas?

Каждая строка имеет 4 столбца: 1) имя учащегося, отсутствующего (имя), 2) адрес студента (адрес), 3) первый день отсутствия (начало) и 4) последний день отсутствия (конец).

Например, одна строка может быть:

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

Это означает, что Бобби отсутствовал каждый день между 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 

До сих пор у меня есть некоторый код (ниже), который будет делать эту работу, но это realllly медленно на больших таблиц, потому что это в основном происходит по строкам через таблицу. Любые идеи о том, как сделать вещи быстрее?

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

Функция 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) 

Примечание. Это еще не проверено.

+0

Спасибо, это было полезно. Думаю, в Пандах нет встроенной функции для достижения этого результата? – monkeybiz7

+0

Там может быть что-то немного чище. Вышеприведенное решение является просто общим решением для быстрого слияния кучи данных. Ваша конкретная проблема может быть более чистой (и быстро?) Решена с помощью перекрестного продукта (http://stackoverflow.com/questions/13269890/cartesian-product-in-pandas), но мне придется больше думать о как бы это произошло. – rhaskett

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"] 
+0

Спасибо за ваш вклад ... Я узнал пару трюков панды от вас. Тем не менее, я заинтересован в том, чтобы выяснить количество студентов, отсутствующих в каждый день, а не общее количество пропусков на одного учащегося. Есть ли разумный способ сделать это? – monkeybiz7

Смежные вопросы