Получение межквартильного диапазона и медианы от групп панд, заполнение нулями для всех не упомянутых дат - PullRequest
0 голосов
/ 25 мая 2018

У меня есть такой фрейм данных (за исключением моего очень большого):

user1      user2   day   hour  quantity
-------------------------------------
Alice      Bob      1     12     250
Alice      Bob      1     13     250
Bob        Carol    1     10     20
Alice      Bob      4     1      600
.
.
.

... тогда предположим, что я получаю следующие данные группирования и агрегации (по user1, user2 и day):

user1      user2   day   quantity
---------------------
Alice      Bob      1      500
                    4      600
Bob        Carol    1      20
                    3      100

, где день должен идти с 0-364 (365 дней).То, что я хочу, это межквартильный диапазон (и медиана) отсчетов для каждого пользователя за все дни - за исключением того, что нули не подсчитываются .

Жизнь была бы проще, если бы у меня был явныйнули для всех исключенных дней:

user1    user2    day   quantity
---------------------
Alice    Bob      1      500
                  2      0
                  3      0
                  4      600
.....
Bob      Carol    1      20
                  2      0
                  3      100
...

... потому что тогда я мог бы сделать df.reset_index().agg({'quantity':scipy.stats.iqr}), но я работаю с очень большим фреймом данных (пример выше - фиктивный), и переиндексировать с нулямипросто невозможно.

У меня есть идея, как это сделать: так как я знаю, что есть 365 дней, тогда я должен просто дополнить оставшиеся числа нулями:

Alice-Bob: [500,600] + (365-2) * [0]

и получите scipy.stats.iqr (и медиану) этого.Однако это будет включать в себя итерацию по всем user1-user2 парам.По опыту, это занимает много времени.

Есть ли какое-нибудь векторизованное решение для этого?Я также должен получить медиану, и я думаю, что тот же подход должен иметь место.

1 Ответ

0 голосов
/ 25 мая 2018

Чтобы использовать нули, не помещая их в кадр данных, вы можете использовать что-то вроде этого:

test = df.groupby(['user1', 'user2', 'day'])['quantity'].mean().reset_index()\
         .groupby(['user1', 'user2'])\
         .agg({'day': lambda x: tuple(x), 'quantity': lambda x: tuple(x)})\
         .reset_index()

def med_from_tuple(row):
    # starts with everything zero, and replaces some with the nonzero values in the dataframe
    z = np.zeros(365)
    np.put(z, row['day'], row['quantity'])
    return np.median(z)

test['example'] = test.apply(lambda x: med_from_tuple(x), axis=1)

Это создаст медиану количества, как если бы в кадре данных были нули.

test
#   user1  user2     day    quantity   example
#0  Alice    Bob  (1, 4)  (250, 600)       0.0
#1    Bob  Carol    (1,)       (20,)       0.0
...