python - сумма GroupBy как доля в диапазоне дат начала и окончания - PullRequest
0 голосов
/ 08 января 2019

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

Обычно я мог бы сделать это, если результат был связан с определенной датой, но, поскольку это долгосрочная аренда, мне нужно выяснить, какая часть результата относится к каждому месяцу между датами начала и окончания.

+------+------------------+------------------+--------+
| Drone|     Start        |      End         | Result |
+------+------------------+------------------+--------+
| DR1    16/06/2013 10:30   22/08/2013 07:00    2786  |
| DR1    20/04/2013 23:30   16/06/2013 10:30    7126  |
| DR1    24/01/2013 23:00   20/04/2013 23:30    2964  |
| DR2    01/03/2014 19:00   07/05/2014 18:00    8884  |
| DR2    04/09/2015 09:00   04/11/2015 07:00    7828  |
| DR2    04/10/2013 05:00   24/12/2013 07:00    5700  |
+-----------------------------------------------------+

Мне удалось найти разницу в датах, используя это:

import datetime
from dateutil.relativedelta import relativedelta
df.Start = pd.to_datetime(df.Start)
df.End = pd.to_datetime(df.End)
a = df.loc[0, 'Start']
b = df.loc[0, 'End']
relativedelta(a,b)

Однако вывод распечатывается так:

относительная дельта (месяцы = -2, дни = -5, часы = -20, минуты = -30)

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

df.groupby(['Device', 'Date']).agg(sum)['Result']

Буду признателен за помощь в правильном мыслительном процессе для решения такой проблемы и как будет выглядеть код.

взяв первый пример для каждого типа дрона, мой ожидаемый результат будет:

+------+-------+-------+---------+
|Drone | Month | Days  |  Result |
+------+-------+-------+---------+
|DR1     June      X       $YY   |
|DR1     July      X       $YY   |
|DR1     August    X       $YY   |
|DR2     March     Y       $ZZ   |
|DR2     April     Y       $ZZ   |
|DR2     May       Y       $ZZ   |
+--------------------------------+

Спасибо

1 Ответ

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

Это зацикленное решение, но я думаю, что оно делает то, что вы хотите.

# Just load the sample data
from io import StringIO
data = 'Drone,Start,End,Result\n' + \
    'DR1,16/06/2013 10:30,22/08/2013 07:00,2786\n' + \
    'DR1,20/04/2013 23:30,16/06/2013 10:30,7126\n' + \
    'DR1,24/01/2013 23:00,20/04/2013 23:30,2964\n' + \
    'DR2,01/03/2014 19:00,07/05/2014 18:00,8884\n' + \
    'DR2,04/09/2015 09:00,04/11/2015 07:00,7828\n' + \
    'DR2,04/10/2013 05:00,24/12/2013 07:00,5700\n'
stream = StringIO(data)

# Actual solution
import pandas as pd
from datetime import datetime

df = pd.read_csv(stream, sep=',', parse_dates=[1, 2])

def get_month_spans(row):
    month_spans = []
    start = row['Start']
    total_delta = (row['End'] - row['Start']).total_seconds()
    while row['End'] > start:
        if start.month != 12:
            end = datetime(year=start.year, month=start.month+1, day=1)
        else:
            end = datetime(year=start.year+1, month=1, day=1)
        if end > row['End']:
            end = row['End']
        delta = (end - start).total_seconds()
        proportional = row['Result'] * (delta / total_delta)
        month_spans.append({'Drone': row['Drone'],
                            'Month': datetime(year=start.year,
                                              month=start.month,
                                              day=1),
                            'Result': proportional,
                            'Days': delta / (24 * 3600)})
        start = end
        print(delta)
    return month_spans

month_spans = []
for index, row in df.iterrows():
    month_spans += get_month_spans(row)
monthly = pd.DataFrame(month_spans).groupby(['Drone', 'Month']).agg(sum)[['Result', 'Days']]

print(monthly)

Что выводит, сколько каждый дрон зарабатывал каждый месяц вместе с количеством дней:

                       Result       Days
Drone Month                             
DR1   2013-01-01   242.633083   7.041667
      2013-02-01   964.789537  28.000000
      2013-03-01  1068.159845  31.000000
      2013-04-01  1953.216797  30.000000
      2013-05-01  3912.726199  31.000000
      2013-06-01  2555.334620  30.000000
      2013-07-01  1291.856653  31.000000
      2013-08-01   887.283266  21.291667
DR2   2013-04-01   459.202454  20.791667
      2013-05-01   684.662577  31.000000
      2013-06-01   662.576687  30.000000
      2013-07-01   684.662577  31.000000
      2013-08-01   684.662577  31.000000
      2013-09-01   662.576687  30.000000
      2013-10-01   684.662577  31.000000
      2013-11-01   662.576687  30.000000
      2013-12-01   514.417178  23.291667
      2014-01-01  1369.726258  28.208333
      2014-02-01  1359.610112  28.000000
      2014-03-01  1505.282624  31.000000
      2014-04-01  1456.725120  30.000000
      2014-05-01  1505.282624  31.000000
      2014-06-01  1456.725120  30.000000
      2014-07-01   230.648144   4.750000
      2015-04-01  7828.000000   1.916667
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...