Коротко
- Операции между Series и таблицами выполняются по совпадающим меткам индекса, а не по позициям. Порядок строк не важен.
- Метка есть только в одном из объектов — в результате
NaN, а набор меток — объединение обоих. - Методы
add,sub,mul,divсfill_value=0считают отсутствующее значение нулём. reindex(метки)приводит объект к нужному набору меток;alignвыравнивает два объекта друг по другу.- Присваивание Series в столбец (
df["new"] = s) тоже идёт по меткам. Массив NumPy или список — по позициям.
Синтаксис
s1 + s2 # выравнивание по меткам
s1.add(s2, fill_value=0) # так же sub, mul, div
s.reindex(new_labels, fill_value=None)
a, b = s1.align(s2, join="outer")Параметры
ПараметрЧто делаетПо умолчанию
fill_valueзначение для отсутствующей метки перед операцией / при reindexNonejoinв align: "outer", "inner", "left", "right""outer"Примеры
plan = pd.Series({"Омск": 100, "Тула": 80, "Сочи": 60})
fact = pd.Series({"Тула": 90, "Омск": 110, "Пермь": 40})fact - plan # по меткам, а не по позициям; порядок не важенВывод
Омск 10.0 Пермь NaN Сочи NaN Тула 10.0 dtype: float64
fact.sub(plan, fill_value=0) # отсутствующая метка считается нулёмВывод
Омск 10.0 Пермь 40.0 Сочи -60.0 Тула 10.0 dtype: float64
plan.reindex(["Омск", "Тула", "Пермь"]) # новый набор меток; новых нет — NaNВывод
Омск 100.0 Тула 80.0 Пермь NaN dtype: float64
plan.reindex(["Омск", "Тула", "Пермь"], fill_value=0)Вывод
Омск 100 Тула 80 Пермь 0 dtype: int64
a, b = plan.align(fact, join="inner") # только общие метки
a, bВывод
(Омск 100 Тула 80 dtype: int64, Омск 110 Тула 90 dtype: int64)
df = pd.DataFrame({"plan": plan})
df["fact"] = fact # новый столбец тоже выравнивается по индексу
dfВывод
plan fact Омск 100 110.0 Тула 80 90.0 Сочи 60 NaN
Подводные камни
Метки не совпали — одни NaN
Если индексы двух объектов не пересекаются (например, после reset_index у одного из них), результат будет из одних NaN. Проверьте индексы или переходите к позиционной работе через to_numpy().
Массив вместо Series
Массив и список выравниванию не подлежат: значения записываются по порядку. Это удобно, но легко перепутать строки, если порядок разный.
df = pd.DataFrame({"plan": plan})
df["fact"] = fact.to_numpy()[:3] # массив без индекса — по порядку позиций
dfВывод
plan fact Омск 100 90 Тула 80 110 Сочи 60 40