Введение
Москва - это один из самых быстроразвивающихся городов России, который к тому же может похвастаться богатой историей. На протяжении своего существования в Москве происходило огромное количество различных исторических событий, оставивших за собой след, который изучается историками и археологами по сей день. В условиях активной реконструкции городского пространства Москвы археологические исследования становятся важным источником данных о прошлом столицы. В ходе земляных работ на улицах города регулярно обнаруживаются артефакты различных исторических периодов, требующие систематизации и анализа.
В рамках проекта мне было интересно изучить информацию об исторических артефактах, обнаруженных на территории столицы за несколько последних лет, так как подобные находки являются частью исторического и культурного наследия моего родного города.

Цветовое оформление

Типы графиков
Столбчатая диаграмма Линейная диаграмма Круговая диаграмма Гистограмма
Начало работы
При работе с датой я использовала Google Colab. Я добавила строку «df.info()», чтобы понять, сколько строк в таблице, сколько столбцов, как называются столбцы и что лежит в каждом столбце — текст, числа или даты. Также я перевела строку DateOfDiscovery из типа object (текст) в формат даты и выделила год.
df["DateOfDiscovery"] = pd.to_datetime(df["DateOfDiscovery"], errors="coerce") df["Year"] = df["DateOfDiscovery"].dt.year
df[["DateOfDiscovery", "Year"]].head()
После выявления нескольких колонок с данными я приступила к созданию графиков, подходящих для визуализации полученной информации.
СТОЛБЧАТАЯ ДИАГРАММА: каково было предназначение находки: предмет быта, монеты, часть декора и т. д.
График визуализирует данные о том, как мог использоваться предмет, найденный в ходе археологических работ, какую функцию он в себе нёс.
Для данной диаграммы я сначала создала функцию классификации:
def classify_finding(text): text = str(text).lower()
if any(word in text for word in ["монет", "деньг", "копейк", "рубл"]):
return "Монеты"
elif any(word in text for word in ["посуда", "горш", "чаш", "бутыл", "сосуд"]):
return "Предметы быта"
elif any(word in text for word in ["декор", "лепнин", "орнамент", "фрагмент"]):
return "Элементы декора"
elif any(word in text for word in ["оруж", "наконечник", "меч"]):
return "Оружие"
else:
return "Прочее"
После этого я создала новую колонку «Тип находки».
df["FindingType"] = df["DescriptionOfFinding"].apply(classify_finding)
df["FindingType"].value_counts()
Создав новую колонку, я смогла приступить к составлению графика:
type_counts = df["FindingType"].value_counts()
plt.figure(figsize=(9,5)) type_counts.plot(kind="bar")
plt.title("Распределение находок по типам") plt.xlabel("Тип находки") plt.ylabel("Количество") plt.xticks(rotation=30, ha="right") plt.tight_layout() plt.show()
КРУГОВАЯ ДИАГРАММА: на каком расстоянии от центра Москвы были найдены артефакты
При построении графика я решила использовать информацию о месте и координатах нахождения артефактов, так как во взятом датасете присутствовали данные о названии улиц, во время реконструкции которых находили тот или иной предмет.
Сначала я выполнила импорт и проверку колонки:
import pandas as pd import matplotlib.pyplot as plt import math import re
df["geodata_center"].head(5)
Потом извлекла координаты из geodata_center:
def parse_two_numbers(x): if pd.isna(x): return (None, None) s = str(x) nums = re.findall(r"-?\d+.\d+", s) # ищем числа вида 37.62 и 55.75 if len(nums) < 2: return (None, None)
a = float(nums[0])
b = float(nums[1])
# Москва: широта ~55, долгота ~37
# если первое похоже на долготу, а второе на широту -> (lat=b, lon=a)
if 30 <= a <= 45 and 50 <= b <= 60:
lon, lat = a, b
# если наоборот
elif 50 <= a <= 60 and 30 <= b <= 45:
lat, lon = a, b
else:
# если не уверены — оставим как есть (потом проверим)
lon, lat = a, b
return (lat, lon)
df[["Lat", "Lon"]] = df["geodata_center"].apply(lambda x: pd.Series(parse_two_numbers(x))) df[["geodata_center", "Lat", "Lon"]].head(10)
Считываю расстояние от центра Москвы:
CENTER_LAT = 55.7522 CENTER_LON = 37.6156
def haversine_km(lat1, lon1, lat2, lon2): R = 6371.0 phi1, phi2 = math.radians(lat1), math.radians(lat2) dphi = math.radians(lat2 - lat1) dlambda = math.radians(lon2 - lon1) a = math.sin(dphi/2)2 + math.cos(phi1)*math.cos(phi2)*math.sin(dlambda/2)2 return 2 * R * math.atan2(math.sqrt(a), math.sqrt(1 - a))
df["Dist_km"] = df.apply( lambda r: haversine_km(r["Lat"], r["Lon"], CENTER_LAT, CENTER_LON) if pd.notna(r["Lat"]) and pd.notna(r["Lon"]) else pd.NA, axis=1 )
df["Dist_km"].describe()
Делю расстояние на группы и кольца:
valid = df[df["Dist_km"].notna()].copy()
bins = [0, 2, 5, 10, 15, 25, 50, 10_000] labels = ["0–2 км", "2–5 км", "5–10 км", "10–15 км", "15–25 км", "25–50 км", "50+ км"]
valid["Dist_group"] = pd.cut(valid["Dist_km"], bins=bins, labels=labels, include_lowest=True)
valid["Dist_group"].value_counts().sort_index()
Выполнив все подготовительные действия строю круговую диаграмму:




