Сумма Python с условием, используя дату и условие - PullRequest
1 голос
/ 13 марта 2019

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

Я хочу добавить второй столбец в df2, который показывает дату, чтобы узнать день, когда сумма столбца AVG большечем 100 после даты 2 в df2.

Например, df1 и df2 - это тот кадр данных, с которого я начинаю, и df3 - то, что я хочу, и df3 ['date100'] - это день, когда сумма avg больше 100:

df1 = pd.DataFrame({'date1': ['1/1/2014', '2/1/2014', '3/1/2014','1/1/2014', '2/1/2014', '3/1/2014','1/1/2014', '2/1/2014', '3/1/2014'],
 'Place':['A','A','A','B','B','B','C','C','C'],'AVG': [62,14,47,25,74,60,78,27,41]})

df2 = pd.DataFrame({'date2': ['1/1/2014', '2/1/2014'], 'Place':['A','C'])})

*Something*
df3 = pd.DataFrame({'date2': ['1/1/2014', '2/1/2014'], 'Place':['A','C'], 'date100': ['3/1/2014', '2/1/2014'], 'sum': [123, 105]})

Я нашел несколько ответов, но большинство из них использует groupby, а df2 не имеет групп.

Ответы [ 2 ]

0 голосов
/ 13 марта 2019

Вот прямое решение со следующими допущениями:

  • df1 отсортировано по дате
  • одно решение существует для каждой даты в df2

Затем вы можете сделать:

df2 = df2.join(pd.concat([
        pd.DataFrame(pd.DataFrame(df1.loc[df1.date1 >= d].AVG.cumsum()).query('AVG>=100')
                .iloc[0]).transpose()
        for d in df2.date2]).rename_axis('ix').reset_index())\
    .join(df1.drop(columns='AVG'), on='ix').rename(columns={'AVG': 'sum', 'date1': 'date100'})\
    .drop(columns='ix')[['date2', 'date100', 'sum']]

Это сделает следующее:

  • для каждой даты в df2 найти первую дату, когда накопитель в AVG будетпо крайней мере 100
  • объединяет результаты в одном отдельном фрейме данных, индексированном по индексу этой строки в df1
  • , сохраняет этот индекс в столбце ix и сбрасывает индекс для присоединения к этому фрейму данныхк df2
  • присоедините его к df1 минус столбец AVG, используя столбец ix
  • , переименуйте столбцы, удалите столбец ix и переупорядочьте все
0 голосов
/ 13 марта 2019

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

Решение:

#   For this solution your DataFrame needs to be sorted by date.
limit = 100
df = pd.DataFrame({
    'date1': ['1/1/2014', '2/1/2014', '3/1/2014','1/1/2014',
              '2/1/2014', '3/1/2014','1/1/2014', '2/1/2014', '3/1/2014'], 
    'Place':['A','A','A','B','B','B','C','C','C'],
    'AVG': [62,14,47,25,74,60,78,27,41]})

df2 = pd.DataFrame({'date2': ['1/1/2014', '2/1/2014'], 'Place':['A','C']})

result = []
for row in df2.to_dict('records'):
    #   For each date, I want to select the date that comes AFTER this one.
    #   Then, I take the .cumsum(), because it's the agg you wish to do.
    #   Filter by your limit and take the first occurrence.
    #   Converting this to a dict, appending it to a list, makes it easy
    #   to rebuild a DataFrame later.
    ndf = df.loc[ (df['date1'] >= row['date2']) & (df['Place'] == row['Place']) ]\
            .sort_values(by='date1')
    ndf['avgsum'] = ndf['AVG'].cumsum()
    final_df = ndf.loc[ ndf['avgsum'] >= limit ]

    #   Error handling, in case there is not avgsum above the threshold.
    try:
        final_df = final_df.iloc[0][['date1', 'avgsum']].rename({'date1' : 'date100'})
        result.append( final_df.to_dict() )
    except IndexError:
        continue

df3 = pd.DataFrame(result)

final_df = pd.concat([df2, df3], axis=1, sort=False)
print(final_df)
#       date2 Place  avgsum   date100
# 0  1/1/2014     A   123.0  3/1/2014
# 1  2/1/2014     C     NaN       NaN
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...