Итеративный цикл для замены значений внутри кадра данных до тех пор, пока критерии не будут удовлетворены – работает непPython

Программы на Python
Anonymous
Итеративный цикл для замены значений внутри кадра данных до тех пор, пока критерии не будут удовлетворены – работает неп

Сообщение Anonymous »

Я пытаюсь написать скрипт Python, который пытается заменить нулевые значения в файле csv, анализируя его с помощью набора правил:
  • Первый Функция пытается получить среднее значение строк с совпадающими значениями в кластере, группе и дате.
  • Вторая функция снова анализирует ее, на этот раз группируя по кластеру, группе и периоду.
  • Третья функция вместо этого использует построчный подход в отношении кода города и группы, при этом всякий раз, когда в «Значениях» обнаруживается нулевое значение, скрипт ищет первое ненулевое значение в этой группе перед ним и первая ненулевая функция после нее, также по дате, принимает среднее значение из двух.
В идеале третья функция должна делать что-то вроде этого:
Исходный


Дата
Значение




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

Вернуться в «Python»