Урок курса
Series и DataFrame: создание, index, columns, shape, dtypes
NumPy и pandas: практический тренажёрВ NumPy мы работали с ndarray — однородным массивом, у которого есть shape и dtype, но нет именованных осей. pandas строится поверх этой идеи и добавляет ключевое: каждая строка и каждый столбец получают метку. Начнём с самого простого объекта — Series.
Создание Series: из списка и из словаря
Series — это одномерный объект pandas: последовательность значений, у каждого из которых есть метка. Метки хранятся в атрибуте index, значения — в values.
Из списка. Когда передаёшь список, pandas сам генерирует целочисленный индекс начиная с 0:
import pandas as pd
s = pd.Series([10, 20, 30])
print(s)
# 0 10
# 1 20
# 2 30
# dtype: int64
print(s.index) # RangeIndex(start=0, stop=3, step=1)
print(s.values) # array([10, 20, 30])
RangeIndex — это не просто список чисел, а ленивый объект, аналогичный range. Pandas не хранит все метки явно в памяти, пока они стандартные целые числа от 0 до n.
Из словаря. Когда передаёшь словарь, ключи становятся метками index, значения — данными:
s2 = pd.Series({'x': 10, 'y': 20, 'z': 30})
print(s2)
# x 10
# y 20
# z 30
# dtype: int64
print(list(s2.index)) # ['x', 'y', 'z']
print(list(s2.values)) # [10, 20, 30]
Порядок меток соответствует порядку ключей в словаре — в Python 3.7+ словари упорядочены, поэтому результат предсказуем.
В обоих случаях структура одна и та же: массив значений плюс набор меток. Разница только в том, кто назначает метки — pandas автоматически или ты явно через ключи словаря. Именно эти метки и называются label; как они соотносятся с порядковыми номерами — разберём отдельно.
Создание DataFrame: из словаря списков и списка словарей
DataFrame — это двумерная структура: таблица со строками и столбцами. В отличие от Series, у неё есть два набора меток: index для строк и columns для столбцов.
Создать DataFrame можно двумя основными способами, и оба дают одинаковый результат при разных входных форматах.
Способ 1: словарь списков. Ключи словаря становятся именами столбцов, а каждый список — данными этого столбца:
import pandas as pd
df = pd.DataFrame({
'name': ['Анна', 'Борис', 'Вера'],
'score': [85, 92, 78],
'passed': [True, True, False]
})
print(df)
# name score passed
# 0 Анна 85 True
# 1 Борис 92 True
# 2 Вера 78 False
Здесь мышление «колонко-центричное»: ты сначала думаешь о столбцах, потом pandas собирает из них строки. Все списки обязаны быть одной длины — иначе pandas выбросит ошибку.
Способ 2: список словарей. Каждый словарь — одна строка, ключи — имена столбцов:
df2 = pd.DataFrame([
{'name': 'Анна', 'score': 85, 'passed': True},
{'name': 'Борис', 'score': 92, 'passed': True},
{'name': 'Вера', 'score': 78, 'passed': False}
])
print(df2)
# name score passed
# 0 Анна 85 True
# 1 Борис 92 True
# 2 Вера 78 False
Здесь мышление «строко-центричное»: каждая запись — один объект. Этот формат часто встречается, когда данные приходят из API или JSON-файлов — список объектов, где каждый объект описывает одну сущность.
Оба вызова дают структурно одинаковый DataFrame: те же столбцы, те же строки, тот же автоматический целочисленный index 0, 1, 2, …
Какой способ выбрать — зависит от источника данных. Если ты формируешь таблицу из готовых колонок (например, результатов вычислений), удобнее словарь списков. Если накапливаешь строки в цикле — удобнее список словарей, и в конце один вызов pd.DataFrame(rows) собирает всё вместе.
Атрибуты index, columns, shape и dtypes
Когда объект создан, нужно уметь быстро понять его структуру: сколько строк и столбцов, какие у них метки, какие типы данных. Для этого у Series и DataFrame есть несколько атрибутов, которые читаются без вызова — просто обращение к имени.
shape работает одинаково для обоих объектов и возвращает кортеж размерностей. У Series это (n,) — один элемент, потому что структура одномерная. У DataFrame — (n_rows, n_cols). Это прямой аналог ndarray.shape, синтаксис идентичен.
index и columns — наборы меток. У Series есть только index. У DataFrame есть оба: index для строк, columns для столбцов. Оба атрибута возвращают объект типа Index, который можно обернуть в list(), чтобы получить обычный список меток.
dtype и dtypes — типы данных. У Series — s.dtype (единственное число), потому что у неё один массив значений. У DataFrame — df.dtypes (множественное число), потому что каждый столбец может хранить свой тип. df.dtypes возвращает отдельный Series, где индекс — имена столбцов, а значения — их типы.
В примерах этого урока встречаются три типа: int64 для целых чисел, float64 для дробных, object для строк. object — это то, что pandas назначает столбцу со строковыми или смешанными значениями при стандартном создании DataFrame из Python-списков.
Вот как это выглядит на практике:
import pandas as pd
# Series из списка
s1 = pd.Series([10, 20, 30])
print(s1.shape) # (3,)
print(s1.dtype) # int64
print(s1.index) # RangeIndex(start=0, stop=3, step=1)
# Series из словаря
s2 = pd.Series({'a': 1.5, 'b': 2.5, 'c': 3.5})
print(s2.shape) # (3,)
print(s2.dtype) # float64
print(list(s2.index)) # ['a', 'b', 'c']
# DataFrame
df = pd.DataFrame({
'name': ['Анна', 'Борис', 'Вера'],
'score': [85, 92, 78],
'passed': [True, True, False]
})
print(df.shape) # (3, 3)
print(list(df.columns)) # ['name', 'score', 'passed']
print(list(df.index)) # [0, 1, 2]
print(df.dtypes)
# name object
# score int64
# passed bool
# dtype: object
На что смотреть в выводе df.dtypes: столбец name получил тип object, потому что содержит строки — именно так pandas представляет строковые данные при создании из обычных Python-списков. Столбец score — int64, passed — bool.
Важный нюанс для int64: если в столбец с целыми числами попадёт хотя бы одно значение None, pandas автоматически повысит тип до float64, чтобы представить отсутствующее значение через NaN. Это поведение характерно именно для стандартного int64 — NumPy-backed типа, который используется по умолчанию:
s3 = pd.Series([1, 2, None])
print(s3.dtype) # float64
print(s3) # 0 1.0 1 2.0 2 NaN dtype: float64
Практика чтения этих четырёх атрибутов стандартная: после создания любой таблицы сначала смотришь на shape, чтобы понять размер, потом на dtypes, чтобы убедиться, что типы подхватились правильно. Если score вдруг оказался object — значит, где-то в данных затесалась строка.
Метка (label) и позиция (position): в чём разница
У каждой строки в Series или DataFrame есть два способа её идентифицировать: по метке и по позиции. Это разные вещи, хотя при стандартном целочисленном индексе они выглядят одинаково.
Позиция — это порядковый номер элемента, считая от нуля. Первый элемент всегда на позиции 0, второй — на позиции 1, и так далее. Позиция не хранится явно нигде: она просто следует из порядка.
Метка — это значение из index, которое pandas хранит и использует для обращения к строке по имени. Метка может быть целым числом, строкой, датой — чем угодно.
Когда создаёшь Series из списка, pandas автоматически ставит метки 0, 1, 2, … Это RangeIndex, и в нём метка и позиция совпадают численно:
import pandas as pd
s = pd.Series([100, 200, 300])
print(list(s.index)) # [0, 1, 2]
Элемент на позиции 0 имеет метку 0, на позиции 1 — метку 1. Выглядит одинаково, но это совпадение, а не тождество.
Как только создаёшь Series из словаря с нецелочисленными ключами, совпадение пропадает:
s2 = pd.Series({'x': 10, 'y': 20, 'z': 30})
print(list(s2.index)) # ['x', 'y', 'z']
Здесь метки — это 'x', 'y', 'z'. Позиции по-прежнему 0, 1, 2. Метка 'y' находится на позиции 1 — это разные идентификаторы одного и того же элемента.
Почему это важно прямо сейчас, до всякой индексации: pandas строит всю систему доступа к данным вокруг этого разграничения. Когда будешь работать с выборкой строк, придётся явно выбирать — обращаешься по метке или по позиции. Если перепутать, получишь либо ошибку, либо молча неверный результат.
Особенно наглядно разрыв между меткой и позицией виден, когда DataFrame создаётся с нестандартным индексом. Представь, что данные уже пришли в таком порядке — строки с метками 2, 0, 1:
df = pd.DataFrame(
{
'name': ['Вера', 'Анна', 'Борис'],
'score': [78, 85, 92]
},
index=[2, 0, 1] # метки строк заданы явно
)
print(df)
# name score
# 2 Вера 78
# 0 Анна 85
# 1 Борис 92
print(df.index.tolist()) # [2, 0, 1]
Строка с меткой 2 (Вера) находится на позиции 0 — первая физически. Строка с меткой 0 (Анна) — на позиции 1. Метки здесь не совпадают с позициями: метка 0 не означает «первая строка».
Если обращаться к этому DataFrame по позиции, на нулевой позиции окажется Вера. Если по метке 0 — Анна. Это ровно та точка, где путаница между меткой и позицией начинает давать неверные результаты — и именно поэтому pandas предоставляет разные инструменты для каждого из этих двух способов обращения к данным.
Задача 1
Series создан командой s = pd.Series({'p': 1, 'q': 2, 'r': 3}). Что вернёт list(s.index)?
Задача 2
DataFrame создан так: df = pd.DataFrame([{'x': 1, 'y': 2}, {'x': 3, 'y': 4}, {'x': 5, 'y': 6}]). Чему равен df.shape?
Задача 3
Series и DataFrame: создание из двух форматов и чтение shape, dtypes, index, columns
Что уже дано
Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет — вы читаете всё сами.
Что нужно сделать
Напишите программу, которая:
- Читает из
stdinцелое числоn— количество строк таблицы. - Читает следующие
nстрок; каждая содержит три токена через пробел:название(строка без пробелов),цена(целое число),количество(целое число). Пример строки:Стол 5000 12. - Создаёт
pd.Seriesс именемpricesиз списка цен (в том порядке, в котором они прочитаны). Индекс — автоматическийRangeIndex. - Создаёт
pd.DataFrameс именемdfиз словаря списков с тремя ключами:'name','price','qty'— в таком порядке. - Выводит в
stdoutровно шесть строк:
- Строка 1:
prices.shapeв виде(n,). - Строка 2:
prices.dtype— строковое представление типа. - Строка 3:
df.shapeв виде(n_rows, n_cols). - Строка 4:
list(df.columns)— список имён столбцов через стандартныйprint. - Строка 5:
list(df.index)— список меток строк. - Строка 6: три пары
имя_столбца:dtypeчерез пробел, по одной на каждый столбецdfв порядкеdf.dtypes.items().
Для строки 6 используйте формат name:object price:int64 qty:int64.
Ввод и вывод
Программа читает stdin и пишет в stdout.
Формат ввода
n название1 цена1 количество1 название2 цена2 количество2 ...
Дополнительные ограничения: n >= 1.
Формат вывода
(n,)
dtype_series
(n, 3)
['name', 'price', 'qty']
[0, 1, ..., n-1]
name:object price:int64 qty:int64
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 4
Series из словаря: метки, позиции и атрибуты index, shape, dtype
Что уже дано
Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет — вы читаете всё сами.
Что нужно сделать
Напишите программу, которая:
- Читает из
stdinцелое числоk— количество пар. - Читает следующие
kстрок; каждая содержит два токена через пробел:метка(строка без пробелов) изначение(целое число). Пример строки:alpha 42. - Создаёт
pd.Seriesиз словаря{метка: значение, …}в порядке прочитанных строк — назовите егоs. - Выводит в
stdoutровноk + 4строк в следующем порядке:
- Строки 1…k: для каждого
iот0доk-1— одну строку видаlabel=<метка> pos=<i> value=<значение>, где<метка>—s.index[i],<i>— позиция (целое число),<значение>—s.iloc[i]. - Строка k+1:
shape=<shape>— кортеж вида(k,). - Строка k+2:
dtype=<dtype>— строковое представлениеs.dtype. - Строка k+3:
index_type=<тип>— имя класса объектаs.index, получите черезtype(s.index).__name__. - Строка k+4:
first_label_is_pos_0=<bool>— результат сравненияs.index[0] == 0в видеTrueилиFalse.
Последняя строка демонстрирует ключевую идею: когда индекс — строки, метка первого элемента не равна его позиции 0.
Ввод и вывод
Программа читает stdin и пишет в stdout.
Формат ввода
k метка1 значение1 метка2 значение2 ...
Дополнительные ограничения: k >= 1; все строковые метки попарно различны.
Формат вывода
label=метка1 pos=0 value=значение1
label=метка2 pos=1 value=значение2
...
shape=(k,)
dtype=int64
index_type=Index
first_label_is_pos_0=False
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 5
DataFrame из списка словарей: dtypes, метки и позиции строк
Что уже дано
Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет — вы читаете всё сами.
Что нужно сделать
Напишите программу, которая:
- Читает из
stdinцелое числоn— количество строк таблицы. - Читает следующие
nстрок; каждая содержит три токена через пробел:город(строка без пробелов),население(целое число),площадь(вещественное число, может быть целым). Пример строки:Казань 1200000 614.0. - Формирует список словарей, где каждый словарь имеет ключи
'city','population','area'— в таком порядке. Создаётpd.DataFrameиз этого списка словарей; называет егоdf. - Выводит в
stdoutровноn + 5строк в следующем порядке:
- Строки 1…n: для каждой позиции
iот0доn-1— строку видаpos=<i> label=<метка> city=<значение df['city'].iloc[i]>, где<метка>—df.index[i](целое число). - Строка n+1:
shape=<shape>— кортеж вида(n, 3). - Строка n+2:
columns=<список>—list(df.columns)через стандартныйprint. - Строка n+3:
city_dtype=<dtype>—df.dtypes['city']. - Строка n+4:
population_dtype=<dtype>—df.dtypes['population']. - Строка n+5:
area_dtype=<dtype>—df.dtypes['area'].
Для строк n+3…n+5 используйте формат city_dtype=object, population_dtype=int64, area_dtype=float64.
Ввод и вывод
Программа читает stdin и пишет в stdout.
Формат ввода
n город1 население1 площадь1 город2 население2 площадь2 ...
Дополнительные ограничения: n >= 1.
Формат вывода
pos=0 label=0 city=город1
pos=1 label=1 city=город2
...
shape=(n, 3)
columns=['city', 'population', 'area']
city_dtype=object
population_dtype=int64
area_dtype=float64
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задача 6
Найди и исправь: три ошибки в создании Series/DataFrame и чтении атрибутов
Что уже дано
Проверяющая система запускает вашу программу и подаёт данные через stdin. Никаких заранее созданных переменных нет.
В редакторе уже есть сломанный код. В нём ровно три ошибки в трёх независимых строках:
pd.Seriesсоздаётся из словаря{'a': 1, 'b': 2, 'c': 3}, но при выводеindex_typeиспользуетсяtype(s.values).__name__вместоtype(s.index).__name__— в результате выводится тип массива значений, а не тип объекта-индекса.pd.DataFrameсоздаётся из словаря списков, но в коде написаноpd.DataFrame([cols]), гдеcols— сам словарь, обёрнутый в список. Это создаёт DataFrame из одного словаря-строки вместо словаря столбцов. Нужно передать словарь напрямую:pd.DataFrame(cols).- При выводе
shapeDataFrame используетсяdf.shape[0]вместоdf.shape— печатается только число строк, а не полный кортеж.
Каждая ошибка находится в отдельной строке; исправление каждой не затрагивает остальные.
Что нужно сделать
Найдите и исправьте все три ошибки так, чтобы программа:
- Читала из
stdinцелое числоn— количество записей. - Читала следующие
nстрок; каждая содержит два токена через пробел:метка(строка без пробелов) изначение(целое число). - Создавала
pd.Seriesиз словаря{метка: значение, …}в порядке прочитанных строк — имя переменнойs. - Создавала
pd.DataFrameиз словаря списков с двумя столбцами:'label'(список меток) и'value'(список значений) — имя переменнойdf. - Выводила в
stdoutровно пять строк:
- Строка 1:
index_type=<тип>— имя классаs.indexчерезtype(s.index).__name__. - Строка 2:
s_shape=<shape>— кортеж вида(n,). - Строка 3:
s_dtype=<dtype>— строковое представлениеs.dtype. - Строка 4:
df_shape=<shape>— полный кортеж вида(n, 2). - Строка 5:
first_label_is_pos_0=<bool>— результатs.index[0] == 0в видеTrueилиFalse.
Ввод и вывод
Программа читает stdin и пишет в stdout.
Формат ввода
n метка1 значение1 метка2 значение2 ...
Дополнительные ограничения: n >= 1; все строковые метки попарно различны.
Формат вывода
index_type=Index
s_shape=(n,)
s_dtype=int64
df_shape=(n, 2)
first_label_is_pos_0=False
Без регистрации. Гостевая проверка не сохраняет прогресс. Для сохранения перейдите к уроку.
Отправьте решение, чтобы увидеть результаты тестов.
Задачи к уроку
- pandas Series из словаря: index, shape и dtype
Создайте Series из словаря и проверьте метки, позиции и атрибуты index, shape и dtype. Задача по pandas.
- pandas DataFrame из списка словарей: пример и задача
Создание DataFrame из списка словарей, индекс и dtype столбцов: короткий пример и практическая задача с проверкой Python-кода.
Продолжить с сохранением прогресса
Перейдите к уроку в учебном кабинете.
