2013-10-08 4 views
0

У меня есть набор данных временных рядов с 10 единицами оберегания. В каждый день каждая единица наблюдения может заниматься деятельностью в течение нескольких часов. Поэтому я (позволяет говорить) 4 переменных в DataFrame:Группировка и трансформация данных Pandas

Дата - дата Unit - единица наблюдения acitvity - некоторая активность CumHours - суммарное количество часов, затраченных на единицу на деятельности.

Мне нужно создать переменную «Hours_calc», в которой указано, сколько часов было потрачено на любую активность по каждой строке в каждый день. После импорта всех нормальным бит части я делаю это:

DF = (mydata, columns = ['Date', 'Unit', 'Activity', 'CumHours']) 
DF['Hours_calc'] = np.nan 
DFGrouped = DF.groupby(['Unit', 'Activity']) 

Я считаю, что мне нужна метод преобразования, и я думаю, что первый аргумент, переданные функции преобразования (как указано) является колонкой DF как ряд как с методом agg(). Это правильно?

Я написал следующую функцию, но, как вы увидите, я понятия не имею, для расчета я должен иметь в виду DF или DFGrouped, или что? В общем, как обращаться к строкам/столбцам внутри goruped данных? Кроме того, могу ли я попытаться вернуть серию такой же длины, как и группа groupby?

def WorkingHours(x, Column): 
    LISTHOURS = [] 
    for row in xrange(1, len(x)): 
     Tot = int(DFGrouped[Column][row]) - int(DFGrouped[Column][row - 1]) 
     LISTHOURS.append(Tot) 
    return pd.Series(LISTHOURS) 

TESTDF = DFGrouped.transform({Hours_calc : lambda x : WorkingHours(x, 'CumHours')}) 

Кроме того, я что-нибудь в документации о пропускании Dict, чтобы преобразовать не видя, но я не вижу какой-либо другой способ выполнения функции только с одной переменной/столбца в Gorup.

Куда я ошибаюсь? Сообщение об ошибке долго запутывает, но заканчивается на «Функция преобразования недопустима для типов данных».

+0

Я не уверен, правильно ли я понял вашу проблему, но разве вы не должны группировать по дате, подразделению, а не по Unit и Activity? Таким образом, вы можете просто использовать сумму CumHours для каждой группы, чтобы получить общее количество часов на все действия. – yemu

+0

Я так не думаю, мне нужно ежедневное количество часов, потраченных на любую деятельность. Так, например, представьте, что в период времени unit1 выполняет две активности, не обязательно в последовательные дни. CumHours измеряет совокупное время, потраченное этим подразделением на деятельность, проведенную в этот день. Чтобы найти ежедневные часы, мне нужно принять кумулятивные часы в определенный день и вычесть кумулятивные часы с последнего дня, когда эта деятельность была выполнена. Следовательно, группировка по единицам/активности и сортировка по дате., –

+3

, можете ли вы представить пример файла данных с некоторыми заполненными данными? – yemu

ответ

2

Я думаю, вы могли бы использовать функцию сдвига, чтобы сдвинуть столбец в сгруппированных данных на одну строку. Затем, если вы вычтите оригинал и сместили, вы получите сырое количество часов, потраченных на активность.

df = (mydata, columns = ['date', 'unit', 'activity', 'cumhours']) 
grouped = df.groupby(['unit', 'activity']) 
shift_it = lambda x: (x - x.shift()) 
raw_hours = grouped.cumhours.transform(shift_it) 
df.insert(0, 'raw_hours',raw_hours) 

EDIT 1. Если вы хотите, общая функция для перебора элементов серии с использованием преобразования, но без копирования в список, попробуйте следующее:

df = (mydata, columns = ['date', 'unit', 'activity', 'cumhours']) 
grouped = df.groupby(['unit', 'activity']) 
def trans_func(x): 
    y=x.copy() 
    for i in range(1,len(x.index)): 
     x.iloc[i]=y.iloc[i]-y.iloc[i-1] 
    return x 

raw_hours = gr['cumhours'].transform(lambda x: trans_func(x)) 
df.insert(0, 'raw_hours',raw_hours) 
+0

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

+0

для повторения строк, вы можете использовать функцию iloc, см. Выше – yemu

1

Я думаю, что я, наконец, решить эту проблему. Я подозреваю, что ответ yemu это хорошо, но я предпочитаю это, как это было упражнение в конце концов научиться применять свои собственные функции:

DF = (mydata, columns = ['Date', 'Unit', 'Activity', 'CumHours']) 
DF['Hours_calc'] = np.nan 
DFGrouped = DF.groupby(['Unit', 'Activity']) 

def WorkingHours(x): 
    CumHoursList = list(x) 
    HoursCalcList = [] 
    HoursCalcList.insert(0, CumHoursList[0]) 
    for index in xrange(1, len(CumHoursList)): 
     CalcHoursList/insert(index, CumHoursList[index] - CumHoursList[index - 1]) 
    return CalcHoursList 

DFGrouped['CumHours'].transform(lambda x: WorkingHours(x)) 

Работает шарм!

+0

Хотя я все еще думаю, что должен быть способ итерации через серию, которая передается как x без необходимости превращать ее в список. Но это решение работает для меня пока. –

+0

отредактировал мой ответ, чтобы включить более общее решение, не использующее список – yemu

+0

ЛЮБОВЬ, ЧТО решение. Спасибо –

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