Last active
February 18, 2025 07:15
-
-
Save Ruthenus/94e11461558466a374f8f63e655b3fb5 to your computer and use it in GitHub Desktop.
Week 9 Homework in IT STEP Academy (file tasks)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import pandas | |
import json | |
import math | |
def load_and_display_csv(filepath): | |
""" | |
Пробує завантажити файл 28,5 ГБ зі значеннями, розділеними комами (csv), | |
за вказаним шляхом filepath. Виводить індекси та назви колонок. | |
Перехоплює перші можливі помилки. Допоміжна функція для визначення | |
напрямку подальшого програмування та задля випробування ЕОМ. | |
""" | |
try: | |
# Нібито перший рядок містить назви колонок! | |
# https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html | |
df = pandas.read_csv(filepath, encoding='utf-8', nrows=1_000_000) | |
# Виводимо індекси та назви колонок: | |
# https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.columns.html | |
for index, column_header in enumerate(df.columns): | |
print(index, column_header) | |
except FileNotFoundError: | |
print(f"ERROR: файл CSV за вказаним шляхом відсутній.") | |
except pandas.errors.ParserError: | |
# https://pandas.pydata.org/docs/reference/api/pandas.errors.ParserError.html | |
print(f"ERROR: не вдалося обробити файл. Перевірте його формат!") | |
except pandas.errors.EmptyDataError: | |
# https://pandas.pydata.org/docs/reference/api/pandas.errors.EmptyDataError.html | |
print(f"ERROR: зустрічаються порожні дані або заголовок.") | |
except Exception as e: | |
# Загальна обробка інших НЕПЕРЕДБАЧЕНИХ помилок | |
print(f"Сталася непередбачувана помилка: {e}") | |
# РЕЗУЛЬТАТ ТЕСТУВАННЯ ФУНКЦІЇ load_and_display_csv(filepath) | |
""" | |
0 Captured Time | |
1 Latitude | |
2 Longitude | |
3 Value | |
4 Unit | |
5 Location Name | |
6 Device ID | |
7 MD5Sum | |
8 Height | |
9 Surface | |
10 Radiation | |
11 Uploaded Time | |
12 Loader ID | |
""" | |
# Встановлюємо тип даних для стовпців, де виявлено змішані типи: | |
dtype = { | |
5: str, | |
9: str, | |
10: str, | |
} | |
try: | |
# Друга спроба завантажити файл ПОВНІСТЮ | |
df = pandas.read_csv(filepath, encoding='utf-8', dtype=dtype, | |
low_memory=False) | |
print("Файл завантажено з обробленими типами даних.") | |
except Exception as e: # спіймав без nrows=1_000_000 | |
print(f"FATAL ERROR: не вдалося завантажити файл: {e}") | |
# Визначення справжньої кількості рядків у DataFrame | |
print(f"Загальна кількість рядків: {len(df)}") # 244 мільйони! | |
def process_coordinates(filepath, chunk_size=1_000_000): | |
""" | |
Функція для обробки великого CSV файлу замірів радіаційного фону | |
та отримання унікальних координат з точністю до 1 знака після коми. | |
Помилки перехопила попередня функція load_and_display_csv(filepath) | |
:param filepath: шлях до CSV файлу | |
:param chunk_size: розмір частини, яку обробляємо за раз | |
:return: список координат у вигляді кортежів (широта, довгота) | |
""" | |
# Встановлюємо тип даних для стовпців, де виявлено змішані типи: | |
dtype = { | |
5: str, | |
9: str, | |
10: str, | |
} # Такі добрі інструкції в pandas! | |
# Застосуємо множину Set для автоматичного видалення дублікатів | |
coord_tuples = set() | |
try: # https://pandas.pydata.org/docs/user_guide/scale.html | |
for chunk in pandas.read_csv(filepath, header=0, chunksize=chunk_size, | |
dtype=dtype, low_memory=False): | |
# https://stackoverflow.com/questions/24251219/pandas-read-csv-low-memory-and-dtype-options | |
# Округлюємо координати до одного знака після коми: | |
chunk['Latitude'] = chunk['Latitude'].round(1) | |
chunk['Longitude'] = chunk['Longitude'].round(1) | |
# Не округлюючи отримуємо 5,9 ГБ! | |
# Множина кортежів (широта, довгота) для поточного шматка: | |
unique_chunk = set(zip(chunk['Latitude'], chunk['Longitude'])) | |
# https://docs.python.org/3.3/library/functions.html#zip | |
# Додаємо нові унікальні пари координат до загальної множини | |
coord_tuples.update(unique_chunk) # 858250 рядків, 9,14 МБ | |
# Повертаємо список списків з множини кортежів: | |
return list(coord_tuples) | |
except Exception as e: | |
print(f"Знову (НЕ) сталася помилка з цим завеликим файлом: {e}") | |
def save_to_json(data, output_file): | |
""" | |
Функція для збереження даних обробленого CSV файлу в JSON файл. | |
:param data: дані, які потрібно зберегти | |
:param output_file: шлях до файлу для збереження | |
""" | |
try: | |
with open(output_file, 'w', encoding='utf-8') as f: | |
json.dump(data, f, indent=4) | |
except IOError: | |
print(f"ERROR: не вдалося відкрити файл '{output_file}' для запису.") | |
except Exception as e: | |
print(f"Помилка під час збереження даних у файл: {e}") | |
def remove_nan_from_json(input_file, output_file): | |
""" | |
Помітив, що JSON файл містить нечислові значення. Функція для | |
очищення JSON файлу від елементів, які містять NaN значення. | |
:param input_file: шлях до вхідного JSON файлу | |
:param output_file: шлях до вихідного очищеного JSON файлу | |
""" | |
try: | |
with open(input_file, 'r', encoding='utf-8') as f: | |
data = json.load(f) | |
# Функція для перевірки, чи є в списку "Not a number" | |
def is_valid_coordinates(coord): | |
return all(not math.isnan(x) for x in coord) | |
# Фільтруємо дані: залишаємо тільки валідні координати | |
filtered_data = [coord for coord in data if | |
is_valid_coordinates(coord)] | |
# Зберігаємо очищені дані в новий файл | |
with open(output_file, 'w', encoding='utf-8') as f: | |
json.dump(filtered_data, f, indent=4) | |
print(f"Дані успішно очищено та збережено у файл '{output_file}'.") | |
except FileNotFoundError: | |
print(f"ERROR: файл JSON за вказаним шляхом відсутній.") | |
except json.JSONDecodeError: | |
print(f"ERROR: не вдалося прочитати JSON файл '{input_file}'.") | |
except Exception as e: | |
print(f"Сталася непередбачувана помилка: {e}") | |
# Спільний виклик функцій | |
filepath = "D:/PYTHON/@radiazioni_ionizzanti_bot/data/measurements-out.csv" | |
output_file = "D:/PYTHON/@radiazioni_ionizzanti_bot/data/coordinates.json" | |
if __name__ == '__main__': | |
# load_and_display_csv(filepath) | |
unique_coords = process_coordinates(filepath) | |
save_to_json(unique_coords, output_file) | |
remove_nan_from_json(output_file, output_file) | |
print(f"Результат дивіться у файлі: {output_file}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment