/
naile1973
/
process-scoretables
Обзор
Документация
Войти
/
naile1973
/
process-scoretables
Код
Запросы
0
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
master
process.py
228 строк
9 KB
naile1973
добавлена запись результата в csv
03 июн 2026, 18:59
03 июн 2026, 18:59
0acad85
Код
Авторство
О чём код?
import csv def read_csv(filename: str) -> tuple[list[str], list[list]]: """ Читает данные из CSV-файла с заданным именем. В первой строке файла должны быть записаны заголовки столбцов. Первый столбец игнорируется. Второй, третий и последний столбцы сохраняются как строки. Остальные столбцы преобразуются в список чисел (если несколько через запятую) или как число. Args: filename: Путь к CSV-файлу. Returns: Кортеж из двух элементов: - list[str]: Названия столбцов (без первого). - list[list]: Список строк с преобразованными данными. Каждая строка — список значений в порядке заголовков (без первого столбца). """ with open(filename, 'r', encoding='utf-8', newline='') as file: reader = csv.DictReader(file) result_data = [] # Получаем названия столбцов и отфильтровываем первый headers = list(reader.fieldnames) filtered_headers = headers[1:] # игнорируем первый столбец total_columns = len(headers) for row in reader: row_values = [] values = list(row.values()) for i in range(1, total_columns): # пропускаем i == 0 (первый столбец) if i == 1 or i == 2 or i == total_columns - 1: # Второй, третий и последний — как строки row_values.append(values[i]) else: # Остальные — преобразование в число или список чисел try: numbers = [float(x) for x in values[i].split(',')] value = numbers[0] if len(numbers) == 1 else numbers except (ValueError, AttributeError): value = values[i] row_values.append(value) result_data.append(row_values) return filtered_headers, result_data def sort_datas(datas: list[list]) -> list[list]: """ Сортирует список datas по второму полю, а при равенстве вторых полей — по первому полю. Args: datas: Список строк, каждая — список значений. Returns: Отсортированный список. """ def sort_key(row): first = row[0] second = row[1] # Приводим к общему виду для сравнения: строки оставляем как есть, числа — как есть # (т.к. Python умеет сравнивать разные типы, если они не смешиваются, но у нас типы предсказуемы) # Для надёжности: если типы разные, приведём к строке — но лучше использовать явную логику return (second, first) return sorted(datas, key=sort_key) def del_1(datas: list[list]) -> list[list]: """ Удаляет первый элемент из каждой строки (первый столбец). Args: datas: Список строк (каждая строка — список значений). Returns: Список строк без первого элемента. """ return [row[1:] for row in datas] def del_2(columns: list[str]) -> list[str]: """ Удаляет первый элемент из списка названий столбцов. Args: columns: Список названий столбцов. Returns: Новый список без первого элемента. """ return columns[1:] def aggregate_datas(datas: list[list]) -> list[list]: """ Группирует записи по значению первого элемента, вычисляет среднее арифметическое числовых полей и конкатенирует последнее поле через '; '. Args: datas: Список строк, каждая — список значений. Returns: Список агрегированных строк, где: - aggregated[0] = значение первого поля исходной строки (row[0]), - aggregated[1..-2] = средние арифметические числовых полей (без учёта 0-го и последнего), - aggregated[-1] = конкатенированные значения последнего поля через '; '. """ if not datas: return [] result = [] groups = {} for row in datas: first_val = row[0] # группируем по первому элементу if first_val not in groups: groups[first_val] = [] groups[first_val].append(row) for first_val, group in groups.items(): num_cols = len(group[0]) # Агрегированная строка имеет ту же длину, что и исходная aggregated = [None] * num_cols # aggregated[0] = значение первого поля (ключ группировки) aggregated[0] = first_val # Последний элемент — конкатенация через '; ' last_idx = num_cols - 1 last_vals = [] for row in group: val = row[last_idx] if val is not None and str(val).strip(): last_vals.append(str(val)) aggregated[last_idx] = '; '.join(last_vals) if last_vals else '' # Собираем числовые значения для полей 1..(num_cols-2) all_values = [[] for _ in range(num_cols)] for row in group: # Пропускаем 0-й (строка) и последний (строка) for i in range(1, num_cols - 1): val = row[i] if isinstance(val, (int, float)): all_values[i].append(val) elif isinstance(val, list): all_values[i].append(val) # Вычисляем среднее для числовых полей (индексы от 1 до num_cols-2) for i in range(1, num_cols - 1): values_list = all_values[i] if not values_list: aggregated[i] = 0.0 continue if all(isinstance(v, (int, float)) for v in values_list): aggregated[i] = sum(values_list) / len(values_list) elif all(isinstance(v, list) for v in values_list): if not values_list[0]: aggregated[i] = [] else: length = len(values_list[0]) sums = [0.0] * length for val in values_list: for j, num in enumerate(val): if j < length: sums[j] += num avg = [s / len(values_list) for s in sums] aggregated[i] = avg[0] if len(avg) == 1 else avg else: aggregated[i] = values_list[0] result.append(aggregated) return result def format_value(val): if isinstance(val, float): return round(val, 1) elif isinstance(val, list): return [format_value(v) for v in val] else: return val def write_csv(filename: str, columns: list[str], datas: list[list]): """ Записывает данные в CSV-файл с заданными заголовками. Args: filename: Имя выходного CSV-файла. columns: Список названий столбцов (заголовков). datas: Список строк с данными. """ with open(filename, 'w', encoding='utf-8', newline='') as file: writer = csv.writer(file) writer.writerow(columns) # записываем заголовки for row in datas: writer.writerow(row) FILENAME = 'data.csv' columns, datas = read_csv(FILENAME) datas = sort_datas(datas) datas = del_1(datas) # <-- удаляем первый столбец из datas columns = del_2(columns) #print("Columns:", columns) #print("Data:") for row in datas: print(row) newdatas = aggregate_datas(datas) for row in newdatas: formatted_row = [format_value(v) for v in row] print(formatted_row) # Записываем результат в result.csv write_csv('result.csv', columns, newdatas)