{
"cells": [
{
"cell_type": "markdown",
"metadata": {},
"source": [
"# Таблицы `pandas`\n",
"\n",
"[pandas.DataFrame](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html) --- по сути дела таблица, на которую можно смотреть как на объединение столбцов `pandas.Series` с выравниванием по общему индексу. "
]
},
{
"cell_type": "code",
"execution_count": 2,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"
\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" s1 | \n",
" s2 | \n",
"
\n",
" \n",
" \n",
" \n",
" a | \n",
" 1 | \n",
" NaN | \n",
"
\n",
" \n",
" b | \n",
" 2 | \n",
" two | \n",
"
\n",
" \n",
" c | \n",
" <NA> | \n",
" three | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" s1 s2\n",
"a 1 NaN\n",
"b 2 two\n",
"c three"
]
},
"execution_count": 2,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"\n",
"s1 = pd.Series({\n",
" \"a\": 1,\n",
" \"b\": 2\n",
"}, dtype=\"Int8\")\n",
"s2 = pd.Series({\n",
" \"b\": \"two\",\n",
" \"c\": \"three\"\n",
"})\n",
"\n",
"df = pd.DataFrame({\n",
" \"s1\": s1,\n",
" \"s2\": s2\n",
"})\n",
"\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Таблицы изменяемы с точки зрения содержимого их ячеек, но лишь частично изменяемы с точки зрения размера: добавлять на месте можно только столбцы, но не строки. \n",
"\n",
"## Создание таблицы\n",
"\n",
"Как и в случае со столбцами, есть множество способов создать таблицу `pandas` из уже существующих объектов `python`. Большинство из них опираются на конструктор [pandas.DataFrame](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.html).\n",
"\n",
"### Список списков или двухмерный массив `NumPy`\n",
"\n",
"Если ваши данные хранятся в виде списка списков, то на выходе каждый вложенный список будет соответствовать строке таблице."
]
},
{
"cell_type": "code",
"execution_count": 8,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" 0 | \n",
" 1 | \n",
" 2 | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" a11 | \n",
" a12 | \n",
" a13 | \n",
"
\n",
" \n",
" 1 | \n",
" a21 | \n",
" a22 | \n",
" a23 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" 0 1 2\n",
"0 a11 a12 a13\n",
"1 a21 a22 a23"
]
},
"execution_count": 8,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"data = [\n",
" [\"a11\", \"a12\", \"a13\"],\n",
" [\"a21\", \"a22\", \"a23\"]\n",
" ]\n",
"\n",
"df = pd.DataFrame(data)\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"По умолчанию генерируется [RangeIndex](https://pandas.pydata.org/docs/reference/api/pandas.RangeIndex.html) и для строк и для столбцов таблицы. "
]
},
{
"cell_type": "code",
"execution_count": 11,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"df.index=RangeIndex(start=0, stop=2, step=1), df.columns=RangeIndex(start=0, stop=3, step=1)\n"
]
}
],
"source": [
"print(f\"{df.index=}, {df.columns=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Опциональными параметрами конструктора `columns` и `index` можно указать пользовательские значения."
]
},
{
"cell_type": "code",
"execution_count": 12,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" column 1 | \n",
" column 2 | \n",
" column 3 | \n",
"
\n",
" \n",
" \n",
" \n",
" row 1 | \n",
" a11 | \n",
" a12 | \n",
" a13 | \n",
"
\n",
" \n",
" row 2 | \n",
" a21 | \n",
" a22 | \n",
" a23 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" column 1 column 2 column 3\n",
"row 1 a11 a12 a13\n",
"row 2 a21 a22 a23"
]
},
"execution_count": 12,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"df = pd.DataFrame(data, columns=[\"column 1\", \"column 2\", \"column 3\"], index=[\"row 1\", \"row 2\"])\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Если вместо списка списков передавать двухмерный массив `NumPy`, то все будет работать точно также, кроме возможной потери типов."
]
},
{
"cell_type": "code",
"execution_count": 14,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" column 1 | \n",
" column 2 | \n",
" column 3 | \n",
"
\n",
" \n",
" \n",
" \n",
" row 1 | \n",
" a11 | \n",
" a12 | \n",
" a13 | \n",
"
\n",
" \n",
" row 2 | \n",
" a21 | \n",
" a22 | \n",
" a23 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" column 1 column 2 column 3\n",
"row 1 a11 a12 a13\n",
"row 2 a21 a22 a23"
]
},
"execution_count": 14,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import numpy as np\n",
"\n",
"data = np.array(data)\n",
"df = pd.DataFrame(data, columns=[\"column 1\", \"column 2\", \"column 3\"], index=[\"row 1\", \"row 2\"])\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Словарь\n",
"\n",
"Один самых удобных способов создавать таблицу в `pandas` --- использовать словари. \n",
"\n",
"Тут возможно два варианта.\n",
"1. ключи словаря --- названия столбца, значение по ключу --- содержимое соответствующего столбца;\n",
"2. ключи словаря --- метки строк, значение по ключу --- содержимое соответствующей строки. \n",
"\n",
"#### По столбцам\n",
"\n",
"Первый вариант гораздо более распространен, поэтому его рассмотрим первым. Итак, ключи словаря станут названиями столбцов, значение по ключу --- станет содержимым с соответствующим значением. \n",
"\n",
"Будущие столбцы в словари могут быть представлены списком, массивом `NumPy`, а также столбцом `pandas`. При этом в случае списков и массивов `NumPy` накладывается требование на одинаковую длину всех столбцов, а также автоматически генерируется [RangeIndex](https://pandas.pydata.org/docs/reference/api/pandas.RangeIndex.html), если он не указан в явном виде опциональным параметром `index`."
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" column 1 | \n",
" column 2 | \n",
" column 3 | \n",
"
\n",
" \n",
" \n",
" \n",
" a | \n",
" a11 | \n",
" a21 | \n",
" a31 | \n",
"
\n",
" \n",
" b | \n",
" a21 | \n",
" a22 | \n",
" a32 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" column 1 column 2 column 3\n",
"a a11 a21 a31\n",
"b a21 a22 a32"
]
},
"execution_count": 18,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"col1 = np.array([\"a11\", \"a21\"])\n",
"col2 = [\"a21\", \"a22\"]\n",
"col3 = \"a31\", \"a32\"\n",
"\n",
"d = {\n",
" \"column 1\": col1,\n",
" \"column 2\": col2,\n",
" \"column 3\": col3\n",
"}\n",
"\n",
"df = pd.DataFrame(d, index=[\"a\", \"b\"])\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Если же содержимое будущих столбцов представлено в виде столбцов `pandas`, то индекс таблицы генерируется из индексов этих столбцов, а ограничение на одинаковую длину столбцов снимается: строки таблицы выравниваются по индексу."
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" column 1 | \n",
" column 2 | \n",
" column 3 | \n",
"
\n",
" \n",
" \n",
" \n",
" a | \n",
" 1.0 | \n",
" 4 | \n",
" 5 | \n",
"
\n",
" \n",
" b | \n",
" 2.0 | \n",
" 3 | \n",
" 6 | \n",
"
\n",
" \n",
" c | \n",
" NaN | \n",
" <NA> | \n",
" 7 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" column 1 column 2 column 3\n",
"a 1.0 4 5\n",
"b 2.0 3 6\n",
"c NaN 7"
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import pandas as pd\n",
"import numpy as np\n",
"\n",
"col1 = pd.Series([1, 2], index=[\"a\", \"b\"])\n",
"col2 = pd.Series([3, 4], index=[\"b\", \"a\"], dtype=\"Int64\")\n",
"col3 = pd.Series([5, 6, 7], index=[\"a\", \"b\", \"c\"])\n",
"\n",
"d = {\n",
" 'column 1': col1, \n",
" 'column 2': col2,\n",
" 'column 3': col3,\n",
"}\n",
"\n",
"df = pd.DataFrame(d)\n",
"df"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"#### По строкам \n",
"\n",
"Статический метод [pandas.DataFrame.form_dict](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.from_dict.html#pandas.DataFrame.from_dict) --- более специализированный метод для создания таблицы из словаря. В примерах из предыдущего раздела этот метод сработает точно также, как и базовый конструктор класса, но наличие дополнительного опционального параметра `orient` (`orientation`) позволяет создавать таблицу из строк. \n",
"\n",
"Если указать в качестве `orient` строку `index`, то ключи словаря будут восприниматься в качестве меток строк, а значение по ключу --- содержимое строки с соответствующей меткой. Все остальное продолжает работать также, но с заменой меток и названий столбцов местами."
]
},
{
"cell_type": "code",
"execution_count": 20,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" column 1 | \n",
" column 2 | \n",
"
\n",
" \n",
" \n",
" \n",
" row1 | \n",
" 1 | \n",
" 2 | \n",
"
\n",
" \n",
" row2 | \n",
" 4 | \n",
" 3 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" column 1 column 2\n",
"row1 1 2\n",
"row2 4 3"
]
},
"execution_count": 20,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"row1 = pd.Series([1, 2], index=[\"column 1\", \"column 2\"])\n",
"row2 = pd.Series([3, 4], index=[\"column 2\", \"column 1\"])\n",
"\n",
"d = {\n",
" \"row1\": row1,\n",
" \"row2\": row2,\n",
"}\n",
"\n",
"pd.DataFrame.from_dict(d, orient=\"index\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Чтение таблиц с жесткого диска \n",
"\n",
"Библиотека `pandas` позволяет свободно оперировать с таблицами в формате `csv`, `json`, таблицами `excel` (потребуется установка дополнительной библиотеки, например, [openpyxl](https://openpyxl.readthedocs.io/en/stable/)), а также более продвинутыми бинарными форматами [hdf5](https://en.wikipedia.org/wiki/Hierarchical_Data_Format#HDF5), [apache parquet](https://parquet.apache.org/docs/) и многими другими форматами. Формат `csv` --- один из самых простых и распространенных в научной среде, поэтому рассмотрим чтение таблиц средствами `pandas` именно на его примере.\n",
"\n",
"```{note}\n",
"Все таблицы из этой лекции хранятся в репозитории с исходниками этого ресурса в папке по [ссылке](https://github.com/FadeevLecturer/python_lectures/tree/main/assets/data/tables). \n",
"```\n",
"\n",
"Предположим следующее содержимое хранится в текстовом файле `planets.csv` со следующим содержимым. \n",
"\n",
"```\n",
"Название,Количество спутников,Масса,Группа,Кольца\n",
"Меркурий,0,0.0055,земная группа,Нет\n",
"Венера,0,0.815,земная группа,Нет\n",
"Земля,1,1.0,земная группа,Нет\n",
"Марс,2,0.107,земная группа,Нет\n",
"Юпитер,62,317.8,газовый гигант,Да \n",
"Сатурн,34,95.2,газовый гигант,Да\n",
"Уран,27,14.37,ледяной гигант,Да\n",
"Нептун,13,17.15,ледяной гигант,Да\n",
"```\n",
"\n",
"Для чтения такой таблицы используется метод [read_csv](https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html). "
]
},
{
"cell_type": "code",
"execution_count": 19,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"\n",
"RangeIndex: 8 entries, 0 to 7\n",
"Data columns (total 5 columns):\n",
" # Column Non-Null Count Dtype \n",
"--- ------ -------------- ----- \n",
" 0 Название 8 non-null object \n",
" 1 Количество спутников 8 non-null int64 \n",
" 2 Масса 8 non-null float64\n",
" 3 Группа 8 non-null object \n",
" 4 Кольца 8 non-null object \n",
"dtypes: float64(1), int64(1), object(3)\n",
"memory usage: 448.0+ bytes\n",
"None\n"
]
},
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Название | \n",
" Количество спутников | \n",
" Масса | \n",
" Группа | \n",
" Кольца | \n",
"
\n",
" \n",
" \n",
" \n",
" 0 | \n",
" Меркурий | \n",
" 0 | \n",
" 0.0055 | \n",
" земная группа | \n",
" Нет | \n",
"
\n",
" \n",
" 1 | \n",
" Венера | \n",
" 0 | \n",
" 0.8150 | \n",
" земная группа | \n",
" Нет | \n",
"
\n",
" \n",
" 2 | \n",
" Земля | \n",
" 1 | \n",
" 1.0000 | \n",
" земная группа | \n",
" Нет | \n",
"
\n",
" \n",
" 3 | \n",
" Марс | \n",
" 2 | \n",
" 0.1070 | \n",
" земная группа | \n",
" Нет | \n",
"
\n",
" \n",
" 4 | \n",
" Юпитер | \n",
" 62 | \n",
" 317.8000 | \n",
" газовый гигант | \n",
" Да | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Название Количество спутников Масса Группа Кольца\n",
"0 Меркурий 0 0.0055 земная группа Нет\n",
"1 Венера 0 0.8150 земная группа Нет\n",
"2 Земля 1 1.0000 земная группа Нет\n",
"3 Марс 2 0.1070 земная группа Нет\n",
"4 Юпитер 62 317.8000 газовый гигант Да "
]
},
"execution_count": 19,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"import os\n",
"path = os.path.join(\"..\", \"..\", \"assets\", \"data\", \"tables\", \"planets.csv\")\n",
"\n",
"planets = pd.read_csv(path)\n",
"print(planets.info())\n",
"planets.head()"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В самом простом варианте использования функции `read_csv` \n",
"- имена столбцов распознаются из первой строки файла (параметром `header` можно повлиять на это);\n",
"- в качестве индекса генерируется `RangeIndex` (параметром `index_col` можно выбрать столбец индекса таблицы);\n",
"- в качестве разделителя ожидается символ запятой \"`,`\" (параметром `sep` можно на это повлиять);\n",
"- пропущенные значения заполняются значением \"`np.nan`\" (параметром `na_values` можно указать, какие ещё значения интерпретировать, как пропущенные);\n",
"- столбцы с датами не распознаются (смотри страницу \"[](datetime)\").\n",
"\n",
"```{note}\n",
"Метод [DataFrame.head](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.head.html) возвращает первые `n` строк таблицы. По умолчанию `n` равно 5, но можно указать явно и другое значение. Похожий по смыслу метод [DataFrame.tail](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.tail.html) возвращает последние `n` строк.\n",
"\n",
"Метод [DataFrame.info](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.info.html) печатает информацию о таблице. В частности, из вывода этой функции можно понять количество строк и столбцов, тип индекса таблицы, имя каждого столбца, тип данных и количество непропущенных значений в них.\n",
"```\n",
"\n",
"Считаем эту таблицу ещё раз, указав в этот раз в качестве индекса столбец `\"Название\"`."
]
},
{
"cell_type": "code",
"execution_count": 28,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Количество спутников | \n",
" Масса | \n",
" Группа | \n",
" Кольца | \n",
"
\n",
" \n",
" Название | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" Меркурий | \n",
" 0 | \n",
" 0.0055 | \n",
" земная группа | \n",
" Нет | \n",
"
\n",
" \n",
" Венера | \n",
" 0 | \n",
" 0.8150 | \n",
" земная группа | \n",
" Нет | \n",
"
\n",
" \n",
" Земля | \n",
" 1 | \n",
" 1.0000 | \n",
" земная группа | \n",
" Нет | \n",
"
\n",
" \n",
" Марс | \n",
" 2 | \n",
" 0.1070 | \n",
" земная группа | \n",
" Нет | \n",
"
\n",
" \n",
" Юпитер | \n",
" 62 | \n",
" 317.8000 | \n",
" газовый гигант | \n",
" Да | \n",
"
\n",
" \n",
" Сатурн | \n",
" 34 | \n",
" 95.2000 | \n",
" газовый гигант | \n",
" Да | \n",
"
\n",
" \n",
" Уран | \n",
" 27 | \n",
" 14.3700 | \n",
" ледяной гигант | \n",
" Да | \n",
"
\n",
" \n",
" Нептун | \n",
" 13 | \n",
" 17.1500 | \n",
" ледяной гигант | \n",
" Да | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Количество спутников Масса Группа Кольца\n",
"Название \n",
"Меркурий 0 0.0055 земная группа Нет\n",
"Венера 0 0.8150 земная группа Нет\n",
"Земля 1 1.0000 земная группа Нет\n",
"Марс 2 0.1070 земная группа Нет\n",
"Юпитер 62 317.8000 газовый гигант Да \n",
"Сатурн 34 95.2000 газовый гигант Да\n",
"Уран 27 14.3700 ледяной гигант Да\n",
"Нептун 13 17.1500 ледяной гигант Да"
]
},
"execution_count": 28,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"planets = pd.read_csv(path, index_col=\"Название\", sep=\",\")\n",
"planets"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Аналогично можно считывать данные из таблиц `excel` методом [read_excel](https://pandas.pydata.org/docs/reference/api/pandas.read_excel.html). \n",
"\n",
"Методами [to_csv](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_csv.html#pandas.DataFrame.to_csv) и [to_excel](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.to_excel.html#pandas.DataFrame.to_excel) можно сохранить `DataFrame` в таблицу удобном формате (для сохранения в `excel` необходимо поставить библиотеку [openpyxl](https://openpyxl.readthedocs.io/en/stable/) или её аналоги)."
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Индексация \n",
"\n",
"### Строки\n",
"\n",
"Для получения строк таблицы используются те же самые [.loc](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html) и [iloc](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.loc.html) (метки и порядковый номер соответственно). "
]
},
{
"cell_type": "code",
"execution_count": 27,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Количество спутников 2\n",
"Масса 0.107\n",
"Группа земная группа\n",
"Кольца Нет\n",
"Name: Марс, dtype: object\n",
"________________________________________________________________________________\n",
"Количество спутников 1\n",
"Масса 1.0\n",
"Группа земная группа\n",
"Кольца Нет\n",
"Name: Земля, dtype: object\n"
]
}
],
"source": [
"print(planets.loc[\"Марс\"])\n",
"print(\"_\" * 80)\n",
"print(planets.iloc[2])"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"В ответ вы получаете объект `pandas.Series` соответствующей всей строке, при этом индекс этого объекта соответствует названиям столбцов. Если использовать срезы или список меток, то вы получите новую таблицу с, возможно, меньшим количеством строк. \n",
"\n",
"```{warning}\n",
"Простые квадратные скобки \"`[]`\" не индексируют таблицу по строкам!\n",
"```\n",
"\n",
"### Столбцы\n",
"\n",
"Для получения столбца используется оператор \"`[]`\"."
]
},
{
"cell_type": "code",
"execution_count": 22,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Название\n",
"Меркурий 0\n",
"Венера 0\n",
"Земля 1\n",
"Марс 2\n",
"Юпитер 62\n",
"Сатурн 34\n",
"Уран 27\n",
"Нептун 13\n",
"Name: Количество спутников, dtype: int64"
]
},
"execution_count": 22,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"planets[\"Количество спутников\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Если в названии столбца нет пробелов и оно не совпадает ни с одним методом класса `pandas.DataFrame`, то можно использовать точечную нотацию. Хотя, конечно, в случае кириллицы это выглядит странно. "
]
},
{
"cell_type": "code",
"execution_count": 23,
"metadata": {},
"outputs": [
{
"data": {
"text/plain": [
"Название\n",
"Меркурий 0.0055\n",
"Венера 0.8150\n",
"Земля 1.0000\n",
"Марс 0.1070\n",
"Юпитер 317.8000\n",
"Сатурн 95.2000\n",
"Уран 14.3700\n",
"Нептун 17.1500\n",
"Name: Масса, dtype: float64"
]
},
"execution_count": 23,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"planets.Масса"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Можно указывать список названий столбцов, чтобы извлечь сразу подтаблицу целиком. "
]
},
{
"cell_type": "code",
"execution_count": 25,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Группа | \n",
" Кольца | \n",
" Масса | \n",
"
\n",
" \n",
" Название | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" Меркурий | \n",
" земная группа | \n",
" Нет | \n",
" 0.0055 | \n",
"
\n",
" \n",
" Венера | \n",
" земная группа | \n",
" Нет | \n",
" 0.8150 | \n",
"
\n",
" \n",
" Земля | \n",
" земная группа | \n",
" Нет | \n",
" 1.0000 | \n",
"
\n",
" \n",
" Марс | \n",
" земная группа | \n",
" Нет | \n",
" 0.1070 | \n",
"
\n",
" \n",
" Юпитер | \n",
" газовый гигант | \n",
" Да | \n",
" 317.8000 | \n",
"
\n",
" \n",
" Сатурн | \n",
" газовый гигант | \n",
" Да | \n",
" 95.2000 | \n",
"
\n",
" \n",
" Уран | \n",
" ледяной гигант | \n",
" Да | \n",
" 14.3700 | \n",
"
\n",
" \n",
" Нептун | \n",
" ледяной гигант | \n",
" Да | \n",
" 17.1500 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Группа Кольца Масса\n",
"Название \n",
"Меркурий земная группа Нет 0.0055\n",
"Венера земная группа Нет 0.8150\n",
"Земля земная группа Нет 1.0000\n",
"Марс земная группа Нет 0.1070\n",
"Юпитер газовый гигант Да 317.8000\n",
"Сатурн газовый гигант Да 95.2000\n",
"Уран ледяной гигант Да 14.3700\n",
"Нептун ледяной гигант Да 17.1500"
]
},
"execution_count": 25,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"planets[[\"Группа\", \"Кольца\", \"Масса\"]]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"### Конкретные ячейки"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Для получения доступа сразу к конкретной ячейке используются методы [DataFrame.at](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.at.html) и [DataFrame.iat](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.iat.html#pandas.DataFrame.iat).\n",
"- метод [DataFrame.at](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.at.html) принимает на вход метку строки и название столбца, и возвращает значение ячейки, располагающейся на их пересечении.\n",
"- метод [DataFrame.iat](https://pandas.pydata.org/docs/reference/api/pandas.DataFrame.iat.html) принимает на вход номер строки и номер столбца, и возвращает значение ячейки, располагающейся на их пересечении."
]
},
{
"cell_type": "code",
"execution_count": 26,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"planets.at['Меркурий', 'Количество спутников']=0, planets.iat[0, 0]=0\n"
]
}
],
"source": [
"print(f\"{planets.at['Меркурий', 'Количество спутников']=}, {planets.iat[0, 0]=}\")"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"Однако, если метки строк и названия столбцов повторяются, то методом \"`.at`\" вместо значения одной ячейки вы можете получить или сразу `pandas.Series` или `pandas.DataFrame`."
]
},
{
"cell_type": "code",
"execution_count": 43,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" b | \n",
" b | \n",
"
\n",
" \n",
" \n",
" \n",
" a | \n",
" 1 | \n",
" 1 | \n",
"
\n",
" \n",
" a | \n",
" 1 | \n",
" 1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" b b\n",
"a 1 1\n",
"a 1 1"
]
},
"execution_count": 43,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"duplicated_df = pd.DataFrame(data=[[1, 1], [1, 1]], index=[\"a\", \"a\"], columns=[\"b\", \"b\"])\n",
"duplicated_df"
]
},
{
"cell_type": "code",
"execution_count": 44,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" b | \n",
" b | \n",
"
\n",
" \n",
" \n",
" \n",
" a | \n",
" 1 | \n",
" 1 | \n",
"
\n",
" \n",
" a | \n",
" 1 | \n",
" 1 | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" b b\n",
"a 1 1\n",
"a 1 1"
]
},
"execution_count": 44,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"duplicated_df.at[\"a\", \"b\"]"
]
},
{
"cell_type": "markdown",
"metadata": {},
"source": [
"## Добавление столбцов \n",
"\n",
"Добавление и изменение столбцов в таблицу похоже на добавление элементов в словарь. При этом данные автоматически выравниваются по индексу. В качестве примера добавим к таблице про планет столбец с данными про экваториальный диаметр. Обратите внимание, что планеты перечислены в порядке отличном от порядка таблицы, и далеко не все планеты есть в новом столбце. В итоговой таблицы все присутствующие значения выравниваются, а недостающие заменяются на `NaN`."
]
},
{
"cell_type": "code",
"execution_count": 39,
"metadata": {},
"outputs": [
{
"data": {
"text/html": [
"\n",
"\n",
"
\n",
" \n",
" \n",
" | \n",
" Количество спутников | \n",
" Масса | \n",
" Группа | \n",
" Кольца | \n",
" Экваториальный диаметр | \n",
"
\n",
" \n",
" Название | \n",
" | \n",
" | \n",
" | \n",
" | \n",
" | \n",
"
\n",
" \n",
" \n",
" \n",
" Меркурий | \n",
" 0 | \n",
" 0.0055 | \n",
" земная группа | \n",
" Нет | \n",
" 0.382 | \n",
"
\n",
" \n",
" Венера | \n",
" 0 | \n",
" 0.8150 | \n",
" земная группа | \n",
" Нет | \n",
" 0.949 | \n",
"
\n",
" \n",
" Земля | \n",
" 1 | \n",
" 1.0000 | \n",
" земная группа | \n",
" Нет | \n",
" 1.000 | \n",
"
\n",
" \n",
" Марс | \n",
" 2 | \n",
" 0.1070 | \n",
" земная группа | \n",
" Нет | \n",
" NaN | \n",
"
\n",
" \n",
" Юпитер | \n",
" 62 | \n",
" 317.8000 | \n",
" газовый гигант | \n",
" Да | \n",
" NaN | \n",
"
\n",
" \n",
" Сатурн | \n",
" 34 | \n",
" 95.2000 | \n",
" газовый гигант | \n",
" Да | \n",
" 9.449 | \n",
"
\n",
" \n",
" Уран | \n",
" 27 | \n",
" 14.3700 | \n",
" ледяной гигант | \n",
" Да | \n",
" NaN | \n",
"
\n",
" \n",
" Нептун | \n",
" 13 | \n",
" 17.1500 | \n",
" ледяной гигант | \n",
" Да | \n",
" NaN | \n",
"
\n",
" \n",
"
\n",
"
"
],
"text/plain": [
" Количество спутников Масса Группа Кольца \\\n",
"Название \n",
"Меркурий 0 0.0055 земная группа Нет \n",
"Венера 0 0.8150 земная группа Нет \n",
"Земля 1 1.0000 земная группа Нет \n",
"Марс 2 0.1070 земная группа Нет \n",
"Юпитер 62 317.8000 газовый гигант Да \n",
"Сатурн 34 95.2000 газовый гигант Да \n",
"Уран 27 14.3700 ледяной гигант Да \n",
"Нептун 13 17.1500 ледяной гигант Да \n",
"\n",
" Экваториальный диаметр \n",
"Название \n",
"Меркурий 0.382 \n",
"Венера 0.949 \n",
"Земля 1.000 \n",
"Марс NaN \n",
"Юпитер NaN \n",
"Сатурн 9.449 \n",
"Уран NaN \n",
"Нептун NaN "
]
},
"execution_count": 39,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [
"planets[\"Экваториальный диаметр\"] = pd.Series({\n",
" \"Венера\": 0.949,\n",
" \"Сатурн\": 9.449,\n",
" \"Земля\": 1.0,\n",
" \"Меркурий\": 0.382,\n",
"})\n",
"\n",
"planets"
]
}
],
"metadata": {
"kernelspec": {
"display_name": "Python 3.8.10 ('venv': venv)",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.10.7"
},
"orig_nbformat": 4,
"vscode": {
"interpreter": {
"hash": "eea3ef54c04064aa17c056cc2578c78db8b44278034b77b7225a3166c34cea02"
}
}
},
"nbformat": 4,
"nbformat_minor": 2
}