Могут ли панды считать столбец с типом строки в объекте RollingGroupby? - PullRequest
0 голосов
/ 29 января 2019

По названию вопроса.Могут ли панды рассчитывать на строковый столбец в объекте RollingGroupby?

Вот мой фрейм данных:

# Let's say my objective is to count the number of unique cars 
# over the last 1 day grouped by park

 park |    date    | to_count
------------------------------
  A   | 2019-01-01 |   Honda
  A   | 2019-01-03 |   Lexus
  A   | 2019-01-05 |   BMW
  A   | 2019-01-05 |   Lexus
  B   | 2019-01-01 |   BMW
  B   | 2019-01-08 |   Lexus
  B   | 2019-01-08 |   Lexus
  B   | 2019-01-10 |   Ford

Вот что я хочу:

 park |    date    | unique_count
----------------------------------
  A   | 2019-01-01 |      1
  A   | 2019-01-03 |      1
  A   | 2019-01-05 |      2
  B   | 2019-01-01 |      1
  B   | 2019-01-08 |      1
  B   | 2019-01-10 |      1

# Bit of explanation:
# There are 2 type of cars coming to park A over last 1 day on 5th Jan so distinct count is 2.
# There are 2 cars of 1 type (Lexus) coming to park B over last 1 day on 8th Jan so distinct count is 1.

Вот что у меня естьпробовал:

import pandas as pd
import numpy as np

# initiate dataframe
df = pd.DataFrame({
    'park': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
    'date': ['2019-01-01', '2019-01-03', '2019-01-05', '2019-01-05',
             '2019-01-01', '2019-01-08', '2019-01-08', '2019-01-10'],
    'to_count': ['Honda', 'Lexus', 'BMW', 'Lexus', 'BMW', 'Lexus', 'Lexus', 'Ford']
})

# string to date
df['date'] = pd.to_datetime(df['date'])

# group. This is more intuitive to me but sadly this does not work.
unique_count = df.groupby('park').rolling('1d', on='date').to_count.nunique()

# factorize then group. This works (but why???)
df['factorized'] = pd.factorize(df.to_count)[0]
unique_count = df.groupby('park').rolling('1d', on='date').factorized.apply(lambda x: len(np.unique(x)) )

result = unique_count.reset_index().drop_duplicates(subset=['park', 'date'], keep='last')

Вот мое окружение:

  • Mac 10.12 High Sierra
  • python3.6
  • pandas 0.22.0

Чтобы подчеркнуть, мне нужна функция скользящего окна для работы.В этом примере окно оказывается 1 днем, но я бы хотел, чтобы оно работало в течение 3 дней, 7 дней, 2 часов, 5 секунд.

Ответы [ 2 ]

0 голосов
/ 30 января 2019

Мое решение не ужасно питонное, но, я думаю, оно выполнено.

По одному парку за раз я нарезал смещение кадра данных по дням (скорректируйте дни, чтобы получить сумму проката), а затем извлек значения автомобилей в список.

Работая с автомобилями в списке за каждый день, мы можем рассчитать общее количество уникальных автомобилей за день.

Результатом является список, который вы можете преобразовать в фрейм данных, если вам нужно.

import pandas as pd
import datetime

# initiate dataframe
df = pd.DataFrame({
    'park': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
    'date': ['2019-01-01', '2019-01-03', '2019-01-05', '2019-01-05',
             '2019-01-01', '2019-01-08', '2019-01-08', '2019-01-10'],
    'to_count': ['Honda', 'Lexus', 'BMW', 'Lexus', 'BMW', 'Lexus', 'Lexus', 'Ford']
})
# string to date
df['date'] = pd.to_datetime(df['date'])

result = []
for park in ['A', 'B']:
    # Do one park at a time
    df_park = df[df['park'] == park][['date','to_count']]
    df_park.set_index('date',inplace=True)
    # interate through the dataframe and put results to list.
    for i, v in df_park.iterrows(): 
        # THIS IS YOUR ROLLING VALUE IN DAYS
        days = 1
        # create the starting date
        b = i - datetime.timedelta(days=days)
        # create a list of cars during the period
        li = df_park.loc[b:i].values
        # reduce the list to unique cars
        unique_cars = len(np.unique(li))
        # append the results to the result list
        result.append((park, i.strftime('%B %d, %Y'), unique_cars))

# the final list has duplicates, so use set to drop the dups and re-sort for the result.
sorted(list(set(result)))

Результат выглядит так:

[('A', 'January 01, 2019', 1),
('A', 'January 03, 2019', 1),
('A', 'January 05, 2019', 2),
('B', 'January 01, 2019', 1),
('B', 'January 08, 2019', 1),
('B', 'January 10, 2019', 1)]
0 голосов
/ 29 января 2019

Попробуйте:
- сначала сгруппируйте фрейм данных по park и date
- агрегируйте to_count по количеству уникальных значений

df = pd.DataFrame({
    'park': ['A', 'A', 'A', 'A', 'B', 'B', 'B', 'B'],
    'date': ['2019-01-01', '2019-01-03', '2019-01-05', '2019-01-05',
             '2019-01-01', '2019-01-08', '2019-01-08', '2019-01-10'],
    'to_count': ['Honda', 'Lexus', 'BMW', 'Lexus', 'BMW', 'Lexus', 'Lexus', 'Ford']
})

agg_df = df.groupby(by=['park', 'date']).agg({'to_count': pd.Series.nunique}).reset_index()
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...