Pandas перебрать строки в 2х DataFrame и изменить 2 колонки
У меня есть 2 DataFrame: 1. продукты, 2. остатки по дням Я пытаюсь:
- перебрать продукты по колонке "Artical" из "prod_df" в "sales_df"
- для каждого найденного продукта изменить количество "Start_of_Day" и "End_of_Day"
- если дата меньше "report_start" минус 1 день, то "Start_of_Day" и "End_of_Day" равны "Qty"
- если нет, то "Start_of_Day" равна "End_of_Day" предыдущего дня, а "End_of_Day" равна "Qty"
В результате я хочу получить DataFrame, как на картинке. Но получаю DataFrame, в котором "Start_of_Day" и "End_of_Day" равны 0
Как заменить значения?
Вот то, что я пробовала:
mport pandas as pd
from datetime import timedelta
report_start = '01.06.2024'
report_start = pd.to_datetime(report_start, format='%d.%m.%Y',errors='coerce')
report_end = '04.06.2024'
report_end = pd.to_datetime(report_end, format='%d.%m.%Y',errors='coerce')
prod_df = pd.DataFrame({
'Artical': ['111', '222', '333', '444'],
'Name': ['name1', 'name2', 'name3', 'name4'],
})
sales_df = pd.DataFrame({
'Artical': ['111', '111', '111', '111', '111', '222', '222', '222', '222', '222'],
'Date': ['31.05.2024', '01.06.2024', '02.06.2024', '03.06.2024', '04.06.2024', '31.05.2024', '01.06.2024', '02.06.2024', '03.06.2024', '04.06.2024'],
'Qty': ['2172', '2172', '2172', '2128', '2128', '0', '2068', '2068', '2056', '2056']
})
frames = []
for i in prod_df['Artical']:
data = sales_df[(sales_df['Artical'] == str(i))].reset_index(drop=True)
data['Start_of_Day'] = 0
data['End_of_Day'] = 0
if data.empty == False:
for index, row in data.iterrows():
if row['Date'] == (report_start - timedelta(days=1)):
row['Start_of_Day'] = row['Qty']
row['End_of_Day'] = row['Qty']
# row['qtyStart_of_Day'] = row['qtyStart_of_Day'].replace(0, row['Qty'])
print(row)
else:
new_qty = data[(data['Date'] == (report_start - timedelta(days=1)))].reset_index(drop=True)
row['Start_of_Day'] = new_qty['End_of_Day']
row['End_of_Day'] = row['Qty']
frames.append(data)
final_df = pd.concat(frames, axis=0, ignore_index=True)
print(final_df)
Ответы (1 шт):
Автор решения: CrazyElf
→ Ссылка
Ну вот вам пример "векторного" подхода с комментариями
# преобразование строк в даты
report_start = pd.to_datetime(report_start, dayfirst=True)
sales_df['Date'] = pd.to_datetime(sales_df['Date'], dayfirst=True)
# сортируем, чтобы артикулы и даты были упорядочены
sales_df = sales_df.sort_values(['Artical', 'Date'])
# End_of_Day одинаковый при всех условиях
sales_df['End_of_Day'] = sales_df['Qty']
# строки, где начинается новый артикл
article_change = (sales_df['Artical'] != sales_df.shift()['Artical'])
# маска, по которой будем по-разному заполнять данные
old_mask = ((sales_df['Date'] - report_start).dt.days <= -1) | article_change
# фильтр по маске
sales_df.loc[old_mask, 'Start_of_Day'] = sales_df['Qty']
# фильтр по отрицанию маски
sales_df.loc[~old_mask, 'Start_of_Day'] = sales_df.shift()['End_of_Day']
# колонки переставляем в нужном порядке
sales_df = sales_df[['Artical', 'Date', 'Qty', 'Start_of_Day', 'End_of_Day']]