Суммирование строк в DataFrame Pandas, где количество суммируемых строк основано на значениях столбцов в другом DataFrame

У меня есть два Dataframe. Кадр данных1 (df1): Столбец B изначально пуст, и его необходимо заполнить, как показано ниже.

| A( in days) | B (sum) |
| ----------- | ------- |
| 7           |         |
| 14          |         |
| 18          |         |
| 25          |         |

df1 имеет два столбца: Столбец A в днях и еще один столбец B, который пуст и должен быть заполнен суммой строк из кадра данных 2. Количество суммируемых строк зависит от того, как дни переводятся в неделю в столбце B.

Датафрейм 2 (df2):

| week | C(weekly) |
| ---- | --------- |
| WK1  | 10        |
| WK2  | 5         |
| WK3  | 7         |
| WK4  | 4         |
| WK5  | 8         |

Dataframe 2 имеет два столбца: Этот фрейм данных имеет номера недель и неделю, которая представляет собой сумму недельных единиц.

Я хочу заполнить значения в столбце A кадра данных 1 на основе столбца d в ​​кадре данных 2, как показано ниже:

Для первой строки, когда A = 7 дней, просто используйте значения WK1 (поскольку 7 дней — это 1 неделя, поэтому просто WK1 из C из DF2), поэтому B = 10.

Для второй строки, когда A=14 дней (2 недели), мне нужна сумма WK1 и WK2 для C из DF2), поэтому B=10+5=15. Для третьей строки, когда A=18, мне нужна сумма WK1 и WK2 и 5/7(WK3) C из DF2), поэтому B=10+5+(4/7)*7=19. Для четвертой строки, когда A=25, мне нужна сумма WK1+Wk2+wk3+(4/7)*4, поэтому B=24,28 (3 недели плюс дробь -21 день + 4/7 значения недели 4).

df1 (Завершено):

| A( in days) | B(sum) | Methodology     |
| ----------- | ------- | --------------- |
| 7           | 10      | 10              |
| 14          | 15      | 10+5            |
| 18          | 19      | 10+5+(4/7)*7    |
| 25          | 24.28   | 10+5+7+(4/7)*4  |

Я новичок в Python и теперь знаю, как действовать. Пожалуйста помоги

Вы уверены в последних вычислениях? Разве это не должно быть 10+5+(4/7*7)+4?

mozway 02.07.2024 06:52

На самом деле я понял

mozway 02.07.2024 07:11
1
2
87
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

количество недель равно количеству строк (возможно, несколько дней отсутствуют)

IIUC, вы можете использовать операцию mod , чтобы исправить cumsum:

r = df1['A'].mod(7).to_numpy()
c = df2['C'].head(len(df1))
df1['B'] = c.cumsum().sub((7-r)/7*c.where(r>0), fill_value=0).to_numpy()

Выход:

    A          B
0   7  10.000000
1  14  15.000000
2  18  19.000000
3  25  24.285714

количество недель произвольное

Затем нам нужно использовать пользовательскую функцию

def cust_sum(n, ref):
    d, r = divmod(n, 7)
    return ref.head(d).sum() + (ref.iat[d]*r/7 if r else 0)

df1['B'] = df1['A'].apply(cust_sum, ref=df2['C'])

Пример:

    A          B
0   7  10.000000
1  14  15.000000
2  18  19.000000
3  29  27.142857

Спасибо за вашу помощь. Это работает. Однако я хотел использовать кадры данных разной длины (df2>df1). скажем, в df1 последняя строка равна 36 дням, тогда я хотел, чтобы B читалось 10+5+7+4+(1/7)*8=27,14. Где 8 — значение пятой недели из df2. Когда я использую приведенную выше логику и делаю последнюю строку в df1 36, я получаю сообщение: «Условный массив должен быть той же формы, что и я». Как это можно включить? Спасибо

One_more_time 03.07.2024 02:08

@One_more_time Понятно, но ты уверен, что имел в виду 36, а не 29? Для 36 это будет 5 недель + 1 день, но у df2 нет данных за 6-ю неделю. Я бы рассмотрел 10+5+7+4+8+(x/7*1), где x — значение W6.

mozway 03.07.2024 10:30

Я добавил подход, предполагая, что вы имели в виду 29

mozway 03.07.2024 10:37

Да, вы правильно это интерпретировали. Это работает. Большое вам спасибо за вашу помощь. Очень ценю. Единственный вопрос, который у меня возник, касается n в пользовательской функции. Это значение в n-й строке df1['A']?

One_more_time 04.07.2024 07:03

Да, вы поняли ;)

mozway 04.07.2024 07:05

Я использовал это и обнаружил, что мне нужно использовать ту же логику, но для совпадения значений между комбинацией двух дополнительных категориальных столбцов, присутствующих в df1 и df2 - например, если df1 будет иметь столбец X и столбец Y со значениями, например, "a" и «b» и df2 также имеют столбцы X и Y — тогда эта логика должна работать только для аналогичной комбинации столбцов (например, с «a» для столбца X и «b» для столбца Y в DF2) — Как это сделать заставить это работать? мне нужно создать для этого новый пост? Я мог бы это сделать, если бы это было необходимо. Я новичок во всем этом, поэтому не мог предвидеть эту необходимость. Пожалуйста, порекомендуйте.

One_more_time 05.07.2024 04:16

@One_more_time, пожалуйста, поймите, что вопрос не должен постоянно меняться (см. вопросы-хамелеоны ) и что мне делать, когда кто-то отвечает на мой вопрос. В данном случае все довольно просто: df1['out1'] = df1['X'].apply(cust_sum, ref=df2['X']) и df1['out2'] = df1['Y'].apply(cust_sum, ref=df2['Y']).

mozway 05.07.2024 06:56

Извините, если я не ясно выразился, но мне нужно использовать столбцы X и Y вместе, а не по отдельности. Я попробовал сделать следующее: df1a= df1.groupby(['X','Y']).agg({'A':mean}) и df2a=df2.groupby(['X','Y']) .agg({'C':среднее}). Поскольку это уникальные значения, я получаю те же значения, что и исходные, когда беру среднее значение. Затем используйте их согласно тому, что вы показали ранее: df1a['B'] = df1a['A'].apply(cust_sum, ref=df2a['C']). Затем я получаю сообщение об ошибке: «Невозможно выполнить позиционную индексацию в MultiIndex с помощью этих индексаторов [1.0] типа float. Пожалуйста, помогите.

One_more_time 06.07.2024 02:20

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

One_more_time 06.07.2024 13:19

К вашему сведению: я задал приведенный выше вопрос с требованием соответствия значений между комбинацией двух дополнительных категориальных столбцов в новом сообщении: stackoverflow.com/questions/78714936/…

One_more_time 06.07.2024 15:17

@One_more_time, спасибо, так гораздо понятнее, честно говоря, я бы не стал догадываться, чего вы хотите, без полного вопроса. Я ответил там.

mozway 06.07.2024 16:05

Другие вопросы по теме