- Первый Функция пытается получить среднее значение строк с совпадающими значениями в кластере, группе и дате.
- Вторая функция снова анализирует ее, на этот раз группируя по кластеру, группе и периоду.
- Третья функция вместо этого использует построчный подход в отношении кода города и группы, при этом всякий раз, когда в «Значениях» обнаруживается нулевое значение, скрипт ищет первое ненулевое значение в этой группе перед ним и первая ненулевая функция после нее, также по дате, принимает среднее значение из двух.
Исходный
Дата
Значение
45443
10
45444
0
45445
0
45446
15
Первый анализ
Дата
Значение
45443
10
45444
12,5
45445
0
45446
15
Второй анализ
Дата
Значение
45443
10
45444
12,5
45445
13,75
45446
15< /td>
Однако, хотя исходные функции, кажется, выполняют свою задачу, третья, похоже, ничего не исправляет при каждом анализе, как следует из журнала.
Стоит отметить: первые две функции должны выполняться только один раз, в то время как третья функция должна выполнять цикл до тех пор, пока все не будет «очищено».
Я прикрепил рассматриваемый код здесь:
# Hypothetical DataFrame
import pandas as pd
import numpy as np
# Create the data
np.random.seed(0) # For reproducibility
area_code = ['AA'] * 10
start_date = pd.to_datetime('2023-01-01')
dates = [(start_date + pd.Timedelta(days=i)).strftime('%Y-%m-%d') for i in range(10)]
period_name = ['1'] * 5 + ['2'] * 5
group = np.tile(np.arange(1, 6), 2)
cluster = ['1'] * 5 + ['2'] * 5
value = np.random.randint(100, 300, size=10)
# Create DataFrame
df = pd.DataFrame({
'Area_Code': area_code,
'Date': dates,
'PERIOD_NAME': period_name,
'Group': group,
'CLUSTER': cluster,
'Value': value
})
# Convert Date to general format
df['Date'] = pd.to_datetime(df['Date']).apply(lambda x: x.toordinal())
df
# Function to replace zero values based on the specified criteria
def replace_zeros(df):
logging.info("Starting to replace zeros based on initial criteria.")
zeros_fixed = 0
# Iterate over each row in the dataframe
for index, row in df.iterrows():
if row['Value'] == 0:
# First grouping: CLUSTER, Group, and Date
group1 = df[(df['CLUSTER'] == row['CLUSTER']) &
(df['Group'] == row['Group']) &
(df['Date'] == row['Date']) &
(df['Value'] != 0)]
if not group1.empty:
df.at[index, 'Value'] = group1['Value'].mean()
zeros_fixed += 1
else:
# Second grouping: CLUSTER, Group, and PERIOD_NAME
group2 = df[(df['CLUSTER'] == row['CLUSTER']) &
(df['Group'] == row['Group']) &
(df['PERIOD_NAME'] == row['PERIOD_NAME']) &
(df['Value'] != 0)]
if not group2.empty:
df.at[index, 'Value'] = group2['Value'].mean()
zeros_fixed += 1
logging.info(f"Completed initial zero replacement. Fixed {zeros_fixed} zeros.")
return df, zeros_fixed
# Function to replace zero values by looking at the date above and the date below
def replace_zeros_with_neighbors(df):
logging.info("Starting to replace remaining zeros by looking at neighbors.")
zeros_fixed = 0
for index, row in df.iterrows():
if row['Value'] == 0:
area_code = row['Area_Code']
group = row['Group']
date = row['Date']
# Get the previous row with the same Area_Code and Group and non-zero Value
prev_row = df[(df['Area_Code'] == area_code) &
(df['Group'] == group) &
(df['Date'] < date) &
(df['Value'] != 0)].sort_values(by='Date').tail(1)
# Get the next row with the same Area_Code and Group and non-zero Value
next_row = df[(df['Area_Code'] == area_code) &
(df['Group'] == group) &
(df['Date'] > date) &
(df['Value'] != 0)].sort_values(by='Date').head(1)
logging.debug(f"Index {index}: prev_row: {prev_row}, next_row: {next_row}")
if not prev_row.empty and not next_row.empty:
avg_value = (prev_row['Value'].values[0] + next_row['Value'].values[0]) / 2
df.at[index, 'Value'] = avg_value
zeros_fixed += 1
logging.debug(f"Replaced zero at index {index} with average of {prev_row['Value'].values[0]} and {next_row['Value'].values[0]}")
elif not prev_row.empty:
df.at[index, 'Value'] = prev_row['Value'].values[0]
zeros_fixed += 1
logging.debug(f"Replaced zero at index {index} with previous value {prev_row['Value'].values[0]}")
elif not next_row.empty:
df.at[index, 'Value'] = next_row['Value'].values[0]
zeros_fixed += 1
logging.debug(f"Replaced zero at index {index} with next value {next_row['Value'].values[0]}")
logging.info(f"Completed neighbor-based zero replacement. Fixed {zeros_fixed} zeros.")
return df, zeros_fixed
# Function to iteratively replace zero values until there are no zeros left
def iterative_replace_zeros(df):
logging.info("Starting iterative zero replacement.")
df, zeros_fixed = replace_zeros(df)
total_zeros_fixed = zeros_fixed
remaining_zeros = (df['Value'] == 0).sum()
logging.info(f"Initial pass: Fixed {zeros_fixed} zeros. {remaining_zeros} zeros remaining.")
while remaining_zeros > 0:
df, zeros_fixed = replace_zeros_with_neighbors(df)
total_zeros_fixed += zeros_fixed
remaining_zeros = (df['Value'] == 0).sum()
logging.info(f"Fixed {zeros_fixed} zeros in this loop. {remaining_zeros} zeros remaining.")
logging.info(f"Completed iterative zero replacement. Total zeros fixed: {total_zeros_fixed}.")
return df
Подробнее здесь: https://stackoverflow.com/questions/789 ... -satisfied