<?xml version="1.0" encoding="UTF-8"?><rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Pandas. Обработка данных - Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</title>
	<atom:link href="https://python.ivan-shamaev.ru/category/pandas-data-processing/feed/" rel="self" type="application/rss+xml" />
	<link>https://python.ivan-shamaev.ru/category/pandas-data-processing/</link>
	<description>Библиотеки обработки данных. Примеры. Строки, списки, файлы, числа, массивы. Язык программирования Python 3 - скачать</description>
	<lastBuildDate>Sat, 29 Jan 2022 10:04:57 +0000</lastBuildDate>
	<language>ru-RU</language>
	<sy:updatePeriod>
	hourly	</sy:updatePeriod>
	<sy:updateFrequency>
	1	</sy:updateFrequency>
	<generator>https://wordpress.org/?v=6.6.5</generator>

<image>
	<url>https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/cropped-data_science_python3_logo-32x32.png</url>
	<title>Pandas. Обработка данных - Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</title>
	<link>https://python.ivan-shamaev.ru/category/pandas-data-processing/</link>
	<width>32</width>
	<height>32</height>
</image> 
	<item>
		<title>ETL Best Practices. ETL Design Patterns. Что такое ETL?</title>
		<link>https://python.ivan-shamaev.ru/etl-best-practices-design-data-patterns/</link>
					<comments>https://python.ivan-shamaev.ru/etl-best-practices-design-data-patterns/#respond</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Tue, 04 Jan 2022 21:39:00 +0000</pubDate>
				<category><![CDATA[Pandas. Обработка данных]]></category>
		<category><![CDATA[Data Lineage]]></category>
		<category><![CDATA[ETL Atomicity]]></category>
		<category><![CDATA[ETL Best Practices]]></category>
		<category><![CDATA[ETL Design Patterns]]></category>
		<category><![CDATA[ETL Error Handling]]></category>
		<category><![CDATA[ETL Modularity]]></category>
		<category><![CDATA[Logging ETL]]></category>
		<category><![CDATA[Аудит ETL]]></category>
		<category><![CDATA[Что такое ETL]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=1249</guid>

					<description><![CDATA[<p>ETL Best Practices Процессы извлечения, преобразования и загрузки данных (ETL) являются центральными в стратегии управления данными любой организации. Каждый шаг в процессе ETL &#8212; получение данных из различных источников, изменение их формы/структуры, применение бизнес-правил, загрузка в хранилище и проверка результатов &#8212; является важным этапом в процессе передачи данных. Ниже перечислены некоторые основы, которые являются ключевыми [&#8230;]</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/etl-best-practices-design-data-patterns/">ETL Best Practices. ETL Design Patterns. Что такое ETL?</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&#038;title=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" data-a2a-url="https://python.ivan-shamaev.ru/etl-best-practices-design-data-patterns/" data-a2a-title="ETL Best Practices. ETL Design Patterns. Что такое ETL?"></a></p><h2><strong>ETL Best Practices</strong></h2>
<p><strong>Процессы извлечения, преобразования и загрузки данных (ETL)</strong> являются центральными в стратегии управления данными любой организации. Каждый шаг в процессе ETL &#8212; получение данных из различных источников, изменение их формы/структуры, применение бизнес-правил, загрузка в хранилище и проверка результатов &#8212; является важным этапом в процессе передачи данных.</p>
<p>Ниже перечислены некоторые основы, которые являются ключевыми для большинства имплементаций ETL.</p>
<h2><strong>Описание ключевых процессов ETL согласно лучшим практикам</strong></h2>
<h3><strong>What is ETL (Что такое ETL)</strong></h3>
<p><strong>ETL (Extraction, Transformation, Loading)</strong> является сокращением от процессов извлечения, преобразования и загрузки данных, которые используются при наполнении данными хранилища.</p>
<p>При работе с операциями ETL вы обычно слышите термин <strong>конвейер данных/data pipeline (или просто &#171;конвейер/pipeline&#187;).</strong> Легко визуализировать такой процесс, как конвейер, в который поступают необработанные данные и выходит полезная информация.</p>
<p>Некоторые данные могут быть переданы в специальное место для очистки, а некоторые данные могут быть помечены как плохие и отправлены в область хранения плохих данных.</p>
<p>Конвейер данных может быть простым и прямым или может иметь множество изгибов и разветвлений. В большинстве случаев этот виртуальный конвейер данных существует в RAM на компьютере/сервере, на котором выполняются операции ETL, также данные могут быть временно сохранены в промежуточные или временные таблицы по мере необходимости.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/06/etl_pipeline_best_practice.png"><img fetchpriority="high" decoding="async" class="aligncenter size-full wp-image-1261" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/06/etl_pipeline_best_practice.png" alt="" width="768" height="437" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/06/etl_pipeline_best_practice.png 768w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/06/etl_pipeline_best_practice-300x171.png 300w" sizes="(max-width: 768px) 100vw, 768px" /></a></p>
<p>Как следует из названия, в ETL-операциях существует три разных этапа.</p>
<h4><strong>Extraction (Экстракция или выгрузка данных)</strong></h4>
<p>На этом этапе данные извлекаются из источника и попадают в конвейер. Источником может быть реляционная база данных, плоский файл (csv, excel, txt, и т.д.), API, устройство IOT, веб-сайт &#8212; почти все, что может создавать и/или хранить данные, может использоваться в качестве источника в процессе ETL. Этот этап не ограничен одним источником данных. Обычно для операций выгрузки данных характерно использование нескольких источников.</p>
<p>Хотя извлечение данных обычно является самой простой частью процесса ETL, иногда процесс выгрузки данных может приобретать сложную форму. Например, при выгрузке очень больших наборов данных, экстракция данных может выполняться длительное время, поэтому может потребоваться реализация дополнительной логики для создания инкрементальной выгрузки данных.</p>
<p>Также при выгрузке данных из API сервисов, таких как Youtube API, Facebook API при большом объеме данных может портебоваться специальная логика, т.к. многие сервисы отдают данные в рамках доступного лимита (например, лимит по количеству запросов или скорости обращения к API).</p>
<h4><strong>Transformation (Преобразование)</strong></h4>
<p>На этапе преобразования/трансформации данных могут выполняться следующие манипуляции над данными:</p>
<ul>
<li><strong>Data reshaping</strong>: Изменение формы данных</li>
<li><strong>Изменение гранулярности данных (data granularity)</strong>, когда одна входная строка становится несколькими выходными или наоборот</li>
<li>Изменения типа данных (например, преобразование текста в целое число)</li>
<li>Устранение дубликатов</li>
<li>Использование таблицы поиска или маппинга (<strong>lookup tables/mappings</strong>) для проверки значений или для подстановки значения по ключу</li>
<li>Удаление пробелов в начале или в конце строки, а также удаление других непечатных символов (их кстати можно обнаружить в MS Word или Notepad++, если вставить в документ и включить режим отображения символов)</li>
<li>Привести текст к единому виду: например, стандартизировать регистр и заглавные буквы</li>
<li>Выявление и перенаправление неверных или подозрительных строк данных</li>
<li>Применение бизнес-логики</li>
<li>Парсинг отдельных значений из строк, например, с помощью RegEx и создание на основе полученных значений дополнительного атрибута данных/транзакций</li>
</ul>
<p>Не каждый процесс ETL требует всех перечисленных манипуляций. Большинство процессов будет использовать только их часть, либо отдельные методы для решения конкретной задачи. Степень преобразования данных зависит от качества и формы исходных данных, а также от того, насколько хорошо они соответствуют потребностям бизнеса и от поставленных задач самим бизнесом.</p>
<p>Некоторые наборы данных потребуют минимального преобразования, в то время как другие наборы данных потребуют значительной переработки. Для финансовых данных очень часто требуется реализация специальной логики аллокаций расходов, что порой приводит к большому числу обрабатывающих скриптов для небольшого объема данных по сравнению с остальными доменами.</p>
<p><strong>Преобразование данных</strong> является наиболее сложной частью процесса ETL. Фактически, для большинства инициатив по перемещению данных, разработка процесса преобразования данных (включая сбор требований, разработку и тестирование) является наиболее трудоемкой частью всего проекта.</p>
<p><strong>Совет по ETL для project managers:</strong> не стоит недооценивать время или усилия, необходимые для создания процесса преобразования данных. Проекты могут значительно задерживаться по срокам, потому что архитекторы или разработчики недооценили время, необходимое для разработки и тестирования этапа преобразования данных.</p>
<h4><strong>Load (Загрузка)</strong></h4>
<p>Фаза загрузки является последним этапом процесса ETL. На этом этапе данные передаются в структуры (<strong>data storage</strong>), в которых они будут храниться постоянно.</p>
<p>К тому времени, когда данные достигают фазы загрузки, все обновления завершены и данные уже подготовлены.</p>
<h4>Собираем все этапы вместе</h4>
<p>Три фазы каждой операции <strong>извлечения, преобразования и загрузки</strong> обычно тесно связаны друг с другом. Конвейер данных обычно работает в оперативной памяти сервера. ETL обычно разбивается на отдельные цепочки выгрузки, трансформации данных.</p>
<p>Иногда и загрузка данных в хранилище включается в эту цепочку.</p>
<h3><strong>Logging (Ведение журнала)</strong></h3>
<p><span style="color: #ff6600;"><strong>Logging (Ведение журнала).</strong></span> Правильная стратегия ведения журнала является ключом к успеху любой архитектуры ETL.</p>
<p>Если бы вы опрашивали специалистов по данным, над какими задачами им больше всего нравится работать, журналирование ETL, вероятно, не попало бы в список. Тем не менее, для успеха любой архитектуры ETL важно установить соответствующую стратегию ведения журнала. Отличной метафорой хорошей инфраструктуры логирования процесса ETL является водопровод дома: он не виден внешне, не является очень интересным, но вы наверняка со временем узнаете, правильно ли он спроектирован и смонтирован (или не установлен вовсе) при возникновении первых проблем с ним.</p>
<h4><strong>Что такое Logging?</strong></h4>
<p><strong>Что же такое протоколирование ETL (или Logging).</strong> <span style="color: #ff6600;"><strong>Протоколирование ETL</strong></span> &#8212; это журнал активности соответствующих событий, которые происходят до, во время и после выполнения процесса <em><strong>extract-transform-load</strong></em>.</p>
<p>Ведение журнала обычно осуществляется в самом программном обеспечении ETL, но может также включать другие журналы (например, в средствах планирования заданий) для получения дополнительных сведений по процессам ETL. Эти журналы будут различаться по степени детализации и объему записей, некоторые из них описывают метрики уровня нагрузки (сколько времени занимал весь процесс, сколько ресурсов потребовалось для работы), а другие относятся к одному небольшому сегменту нагрузки (сколько строк было загружено на шаге N).</p>
<p>Не существует универсального подхода к ведению журнала. В идеале каждый процесс должен оцениваться для определения стратегии ведения журнала на основе критичности данных, частоты выполнения, вероятности отказа и других факторов, которые важны в вашей среде.</p>
<h4>Что следует логировать (писать в журнал)?</h4>
<p>Как отмечалось выше, для ведения журнала требуется нечто большее, чем просто подход к работе с файлами cookie, поскольку каждый процесс может иметь немного разные потребности при ведении журнала. Однако в реальном мире большинство организаций применяют подход «все или ничего» ко всем процессам ETL:</p>
<ul>
<li>либо они вообще не регистрируются,</li>
<li>либо все возможные метрики регистрируются и сохраняются навсегда.</li>
</ul>
<p>Хотя для каждого из них есть некоторые крайние случаи, ответ почти всегда лежит где-то посередине (хотя, мы надеемся, ближе к способу «регистрировать все»).</p>
<p>Минималистичный подход может включать в себя просто запись времени начала и окончания всего процесса. Подобный урезанный подход работает лучше всего, когда объем возможных ошибок невелик, и когда процесс может быть перезапущен без больших временных и стоимостных издержек.</p>
<p>Это успешно используется для некоторых этапов загрузки, когда данные загружаются в изменяемые промежуточные таблицы. Большинство этапов загрузки включают в себя сначала удаление старых данных из целевых таблиц, что означает, что они могут запускаться повторно, не вызывая случайного дублирования данных. Следовательно, использование минималистического подхода к ведению журнала может быть использовано при таких типах нагрузок, поскольку точки отказа довольно минимальны, и процесс может быть легко перезапущен, если потребуется дальнейшая диагностика.</p>
<p>Однако большинство процессов требуют более интенсивного ведения журнала. Чтобы по-настоящему фиксировать то, что происходит внутри каждого процесса загрузки, а не просто измерять процесс в целом, для каждой задачи должен существовать пошаговый журнал. Если конкретное задание ETL имеет, например, десять шагов, в идеальном проекте будет регистрироваться запуск и остановка каждой задачи, любые исключения на уровне задачи, а также любая необходимая информация для аудита.</p>
<p>Следующие <strong>атрибуты logging</strong> могут использоваться в качестве приблизительного руководства по типам событий и метрик, которые нужно регистрировать во время логирования:</p>
<ul>
<li><em><strong>Запуск и остановка событий.</strong></em> Начальная и конечная временные метки для процесса ETL в целом, а также их отдельные шаги должны быть сохранены.</li>
<li><em><strong>Статус. </strong></em>Шаги процесса могут быть успешными или неудачными по отдельности, и поэтому их состояние (not started, running, succeeded, или failed) должно регистрироваться индивидуально.</li>
<li><em><strong>Ошибки и другие исключения.</strong></em> Сбои и аномалии ведения журнала часто являются наиболее трудоемкой частью построения инфраструктуры ведения журнала. Это также та часть, которая приносит наибольшую пользу при тестировании и устранении неисправностей.</li>
<li><em><strong>Аудиторская информация.</strong></em> Это может варьироваться от простого захвата количества строк, загруженных при каждом выполнении процесса, до полного анализа количества строк и значений в единицах измерения на пути от источника к месту назначения.</li>
<li><em><strong>Тестирование и отладка информации.</strong></em> Это особенно полезно на этапе разработки и тестирования, в частности, для процессов, которые сильно влияют на преобразование ETL.</li>
</ul>
<p>При планировании стратегии ведения журнала обычно просто регистрируют все события. Некоторые инструменты ETL, в том числе <a href="https://msdn.microsoft.com/en-us/library/ms141026.aspx" target="_blank" rel="noopener noreferrer">службы интеграции SQL Server</a> , позволяют относительно легко перейти в режим <em>захвата всех событий</em>.</p>
<p>Регистрировать слишком много информации лучше, чем недостаточно, при прочих равных условиях. Однако с ведением журнала всегда связаны затраты: накладные расходы на обработку, пропускная способность сети и требования к хранилищу должны учитываться при определении того, как будут регистрироваться процессы ETL. Регистрация каждого доступного показателя и события может быть проще, но это не бесплатно.</p>
<p><strong>Помните:</strong> соблюдайте баланс между тем, что вы хотели бы получить при ведении журнала, и затратами (жесткими и мягкими) на стратегию ведения журнала.</p>
<h4><strong>Как следует использовать Logs?</strong></h4>
<p>Давайте на минутку предположим, что ваша инфраструктура логирования построена и работает так, как ожидалось. Как вы передаете эту информацию нужным людям?</p>
<p><strong>Очень часто бывает так:</strong> процессы ETL полностью регистрируются, но никто не знает, что именно регистрируется и где хранится информация. Если процессы регистрируются в черной дыре, информация о регистрации &#8212; это <em>просто данные</em>; они должны быть доступны и понятны, прежде чем эти данные можно будет классифицировать как <em>информацию</em>.</p>
<p>Большинство фанатов данных на самом деле предпочитают иметь доступ к необработанным, нефильтрованным данным журнала, чтобы можно было писать собственные запросы для получения именно тех исходных данных для детального понимания процессов ETL. Другие люди, которые не так любят писать SQL, вероятно, добились бы большего успеха с более упорядоченной информацией по логированию. Все чаще другим, часто полутехническим или нетехническим людям, также необходим доступ к журналам ETL. Администраторам баз данных, сотрудникам службы поддержки, бизнес-аналитикам и аудиторам, возможно, потребуется увидеть, что находится в журналах, и каждая группа, вероятно, имеет совершенно разные ожидания того, как получить эти данные. Некоторые топ менеджеры также могут периодически просматривать данные журнала ETL.</p>
<p>При рассмотрении того, как будет использоваться информация о регистрации, учтите следующее:</p>
<ul>
<li>Кто будет основной аудиторией для этих журналов?</li>
<li>Каким другим аудиториям может понадобиться доступ к этой информации?</li>
<li>Будут ли данные проверяться в режиме ad-hoc, или их необходимо формализовать с помощью принудительной доставки через уведомления или с помощью различных dashboards?</li>
<li>В каком формате информация будет доставлятся наиболее понятным способом?</li>
<li>Существуют ли проблемы безопасности, требующие фильтрации данных на уровне пользователя?</li>
</ul>
<p>Ответы на эти вопросы будут определять стратегию раскрытия данных журнала. Это может быть так же просто, как предоставить другим администраторам баз данных местоположение данных журнала, или более формализованным, например, создать отчет через службу отчетов SQL Server или создать отдельную панель мониторинга <a href="https://powerbi.microsoft.com/" target="_blank" rel="noopener noreferrer">Power BI</a>.</p>
<p>Независимо от того, какой подход используется, цель состоит в том, чтобы донести необходимую информацию до целевой аудитории максимально понятным способом.</p>
<h4><strong>Политика хранения (Retention Policy)</strong></h4>
<p>Часто клиенты спрашивают: «Как долго необходимо хранить журналы ETL?».</p>
<p>Оптимальный ответ таков: «Храните их столько, сколько нужно, но не дольше». Да, это стереотипный ответ консультанта, но на самом деле ответ полностью зависит от ожиданий того, как будут использоваться эти журналы.</p>
<p>Вот общий диалог, который случается при обсуждении краткосрочной и долгосрочной стратегии хранения для журналов ETL:</p>
<ul>
<li><em><strong>Короткий срок хранения </strong></em>: «Короткий срок хранения гарантирует, что вы не будете заполнять свои диски кучей старых данных журнала, которые вы никогда не будете использовать. Ведение журналов всего за несколько месяцев или за год обеспечивает достаточную историю для устранения любых недавних логических проблем или проблем с производительностью в вашем ETL. Короткие сроки хранения могут работать хорошо для вас, если вы в основном заинтересованы в оперативной поддержке и не используете свои журналы для долгосрочного анализа производительности или аудита».</li>
<li><strong>Длительный срок хранения</strong> : «Да, в хранилище вам дороже хранить журналы в течение более длительного периода времени. Но кого это волнует? Хранение относительно недорого, и вы можете архивировать старые логи на более медленные и более дешевые диски. Сохраняя свои журналы в течение более длительного периода, вы можете анализировать рабочие нагрузки и производительность ETL с течением времени, чтобы увидеть, как вы оцениваете тенденции по сравнению с прошлым годом. А если вы находитесь в среде с жестким аудитом, длительное хранение журналов может удовлетворить большую часть (или даже все) ваши требования аудита ETL».</li>
</ul>
<p>Как и с большинством других концепций, не существует единого подхода для удовлетворения каждой ситуации. Однако в большинстве случаев следует ориентироваться на более длительный срок хранения журналов ETL, если только нет явной причины избегать этого. Лучше иметь данные, которые вы никогда не будете использовать, чем если вам потребуются данные, которых у вас нет.</p>
<p>Также можно агрегировать информацию из логов и наиболее старые данные хранить в виде сводной информации по дням или месяцам.</p>
<p>При создании стратегии хранения журналов ETL необходимо задать следующие ключевые вопросы:</p>
<ul>
<li>Будем ли мы использовать данные журнала ETL для тактического устранения неполадок или анализа тенденций и аудита?</li>
<li>Сколько данных журнала мы генерируем каждый день / месяц / год?</li>
<li>Сколько стоит хранение данных журнала?</li>
<li>Насколько сложно и дорого будет архивировать старые логи в более дешевое и медленное хранилище?</li>
<li>Каковы нормативные и/или аудиторские требования для журналов ETL?</li>
</ul>
<h4><strong>Вывод</strong></h4>
<p>Построение правильной архитектуры ведения журнала ETL является одним из самых основных компонентов стратегии управления данными предприятия. Слишком часто ведение журнала является запоздалой мыслью, связанной с тем, что все остальное завершено или почти завершено. Точно так же, как сантехника в вашем доме спроектирована параллельно с остальной частью дома, ваша стратегия logging должна быть центральной частью вашей архитектуры ETL.</p>
<p>Дизайн ведения журнала ETL будет отличаться в разных организациях и даже может отличаться в разных проектах одной и той же компании. Рассмотрение всех переменных &#8212; какой уровень ведения журнала требуется, кто будет его использовать и как долго его следует хранить &#8212; поможет сформировать дизайн вашей архитектуры ведения журнала ETL.</p>
<h3><strong>ETL Auditing (Аудит)</strong></h3>
<p><strong><span style="color: #ff6600;">Auditing (Аудит).</span></strong> Загрузка данных без ошибок не обязательно является успешной загрузкой. Хорошо продуманный процесс не только проверяет ошибки, но также поддерживает аудит количества строк, финансовых сумм и других показателей.</p>
<p><span>Это случается слишком часто: после того, как процесс ETL был протестирован и успешно выполнен, нет никаких дальнейших проверок, чтобы убедиться, что операция действительно сделала то, что должна была сделать. </span><span>Иногда на это уходит день, иногда — год, но в конце концов от клиента, коллеги или начальника поступает звонок: «Что не так с этими данными?» </span><span>В этот момент потребность в аудите ETL, который, к сожалению, часто рассматривается как необязательная функция, становится совершенно очевидной.</span></p>
<p>В этом совете по лучшей практике ETL я собираюсь обсудить аудит ETL и его важность в хорошо разработанной стратегии загрузки данных.</p>
<h4><strong>ETL Аудит</strong></h4>
<p><span>Начнем с определения аудита ETL. Аудит в процессе извлечения, преобразования и загрузки предназначен для достижения следующих целей:</span></p>
<ul>
<li><span>Проверка наличия аномалий в данных, помимо простой проверки серьезных ошибок.</span></li>
<li><span>Захват и хранение электронного следа любых существенных изменений, внесенных в данные во время преобразования.</span></li>
</ul>
<p><span>Если процесс ETL — это автомобиль, то аудит — это страховой полис. Аудит ETL помогает подтвердить отсутствие аномалий в данных даже при отсутствии ошибок. Хорошо продуманный механизм аудита также повышает целостность процесса ETL, устраняя двусмысленность в логике преобразования путем перехвата и отслеживания каждого изменения, вносимого в данные по пути. Есть некоторые общие черты поведения аудита и линии передачи данных.</span></p>
<h4>Проверка аномалий данных</h4>
<p><span>Допустим, вы загружаете данные из OLTP в хранилище данных с помощью своего любимого инструмента ETL. Эта конкретная загрузка извлекает 1,5 миллиона строк из источника OLTP. По пути он проходит несколько шагов преобразования и успешно завершает все свои задачи, загружая данные в пункт назначения. Однако быстрая проверка места назначения показывает, что было загружено только 1 499 990 строк. Что случилось с теми недостающими 10 строками данных?</span></p>
<p><span>Вот небольшой грязный секрет, который существует в программном обеспечении ETL: относительно легко просто потерять данные. Даже в таком инструменте ETL как </span><a href="https://msdn.microsoft.com/en-us/library/ms141026.aspx" target="_blank" rel="noopener"><span>SSIS</span></a><span>, не так уж сложно настроить пакет, который позволяет данным попадать в битовое ведро (bit bucket) без каких-либо предупреждений или ошибок. А обновить данные — возможно, неправильно — даже проще, чем просто потерять данные. Это не дисфункция программного обеспечения, а функция его гибкости. Инструмент ETL не сможет долго продержаться на рынке, если он не позволит разработчикам сгибать, изменять форму и преобразовывать данные неортодоксальными способами. Эта гибкость связана с ответственностью за правильное использование инструментов; при плохой настройке данные могут просто исчезнуть или неправильно преобразоваться. Даже самые опытные и благонамеренные ETL-инженеры время от времени обнаруживали, что их данные где-то пошли не в ту сторону.</span></p>
<p><span>Противоядием от этого является проверка данных на наличие несоответствий, даже если ошибок не обнаружено. Даже в самых элементарных архитектурах ETL можно проверить несколько высокоуровневых метрик, чтобы убедиться, что загружены именно те данные, которые ожидались. Как минимум, критически важные процессы ETL должны проверять следующее, чтобы убедиться, что входные данные соответствуют выходным:</span></p>
<ul>
<li><span>Общее количество строк</span></li>
<li><span>Совокупные итоги (которые могут включать финансовые суммы или другие сводные данные)</span></li>
</ul>
<p><span>Некоторые процессы потребуют более тщательного аудита. Те, кто, как и я, когда-либо тратили время на перемещение и преобразование данных главной бухгалтерской книги, подтвердят, что даже подсчета строк и финансовых сумм недостаточно; обеспечение того, чтобы конечный баланс соответствовал начальному балансу плюс все транзакции за этот период. В других случаях может потребоваться проверка, чтобы убедиться, что данные находятся в разумных пределах.</span></p>
<p><span>Последнее замечание по проверке аномалий данных: не забывайте проверять случаи, когда данные не загружены. Это случается чаще, чем вы думаете. Исходный файл данных, не содержащий данных, неправильно сконфигурированный запрос, не возвращающий строк, или пустой исходный каталог, предназначенный для хранения одного или нескольких файлов, — все это может привести к успешному выполнению процесса ETL, но загрузке ровно нулевых строк данных. Бывают случаи, когда это уместно, в частности, при выполнении инкрементальной загрузки данных, которые могли измениться или не измениться. Однако, если данный процесс всегда должен приводить к загрузке ненулевого числа строк, обязательно добавьте шаг аудита, чтобы проверить это.</span></p>
<h4><strong>Журнал изменений скриптов трансформации данных</strong></h4>
<p><span>Разработчики ETL имеют значительные возможности для изменения данных. Часть «T» ETL подразумевает, что создаваемые нами процессы будут обновлять данные из их исходного состояния. Когда возникают проблемы с ETL-нагрузками, они очень часто коренятся в этих преобразованиях: сталкиваются бизнес-правила, процессы очистки, дедупликации и другие настройки, что приводит к неожиданному выводу данных. </span></p>
<p><span>Слишком часто процессы ETL превращаются в черные ящики, понятные только их создателю, с малой прозрачностью в отношении того, что происходит внутри.</span></p>
<p><span>Когда данные изменяются процессом ETL, должна быть запись об этом изменении. Это может быть столь же общим, как публикация для потребителей данных списка бизнес-правил и других преобразований, которые применяются к данным по мере их перемещения по цепочке ETL. </span></p>
<p><span>В некоторых случаях это включает в себя тщательную регистрацию каждого изменения, которое происходит в границах ETL, фиксируя картину данных до и после каждого изменения. Глубина этой регистрации зависит от многих факторов:</span></p>
<ul>
<li><span>Насколько критичен этот процесс?</span></li>
<li><span>Сколько преобразований выполняется с данными?</span></li>
<li><span>Насколько сложно неспециалисту понять, какие изменения происходят по замыслу в процессе ETL?</span></li>
<li><span>В какой степени эти данные регулируются </span><a href="http://www.hhs.gov/hipaa/" target="_blank" rel="noopener"><span>HIPAA</span></a><span> , </span><a href="http://www.soxlaw.com/" target="_blank" rel="noopener"><span>SOX</span></a><span> или другими правилами?</span></li>
</ul>
<p><span>Фиксация преобразующих изменений в процессе ETL делает процесс более прозрачным и заслуживающим доверия и может защитить разработчика ETL, когда возникают вопросы о том, что было изменено, когда и почему.</span></p>
<h4><strong>Построение системы аудита ETL</strong></h4>
<p><span>Способы добавления аудита в существующий процесс ETL сильно различаются в зависимости от используемой платформы и требуемого объема аудита. В большинстве программных пакетов ETL есть инструменты, которые могут помочь в процессе регистрации, а некоторые сторонние поставщики программного обеспечения предлагают компоненты и платформы аудита. Иногда в этом может помочь и само ядро ​​базы данных: и </span><a href="https://msdn.microsoft.com/en-us/library/cc645937.aspx" target="_blank" rel="noopener"><span>SQL Server</span></a><span> , и </span><a href="https://docs.oracle.com/cd/B28359_01/server.111/b28313/cdc.htm" target="_blank" rel="noopener"><span>Oracle</span></a><span> предлагают функции сбора измененных данных для отслеживания всех операций вставки, обновления и удаления в отслеживаемых таблицах.</span></p>
<p><span>Независимо от того, является ли ваша архитектура ETL простой, как набор пакетных файлов, выполняющих операторы SQL, или сложной, как сотни или тысячи вложенных пакетов SSIS, добавление логики аудита достижимо. Даже при наличии программного обеспечения, специально созданного для аудита ETL, считается, что подход, который работает лучше всего заключается в настройке логики аудита для каждого процесса. С аудитом сложно справиться с помощью шаблонного подхода (даже в большей степени, чем с </span><span>логированием</span><span>), и то, что вы получаете в удобстве, дорого обходится в гибкости.</span></p>
<p><span>Можно проводить аудит процессов ETL в индивидуальном порядке, не изобретая каждый раз велосипед. Я держу под рукой общий набор определений таблиц и поддерживающую логику, чтобы сократить путь к следующим целям аудита:</span></p>
<ul>
<li><span>Простой совокупный аудит количества строк, финансовых данных и других ключевых показателей.</span></li>
<li><span>Шаблоны документации для сопоставления источника и цели и логики преобразования</span></li>
<li><span>Облегченный аудит изменений на уровне пакетов</span></li>
<li><span>Полный аудит каждого изменения, внесенного в процессе трансформации</span></li>
</ul>
<p><span>В зависимости от формы и типа данных, потребностей бизнеса, а также политик и правил, касающихся изменения данных, используется один или несколько, а иногда и все четыре вышеперечисленных дизайна в процессах ETL. Там, где вы можете, найдите воспроизводимые шаблоны, которые можно использовать в нескольких процессах, но не поддавайтесь привычке копировать и вставлять логику. Почти каждый процесс потребует различного уровня аудита.</span></p>
<h4><strong>Вывод</strong></h4>
<p><span>Аудит процессов ETL часто считается роскошью, несущественной необходимостью, которую можно добавить, если позволяет время. </span><span>Однако пропуск этого критического элемента хорошо спроектированной архитектуры ETL почти всегда приведет к трениям или путанице в отношении того, как и почему данные выглядят именно так. </span><span>Аудит ETL редко является наиболее заметным элементом архитектуры, но это необходимый страховой полис для защиты целостности данных и процесса.</span></p>
<h3><strong>Data Lineage (Линия данных или Наследование данных ETL)</strong></h3>
<p><span style="color: #ff6600;"><strong>Data Lineage (Линия данных).</strong></span> Понимание того, откуда берутся данные, когда они были загружены и как они были преобразованы, крайне важно для целостности последующих данных и процесса их перемещения.</p>
<p><span>Прежде чем я начал свою техническую карьеру более полутора десятилетий назад, я несколько лет работал в правоохранительных органах. В этой области одной из вещей, которую нужно быстро усвоить, является концепция цепочки хранения доказательств. Мы должны были следовать многочисленным процедурам, чтобы убедиться, что улики не просто собраны и сохранены, но полностью задокументированы в отношении того, когда и где они были собраны, кто, когда и по какой причине завладел ими. Эти процессы, хотя и жесткие и трудоемкие, помогли создать необходимый след документации для защиты как доказательств, так и тех, кто ими владеет. Хотя нечасто ставилась под сомнение целостность доказательств, наличие хорошо задокументированной цепи хранения устранило бы двусмысленность в отношении того, откуда взялись доказательства и кто мог иметь к ним доступ.</span></p>
<p><span>Я нахожу параллель между цепочкой хранения доказательств и необходимостью фиксировать происхождение данных во время процессов перемещения и преобразования. Данные могут передаваться из одной системы в другую или даже между процессами в одной системе много раз в течение одного цикла загрузки. Данные могут поступать из нескольких систем одновременно, часто быстро и параллельно. В некоторых случаях сама загрузка ETL может генерировать новые данные. Несмотря на все это, мы все еще должны быть в состоянии ответить на два фундаментальных вопроса: </span><em><span>откуда взялись эти данные и как они сюда попали</span></em><span> ?</span></p>
<p><span>В мире данных шаблон проектирования линии передачи данных ETL — это наша цепочка поставок. В этом совете </span><span>ETL Best Practices</span><span>  я расскажу о важности происхождения данных ETL и продемонстрирую некоторые советы по проектированию, как добавить это в ваши новые и существующие процессы.</span></p>
<h4><strong>ETL Data Lineage</strong></h4>
<p>Почему важна линия передачи данных?</p>
<ul>
<li>Он укрепляет доверие к данным, разъясняя происхождение данных</li>
<li>Упрощает процесс устранения неполадок, позволяя отслеживать данные на уровне строк</li>
<li>Снижает риск потери данных ETL, делая «дыры» в процессе более заметными</li>
<li>Обеспечивает лучшую видимость бизнес-правил, которые в противном случае были бы скрыты в процессе загрузки ETL</li>
</ul>
<p>Концепция происхождения данных относительно проста: построить процессы ETL таким образом, чтобы можно было проследить одну строку данных до источника, откуда они пришли и как они пришли сюда. Достаточно просто как шаблон дизайна, верно? Однако «простое» не означает «простое», и в результате я обнаружил, что большинство процессов ETL не определяют четкую линию данных. Правильное построение и тестирование элементов отслеживания происхождения данных требует времени и усилий. Требуются положения в самих данных &#8212; некоторые ключи или ключи, позволяющие отслеживать данные из исходного источника в конечный пункт назначения, &#8212; а также тщательная документация процессов, через которые они проходят, чтобы туда попасть. В большинстве случаев установление происхождения данных также включает в себя аудит изменений, которые происходят на различных этапах ETL.</p>
<h4><strong>Относительная и Абсолютная Линия Данных</strong></h4>
<p>Существует два варианта построения линии данных ETL: либо отследить каждую строку до ее исходного значения, используя первое доступное значение ключа (абсолютное происхождение), либо для процесса ETL с несколькими шагами настройте каждую таблицу так, чтобы каждый row будет иметь указатель на ключ из таблицы, которая непосредственно предшествовала этому процессу загрузки (относительное происхождение). Первый шаблон лучше подходит для более простых установок, когда есть только одна или две фазы (или шлюзы) ETL-преобразования, и прохождение данных от одного шлюза к другому является четким и однозначным. Однако модель абсолютного происхождения данных легко перерастает, что требует перехода к относительной модели происхождения данных.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/Absolute_Relative_Data_Lineage_ETL.jpg"><img decoding="async" class="aligncenter size-full wp-image-1499" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/Absolute_Relative_Data_Lineage_ETL.jpg" alt="" width="989" height="531" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/Absolute_Relative_Data_Lineage_ETL.jpg 989w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/Absolute_Relative_Data_Lineage_ETL-300x161.jpg 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/Absolute_Relative_Data_Lineage_ETL-768x412.jpg 768w" sizes="(max-width: 989px) 100vw, 989px" /></a></p>
<p>Как показано в приведенной выше модели, модель относительного происхождения данных является немного более сложной, требующей обхода нескольких шлюзов для определения происхождения конкретной строки. Тем не менее, относительная модель происхождения данных также гораздо легче масштабируется и упрощает процесс отслеживания нетипичных моделей нагрузки (например, таких, когда один из этапов в процессах ETL может генерировать новые данные без соответствующей строки из источника).</p>
<h4><strong>Как выглядит Data Lineage?</strong></h4>
<p>Давайте установим конкретный пример этого. Знакомый сценарий: клиент отправляет нам данные с помощью Excel. Ниже приведен фрагмент этого файла данных.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_snippet_of_this_data_file.jpg"><img decoding="async" class="aligncenter size-full wp-image-1500" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_snippet_of_this_data_file.jpg" alt="" width="827" height="144" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_snippet_of_this_data_file.jpg 827w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_snippet_of_this_data_file-300x52.jpg 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_snippet_of_this_data_file-768x134.jpg 768w" sizes="(max-width: 827px) 100vw, 827px" /></a></p>
<p>Быстрый взгляд показывает некоторые очевидные закономерности в этих данных:</p>
<ul>
<li>В этом файле представлены две разные категории данных: демография пациентов и детали транзакций.</li>
<li>Существует уникальный ключ уровня строки. PatientID специфичен для пациента, но у нас есть дублированные значения для пациента «Уэйн, Брюс»</li>
<li>Грязно. Имена появляются в двух разных форматах.</li>
<li>Это неполно Количество отсутствует в одной строке, а в другой отсутствует Итоговая строка и Новый баланс.</li>
<li>У него есть запись Джона Доу. Возможно, это потребует особой обработки?</li>
</ul>
<p>Одна из основ происхождения данных &#8212; наличие одного или нескольких полей, обеспечивающих уникальность на уровне строк. В этом случае у нас нет таких полей из источника, поэтому нам нужно будет создать свои собственные в этом случае. Даже в тех случаях, когда поле (или комбинация полей), по-видимому, обеспечивает уникальность на уровне строк, я рекомендую вам не поддаваться искушению использовать естественный уникальный ключ (ключи) для целей происхождения данных. Хотя он может сохранить дополнительный столбец, пропуская суррогатный уникальный ключ, в ряде случаев использование естественных ключей может вызвать проблемы: заполнение одной и той же таблицы из нескольких источников потенциально перекрывающимися значениями; непреднамеренные повторяющиеся значения ключей, когда ни один из них не ожидается процессом ETL; и <a href="http://www.kimballgroup.com/2008/09/slowly-changing-dimensions-part-2/">тип 2 медленно меняющиеся размеры</a>где дублирование бизнес-ключей ожидается в соответствии с замыслом. Для использования суррогатного уникального ключа требуется немного больше усилий и дополнительное пространство для хранения, но преимущества намного перевешивают затраты.</p>
<p>При создании идентификаторов строк на уровне таблицы лучше всего работает целое число (целое число 4 или 8 байтов). Чтобы поместить эти данные в таблицу базы данных, я бы создал дополнительный столбец в виде автоматически увеличивающегося целочисленного значения, которое в большинстве систем баз данных упоминается как значение идентификатора, чтобы обеспечить привязку на уровне строк для уникальности и отслеживания происхождения данных. Ниже я показываю промежуточную таблицу, используемую для получения данных из файла выше. Обратите внимание, что на данный момент я не вносил изменений в схему, за исключением добавления этого нового столбца идентификаторов (SourceRowID) и столбца ETLID для отслеживания идентификатора операции ETL, которая обработала загрузку (подробнее об этом позже).</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_2.jpg"><img decoding="async" class="aligncenter size-full wp-image-1501" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_2.jpg" alt="" width="785" height="141" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_2.jpg 785w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_2-300x54.jpg 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_2-768x138.jpg 768w" sizes="(max-width: 785px) 100vw, 785px" /></a></p>
<p>Новый столбец SourceRowID теперь будет использоваться для целей происхождения данных.</p>
<p>В большинстве корпоративных систем ETL данные проходят через несколько шлюзов для изменения, очистки и стандартизации данных. В случае вышеупомянутой выборки данных первый элемент преобразования будет состоять в том, чтобы разделить две части данных &#8212; пациента и элемент оплаты &#8212; на отдельные выходные таблицы. Вывод позиции начисления проще, поскольку показанный образец данных соответствует ровно одному элементу начисления на строку данных. Простой захват этих элементов, специфичных для элементов начислений, вместе с вновь добавленными метаданными происхождения данных приводит к таблице вывода элементов начислений, аналогичной приведенному ниже примеру.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_3.jpg"><img decoding="async" class="aligncenter size-full wp-image-1502" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_3.jpg" alt="" width="594" height="136" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_3.jpg 594w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_3-300x69.jpg 300w" sizes="(max-width: 594px) 100vw, 594px" /></a></p>
<p>Как показано, перемещение данных элемента начисления в его собственную таблицу сохраняет строки, относящиеся к отдельным позициям начисления, а также значение SourceRowID, сгенерированное, когда данные попали в исходную промежуточную таблицу выше. В этой таблице я также добавил поле идентификации ChargeItemKey, которое однозначно идентифицирует каждый элемент начисления. Поле ChargeItemKey не является обязательным для этого дизайна, но я обычно использую столбец идентификаторов в каждой новой таблице в стробированном дизайне ETL &#8212; особенно, когда данные изменяются при прохождении через эти ворота. Использование этого шаблона создания нового суррогатного идентификатора для каждой таблицы также поддерживает гибкий шаблон относительного происхождения данных, упомянутый выше.</p>
<p>Работа с информацией о пациенте из исходного файла данных немного сложнее, чем элементы оплаты. Поскольку в данных есть известные дубликаты, перемещение данных в таблицу с детализацией на уровне пациента потребует некоторой дедупликации. Существует много методов для выполнения дедупликации, поэтому я сохраню специфику этой операции для другого дня. После дедупликации мы получаем таблицу подготовки пациентов, которая выглядит примерно так.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_4.jpg"><img decoding="async" class="aligncenter size-full wp-image-1503" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_4.jpg" alt="" width="510" height="134" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_4.jpg 510w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_example_data_lineage_4-300x79.jpg 300w" sizes="(max-width: 510px) 100vw, 510px" /></a></p>
<p>Как и прежде, специфичные для зерна поля передаются в новую таблицу пациентов. SourceRowID сохраняется как указатель на исходные данные, сохраняя происхождение данных. Поскольку эти ворота также управляли дедупликацией записей о пациентах, выходные данные представляют собой пять строк, а не шесть, показанные в оригинале. Обратите внимание, что процесс дедупликации в этом примере явно не отслеживает запись пациента для SourceRowID 2 (дубликат пациента «Уэйн, Брюс»), так как данные уровня пациента были свернуты в строку, помеченную SourceRowID 1. В некоторых При планировании линий данных ETL может возникнуть необходимость отслеживать строки, которые намеренно отбрасываются из-за дедупликации. Вот где может пригодиться хорошая стратегия аудита ETL , отслеживая те строки, которые приносятся в жертву дедупликации и другим бизнес-правилам.</p>
<p>Этот относительно тривиальный пример показывает краткое описание конструкции, в которой уникальный идентификатор строки создается и сохраняется на протяжении двух этапов ETL. Очевидно, что состояние этих данных, скорее всего, будет и дальше меняться: очистка данных будет выполняться по формату столбца с именем, столбцы с нулевыми числами, скорее всего, должны быть очищены, а запись Джона Доу имеет некоторые недостатки (нет AccountStatus или Значения ChargeEvent), которые могут потребовать либо создания значения, либо перенаправления всей строки для сортировки. Независимо от того, имеет ли этот процесс два шлюза или двадцать, один и тот же шаблон происхождения данных ETL будет по-прежнему оставаться верным: каждая строка должна быть прослеживаемой до своего происхождения либо напрямую (через абсолютное происхождение), либо косвенно (используя относительное происхождение).</p>
<h4><strong>Отслеживание процесса ETL</strong></h4>
<p>При реализации линии данных я почти всегда добавляю также идентификаторы линии процесса ETL. Эти идентификаторы процесса, представленные в приведенном выше примере в столбце ETLID, идентифицируют экземпляр выполнения процесса ETL, который загрузил данные. Как показано выше, эти идентификаторы отличаются от одной таблицы к другой, но дублируются в каждой таблице. Это по замыслу; все строки, вставленные или обновленные в данной таблице в одном и том же цикле ETL, будут совместно использовать значение идентификатора ETL, и в большинстве случаев эти идентификаторы ETL являются специфическими для каждой загрузки таблицы. Отслеживание происхождения линии на уровне, а также идентификаторов операций ETL помогает создать электронный след, показывающий путь, по которому каждая строка данных проходит через конвейер ETL.</p>
<h4><strong>заявка</strong></h4>
<p>Все ли процессы ETL требуют отслеживания происхождения данных? Нет. Меньшие, менее сложные процессы ETL могут не требовать того же уровня (если вообще) отслеживания происхождения, который был бы обнаружен при большой загрузке хранилища данных с несколькими шлюзами. Больше гейтов и / или преобразований, которые происходят во время ETL, увеличат потребность в полном отслеживании линии передачи данных. В случае сомнений, я рекомендую потратить дополнительное время на встраивание происхождения данных ETL в ваш конвейер данных. Лучше иметь это и не нуждаться в этом, чем наоборот.</p>
<h4><strong>Вывод</strong></h4>
<p>Отслеживание происхождения данных ETL &#8212; это необходимый, но, к сожалению, недостаточно используемый шаблон проектирования. Правильная идентификация линии передачи данных помогает создать более надежный и надежный процесс ETL, который легче контролировать, проще устранять неисправности и более понятен в своей работе.</p>
<h3><strong>ETL Modularity (ETL Модульность)</strong></h3>
<p><span style="color: #ff6600;"><strong>ETL Modularity (ETL Модульность).</strong></span> Создание многократно используемых структур кода важно в большинстве областей разработки, и особенно в процессах ETL. Модуляризация ETL помогает избежать многократного написания одного и того же сложного кода и уменьшает общие усилия, необходимые для поддержки архитектуры ETL.</p>
<p>Представьте на минуту, что вы создали программную вещь. На самом деле, мы будем называть это Вещи. Вы вложили много работы в The Thing, и она делает именно то, что вы хотели. Вы вводите The Thing в игру как часть более крупного решения, и после нескольких ревизий его поведение проверяется, и оно считается готовым к производству. Месяцы спустя, создавая другое программное решение, вы столкнетесь с проблемой, аналогичной той, которую вы решили с The Thing. Вы делаете копию оригинальной The Thing, настраиваете ее для этой цели и помещаете в новое решение. Повторите этот цикл несколько раз. Пять лет спустя вы смотрите вверх и понимаете, что у вас есть две дюжины адаптаций The Thing, несколько отличающихся друг от друга и разбросанных по всей ширине базы кода.</p>
<p>Так, дорогие читатели, так разрабатывается большинство решений ETL.</p>
<p>Этот дизайн, который часто приводит к десяткам &#8212; возможно, даже сотням &#8212; копий одной и той же логики, создан с благими намерениями. Мне нужно использовать Вещи здесь, я делаю копию последней Вещи и изменяю ее для этого случая использования. Это быстро решает проблему. Тем не менее, это техническое поведение, вызывающее долги, стоит гораздо дороже при длительном обслуживании, чем количество времени, сэкономленное за счет рефакторинга копии существующего фрагмента кода.</p>
<p>Это затруднение не уникально для ETL. Каждый проект по кодированию в каждой организации имеет некоторое количество целенаправленного дублирования кода. Проекты ETL, однако, кажутся особенно восприимчивыми к этой проблеме. Разработчики, архитекторы и менеджеры проектов опасаются незавидного определения лица, нарушившего фид хранилища данных, загрузку данных клиентов или отчет акционеров. Короткий путь заключается в дублировании и адаптации. Но так ли это?</p>
<p>В своей продолжающейся серии статей о лучших практиках ETL я поделюсь некоторыми соображениями о том, почему модульность ETL помогает сократить общее время разработки и затраты на владение.</p>
<h4><strong>ETL Модульность</strong></h4>
<p>Из всех шаблонов проектирования ETL, о которых я пишу, нет ни одного, который обеспечил бы большую отдачу от ваших временных затрат, чем модульность ваших процессов ETL. В двух словах, модульность ETL предполагает абстрагирование общих задач в повторно используемые единицы работы. В качестве более конкретного примера рассмотрим сценарий загрузки файла с FTP-сервера, что является обычной задачей в большинстве инфраструктур ETL. Поскольку большинство пакетов программного обеспечения ETL имеют встроенные задачи для обработки загрузок по FTP, общая схема проектирования заключается в том, чтобы включать эту задачу (с жестко заданными путями к исходному файлу и локальной папке назначения) в каждый процесс ETL, требующий загрузки по FTP. Как описано, процесс загрузки и импорта будет иметь следующий поток.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_1.jpg"><img decoding="async" class="aligncenter size-full wp-image-1505" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_1.jpg" alt="" width="693" height="534" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_1.jpg 693w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_1-300x231.jpg 300w" sizes="(max-width: 693px) 100vw, 693px" /></a></p>
<p>Этот шаблон прекрасно работает для одного процесса. Однако у вас никогда не будет только одного процесса ETL, который загружает файл с FTP. Эти вещи всегда путешествуют в стадах, так что вероятность того, что у вас есть тонна связанных задач, велика. Когда вы устанавливаете их по частям в течение месяцев или даже лет, ваши шаблоны начинают выглядеть примерно так.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_2.jpg"><img decoding="async" class="aligncenter size-full wp-image-1506" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_2.jpg" alt="" width="1024" height="256" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_2.jpg 1024w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_2-300x75.jpg 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_2-768x192.jpg 768w" sizes="(max-width: 1024px) 100vw, 1024px" /></a></p>
<p>Видишь что случилось? Мы начали с хорошего паттерна в процессе ETL A, но два других слегка различались в своих подходах, каждый из которых упускал что-то из исходного паттерна. На самом деле разработчик (и) ETL мог намеренно целенаправленно проектировать эти процессы с различным поведением. Однако в большинстве случаев это не так &#8212; разница между этими шаблонами проектирования вызвана ошибкой человека, а не намерением.</p>
<p>Модуляризация процессов ETL может помочь избежать подобных проблем. Модульная конструкция включает в себя разделение общих операций на отдельные и отдельные процессы, которые можно вызывать в общем. Эти модульные процессы параметризованы для обеспечения возможности передачи рабочих значений во время выполнения и централизованно хранятся, чтобы они были доступны и отображались для общего использования.</p>
<p>Среди преимуществ модульности процессов ETL:</p>
<ul>
<li>Стандартизированное поведение в основных функциях, а также в периферийных задачах, таких как ведение журнала и обработка ошибок</li>
<li>Уменьшите дублирующую работу в будущем развитии ETL</li>
<li>Более легкие процессы изменения</li>
<li>Более простое модульное тестирование</li>
<li>Упрощенный обмен задачами разработки между несколькими разработчиками</li>
<li>Меньшая площадь поверхности для устранения неполадок, когда что-то идет не так</li>
</ul>
<p>Создание архитектуры ETL с использованием модульных и многократно используемых компонентов требует времени и усилий для внедрения, и, как и любая другая часть программного обеспечения, со временем будет развиваться при надлежащем уходе и питании. Работа модуляризации обычно включает четыре этапа:</p>
<ul>
<li>Инвентаризация общих задач. Что может быть модульным? <a href="https://www.timmitchell.net/etl-atomicity/">Насколько большими или маленькими должны быть эти единицы работы? </a> Я не хочу упрощать работу, которая входит в этот этап, потому что решение, какие задачи можно использовать повторно, чтобы оправдать работу (и, что более важно, может быть сделано универсальным без чрезмерной сложности), требует больших усилий. Просмотр журналов прошлых выполнений, изучение возможных процессов, которые могут быть объединены, и создание прототипов &#8212; все это требуется для правильной работы.</li>
<li>Построить модульный процесс. Этот этап может быть облегчен путем повторного использования некоторых зрелых компонентов существующих процессов (если они уже существуют).</li>
<li>Выявление и вывод значений во время выполнения. Любое значение, которое может быть изменено (например, имя FTP-сервера или место загрузки в приведенном выше примере), должно быть задано как параметр времени выполнения, а не как жестко заданное значение.</li>
<li>Стандартизация использования. Этот этап в основном включает документацию и обучение и предназначен для устранения быстрых и простых (и вызывающих технический долг) жестко закодированных шагов, смоделированных выше.</li>
</ul>
<p>В приведенном выше кратком примере проектов есть две легко идентифицируемые возможности для модульности: загрузка файлов с FTP и перемещение файлов в архив. Поскольку эти типы операций очень распространены, и каждый из них включает в себя этапы ведения журнала для сбора некоторой информации об операции (всегда хорошая практика &#8212; см. Мой пост по разработке ведения <a href="https://www.timmitchell.net/etl-logging/" target="_blank" rel="noopener noreferrer">журнала ETL</a> в этой серии), оба они будут хорошими кандидатами для модульности. Инкапсулируя общее поведение и параметрируя значения, необходимые во время выполнения, следующий дизайн можно использовать повторно и намного проще в обслуживании.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_3.jpg"><img decoding="async" class="aligncenter size-full wp-image-1507" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_3.jpg" alt="" width="678" height="442" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_3.jpg 678w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Modularity_3-300x196.jpg 300w" sizes="(max-width: 678px) 100vw, 678px" /></a></p>
<p>Как показано, высокоуровневые нагрузки (процессы ETL A, B и C) блаженно не знают, что входит в загрузку с FTP или операцию архивирования файлов. Единственное, что важно для этих трех процессов &#8212; это требуемые параметры и результат каждой операции. По мере добавления новых процессов разработчики могут просто вызывать модули для загрузки по FTP и / или файлового архива по мере необходимости, без необходимости каждый раз переписывать эти фрагменты логики. Хотя этот шаблон требует дополнительной предварительной работы, усилия, необходимые для обновления модульной логики или добавления новых процессов с использованием указанной логики, намного меньше, чем поддержание множества копий одних и тех же задач ETL.</p>
<p>Последнее замечание о модульности ETL: не все может быть сделано достаточно общим, чтобы соответствовать этому шаблону. Вы заметите, что в приведенном выше примере не была предпринята попытка обобщить импорт данных плоского файла в промежуточную таблицу. Это было сделано намеренно, чтобы продемонстрировать тот факт, что некоторые компоненты ETL все еще требуют частичной разработки. Операции с потоками данных &#8212; в частности, те, которые связывают вместе метаданные из источника в место назначения &#8212; особенно сложны для модульности. Я не говорю, что это не может быть сделано, но усилия, чтобы сделать это, часто больше, чем последующая выгода. Как отмечалось ранее, одна из самых сложных задач, которые вам предстоит пройти, &#8212; это выяснить, какие операции могут быть разумно модульными, а какие &#8212; нет.</p>
<h4><strong>Вывод</strong></h4>
<p>Построение модульных процессов ETL является сложной задачей и требует дисциплины, особенно при первом запуске по пути модульности. Тем не менее, правильно разработанная модульность ETL экономит время и усилия, упрощает тестирование и устранение неполадок, а также снижает текущие расходы на операции ETL.</p>
<h3><strong>ETL Atomicity (ETL Атомность)</strong></h3>
<p><span style="color: #ff6600;"><strong>ETL Atomicity (ETL Атомность).</strong></span> Насколько большим должен быть каждый процесс ETL?</p>
<p>Я до сих пор помню первый настоящий процесс ETL, который я разработал. В то время я работал в больнице, проходя серьезную реализацию системы, когда мы заменили 17-летнюю систему на основе UNIX более современным набором медицинских приложений с серверной частью SQL Server. Мне было поручено создать, протестировать и выполнить процессы ETL для этого преобразования. Несмотря на то, что я имел опыт работы с базами данных, я все еще был новичком в мире ETL и нашего предпочтительного инструмента, SSIS. Моей первой и единственной заботой было перемещение данных как единовременной операции, поэтому я поместил все в один огромный пакет служб SSIS. В этом пакете были десятки задач, которых было слишком много, чтобы их можно было разместить на одном экране, и только метаданные для этого пакета имели размер более 5 МБ.</p>
<p>В конце концов, монолитный процесс, который я построил, сделал то, что должен был сделать. Он был разработан для одноразового использования и больше не будет вызываться после окончательной загрузки данных в новую систему. Тем не менее, я извлек некоторые ценные уроки о возможности повторного использования и тестируемости в ходе разработки этого процесса, и в результате я полностью изменил способ, которым я строил процессы ETL с этого момента. Это тот шаблон проектирования, которым я поделюсь с вами в этой части моей серии ETL Best Practices .</p>
<h4><strong>ETL Atomicity</strong></h4>
<p>Атомность &#8212; чрезмерно причудливое слово, чтобы описать разбивание вещей на отдельные части. Шаблон проектирования атомарности ETL включает в себя определение отдельных единиц работы и создание небольших и индивидуально выполняемых процессов для каждого из них. В отличие от архитектуры моего первого в истории проекта ETL, в котором вся логика содержалась в одном процессе, атомарный проект разбивает отдельные части нагрузки на более мелкие куски логики, каждый из которых может быть вызван самостоятельно. В то время как функциональные результаты двух разных шаблонов проектирования должны быть одинаковыми, атомный дизайн, состоящий из более мелких частей, а не из нескольких более крупных, делает процесс более зрелым.</p>
<p>Проект атомарности ETL требует анализа частей процесса, которые тесно связаны друг с другом, вместо того, чтобы сосредоточиться на высоком уровне на том, что должно быть сделано всем проектом в целом. Я немного говорил об этом в своем посте о модульности ETL , в котором я обсуждал абстрагирование часто используемых функций, позволяющих легко использовать их повторно. Проектирование ETL-процессов атомарно делает этот шаг еще дальше, отделяя не только части, которые могут быть повторно использованы в других нагрузках, но и выделяя любую часть нагрузки, которую, возможно, потребуется изменить, протестировать или выполнить самостоятельно.</p>
<h4><strong>Почему ETL Atomicity?</strong></h4>
<p>Существует множество преимуществ для создания небольших узкопрофильных подпроцессов, а не для монолитных пакетов «все».</p>
<p><em>Опыт тестирования и отладки</em> . Если вы когда-либо пытались выполнить модульное тестирование или отладку процесса с помощью множества движущихся частей, вы знаете, какое это может быть время. Если что-то ломается или не ведет себя должным образом, обход кода для поиска проблемной логики является излишне сложным и отнимает много времени. Разбивая нагрузку на функциональные блоки, тестирование и отладку можно выполнять индивидуально для выявления ошибок до того, как будет проведено полное интеграционное тестирование.</p>
<p><em>Техническое обслуживание</em> . Каждый процесс ETL нужно будет пересмотреть и настроить в какой-то момент. Разделяя функции на их собственные процессы, обновлять или заменять эти поведения становится легче, потому что теперь это модульная конструкция.</p>
<p><em>Разделение обязанностей по развитию</em> . Если вы работаете в среде с несколькими разработчиками, и у вас есть несколько сотрудников, работающих над одной и той же нагрузкой, процесс разработки будет намного проще, если каждый разработчик будет работать над своим назначенным подпроцессом, а не пытаться согласовать изменения в одном монолитном коде. файл. Как сторонние разработчики служб SSIS: если вы никогда не пытались использовать файл пакета служб SSIS, не делайте этого; это бесполезное упражнение. Разделите свою логику на несколько пакетов, если вы разрабатываете как часть команды.</p>
<p><em>Пользовательский интерфейс</em> . Большинство инструментов ETL имеют графический интерфейс, который может стать очень занятым, когда задействовано много движущихся частей. Кроме того, многие из них (включая мой инструмент выбора, SQL Server Integration Services) выполняют проверку во время разработки, пока вы редактируете пакеты, и наличие большого количества соединений и конечных точек может замедлить этот процесс проверки. Разделение функциональных блоков работы на отдельные подпроцессы обеспечивает более удобный и отзывчивый интерфейс.</p>
<p><em>Возможность повторного использования</em> . Как уже отмечалось, сохранение процессов ETL небольшим и сфокусированным не обязательно должно быть связано с возможностью повторного использования, но это может быть дополнительным преимуществом атомарности ETL. С более мелкими и более конкретными функциональными блоками вы сможете повторно использовать некоторые компоненты в том же процессе или даже в других процессах.</p>
<p>При использовании атомарного дизайна ETL вы обычно получаете больше кода. Но действительно ли это имеет значение? Как профессионалы в области данных, наша основная цель должна заключаться не в том, чтобы уменьшить объем кода, который мы пишем, а в том, чтобы написать максимально эффективный код. Если атомарный ETL-дизайн означает, что у вас на 20% больше кода (что является очень либеральной оценкой), вы в разы вернете свои затраты времени и памяти за счет более простого тестирования, более простого обслуживания и лучшего повторного использования.</p>
<h4><strong>Насколько маленькими должны быть эти процессы?</strong></h4>
<p>При проектировании атомарности ETL должна быть только одна движущаяся часть на процесс, или две, или десять? Как это часто бывает, ответ &#8212; <em>это зависит</em> . Я не стремлюсь к определенному размеру или количеству движущихся частей; скорее, я сосредотачиваюсь на <em>функциональной единице работы</em> . Все задачи или шаги в рамках одного процесса должны быть непосредственно связаны с другими. Оценивая отдельные этапы процесса, чтобы определить, какие (или группы) должны стоять самостоятельно, я задаю следующие вопросы:</p>
<ul>
<li>Не упростит ли это процесс тестирования, если я сам протестирую эту задачу?</li>
<li>Что касается этого процесса, нужно ли мне когда-либо выполнять эту задачу самостоятельно?</li>
<li>Будет ли этот процесс иметь логику после этой задачи, которая будет по-разному реагировать на успех или провал этой задачи?</li>
<li>Может ли логика в этой задаче быть изменена или заменена без принудительного изменения других частей процесса?</li>
<li>Может ли логика в этой задаче быть повторно использована в других частях этого процесса или других процессов?</li>
</ul>
<p>Чем больше ответов «Да» я получу выше, тем больше вероятность того, что задача или группа задач будут преобразованы в отдельный подпроцесс.</p>
<p>В качестве более конкретного примера представьте себе процесс, который будет загружать zip-файл с сайта SFTP, извлекать содержащиеся в нем файлы, обрезать набор промежуточных таблиц, загружать эти файлы в промежуточные таблицы и затем архивировать zip-файл. Учитывая вышеупомянутые краткие детали, я склоняюсь к следующему дизайну:</p>
<ul>
<li>Подпроцесс для выполнения загрузки SFTP. Я хотел бы сделать это как можно более универсальным, чтобы его могли использовать другие процессы, поскольку подключение к SFTP-серверам для обмена данными довольно часто встречается в рабочих нагрузках ETL.</li>
<li>Подпроцесс для извлечения архивных файлов. Опять же, поскольку это довольно часто встречается в операциях ETL, я бы сделал этот процесс модульным .</li>
<li>Подпроцесс для усечения промежуточных таблиц и загрузки этих таблиц с извлеченными файлами в качестве источника. Обратите внимание, что в этом подпроцессе есть две разные задачи. Это сделано намеренно, поскольку маловероятно, что мне нужно будет усекать промежуточные таблицы без последующей их перезагрузки, и я определенно не хочу загружать в изменчивые промежуточные таблицы без предварительного их усечения.</li>
<li>Подпроцесс для перемещения zip-файла в расположение архива.</li>
</ul>
<p>Как показано, это не всегда дизайн с одной задачей на подпроцесс. Группировка задач целесообразна, когда коллекция работает вместе для выполнения единой единицы работы, и когда выполнение или тестирование одного фрагмента из этой группы не добавляет ценности.</p>
<h4><strong>Связывая все вместе</strong></h4>
<p>Имейте в виду, что разделение процессов на группы тесно связанных задач не означает, что у вас все еще не может быть одного процесса, контролирующего выполнение. В атомарном процессе ETL обычно существует процесс оркестровки, который объединяет все движущиеся части для сквозной нагрузки, обеспечивая единую точку вызова для этой нагрузки. Разница между этим шаблоном и монолитом, который я описал в начале поста, состоит в том, что этот шаблон встраивает рабочую логику (где выполняется «настоящая работа») в эти подпроцессы, а процесс оркестровщика или контроллера обрабатывает поток из одного подпроцесса. другому.</p>
<h4><strong>Вывод</strong></h4>
<p>Модульность ETL облегчает задачу разработки и поддержки процессов извлечения, преобразования и загрузки. Разбивая функциональные блоки работы на индивидуально тестируемые, заменяемые и исполняемые подпроцессы, общий механизм загрузки становится более устойчивым.</p>
<h3><strong>Error Handling (Обработка ошибок)</strong></h3>
<p><span style="color: #ff6600;"><strong>Error Handling (Обработка ошибок).</strong></span> Что происходит, когда что-то идет не так? В этом разделе рассматриваются шаблоны проектирования для предотвращения и управления ошибками в процессах ETL.</p>
<p>При разработке правильной архитектуры ETL есть два ключевых вопроса, на которые необходимо ответить. Первый: «Что должен делать этот процесс?» Определение начальной и конечной точек данных, преобразований, фильтрации и других шагов должно быть выполнено, прежде чем можно будет продолжить любую другую работу. Второй вопрос, на который необходимо ответить: «Что должно произойти, если процесс завершится неудачей?» Слишком часто дизайн останавливается, не задав и не ответив на этот второй вопрос. Обработка ошибок ETL становится запоздалой мыслью, а не ключевой частью дизайна.</p>
<p>В этой части моей серии ETL Best Practices я расскажу о важности логики обработки ошибок в процессах ETL.</p>
<h4><strong>Fail-First Design</strong></h4>
<p>Правильная обработка ошибок ETL &#8212; это не то, что можно просто закрепить в конце проекта. Скорее, это должно быть частью архитектуры от первоначального дизайна. Создание логики ошибок после построения процессов ETL сродни добавлению сантехники в дом после того, как все стены уже подняты: это можно сделать, но это уродливо. Правильное управление ошибками требует, чтобы эти части разрабатывались и создавались вместе с ядром приложения ETL, а не после него. По этой причине я практикую то, что я называю <em>отказоустойчивым дизайном</em> . В этом проекте я уделяю одинаковое внимание тому, что происходит, когда нагрузка идет правильно или неправильно. Этот подход занимает больше времени, но он также обеспечивает более надежное и предсказуемое поведение.</p>
<h4><strong>Обработка ошибок ETL</strong></h4>
<p>Управление логикой ошибок в процессах ETL &#8212; это широкая тема, но ее можно разбить на следующие подходы.</p>
<ul>
<li>Предотвращение ошибок: исправить или обойти условие ошибки, чтобы остановить процесс сбоя.</li>
<li>Реакция на ошибку: когда сбой неизбежен, критически важно правильно реагировать на ошибку.</li>
</ul>
<p>Чтобы быть понятным, управление условиями отказа не означает, что вы должны выбрать один из двух вышеуказанных подходов. Эффективные архитектуры ETL обычно включают в себя как предотвращение, так и реагирование, формируя двусторонний подход к управлению ошибками. Я расскажу о каждом из этих подходов ниже.</p>
<h4><strong>Предотвращение ошибок</strong></h4>
<p>Существуют некоторые условия, которые вызывают сбои в процессах загрузки, которые можно предотвратить с помощью логики обработки ошибок ETL. Среди случаев, когда предотвращение ошибок полезно:</p>
<ul>
<li>Процесс загрузки состоит из нескольких этапов, но один сбой не должен прерывать остальную нагрузку</li>
<li>В некоторых частях данных существует известный недостаток, который можно исправить как часть процесса ETL</li>
<li>Некоторая часть процесса ETL является нестабильной, и вам необходимо повторить попытку в случае сбоя</li>
</ul>
<p>Первый пункт в списке выше &#8212; это наиболее распространенный сценарий, в котором предотвращение ошибок полезно. Допустим, вы выполняете операции ETL, собирая данные о розничных продажах по всему миру и в каждом часовом поясе. Для загрузки в одном часовом поясе могут быть торговые точки, данные которых еще не доступны (магазин оставался открытым поздно, задержки в сети и т. Д.). Этот сценарий не обязательно представляет ошибку, просто задержка в обработке. В этом примере бизнес-загрузка имеет смысл при загрузке доступных данных, пропуская источники, которые еще не готовы. В таком случае, как правило, допускается сбой отдельных задач без прерывания процесса ETL, а затем сбой процесса в целом после выполнения всех задач. Процесс может попытаться выполнить все задачи загрузки, завершившись с ошибкой только в случае сбоя одного или нескольких отдельных шагов.</p>
<p>Хотя предотвращение ошибок является полезным инструментом в вашем наборе трюков ETL, позвольте мне призвать вас не подавлять условия ошибок просто для того, чтобы заставить ваши процессы ETL успешно работать. Хотя это, как правило, имеет хорошие намерения, оно может вызвать некоторые неожиданные проблемы, если не будет сделано должным образом. То, что ошибку можно предотвратить, не означает, что она должна быть! Предотвращение ошибок часто является решением бизнес-логики, а не техническим. Прежде всего, убедитесь, что любое предотвращение или подавление ошибок решает <em>деловую</em> проблему под рукой.</p>
<h4><strong>Ответ об ошибке</strong></h4>
<p>Не все ошибки ETL должны быть предотвращены. Фактически, большинство бизнес-случаев поддается ошибочному реагированию, а не предотвращению. Как бы странно это ни звучало, есть смысл в том, чтобы позволить процессам ETL не работать:</p>
<ul>
<li>Управление зависимостями: если шаг B зависит от успеха шага A, то шаг B не должен выполняться в случае сбоя A.</li>
<li>Отчет об ошибках: часто уведомления запускаются из-за ошибок. Разрешение сбоя процессов обеспечивает выполнение этих уведомлений.</li>
<li>Триггеры ошибок: задачи, которые не выполняются, могут инициировать логику ответа об ошибках для дополнительных уведомлений, операций очистки и т. Д.</li>
</ul>
<p>Именно в дизайне ответа на ошибку я свободно использую фразу, <em>изящно терпящую неудачу</em>, При разработке процессов, которые построены так, что они терпят неудачу, вы должны учитывать, как что-то может пойти не так, и решить, что должно произойти, когда это произойдет. Для многих процессов изящный сбой &#8212; это просто сбой без других действий. Рассмотрим пример процесса, который загружает энергозависимую промежуточную таблицу. Обычно это включает усечение этой таблицы с последующей перезагрузкой этой таблицы. Если произойдет сбой этого процесса, очистить нечего &#8212; просто исправьте недостаток и повторите последовательность усечения / перезагрузки. Однако при загрузке данных транзакций в рабочую таблицу дело обстоит иначе. Если эта транзакционная нагрузка завершится неудачей на полпути, вы получите частично загруженную целевую таблицу. Вы не можете просто перезапустить процесс, чтобы избежать дублирования транзакций. В таком случае,</p>
<p>В некоторых случаях можно прогнозировать сбой и реагировать соответствующим образом. Некоторые инструменты ETL, включая мой любимый такой инструмент (SSIS), включают функциональность для проверки возможных сбоев перед выполнением. В службах SSIS вы можете запустить проверку пакета без фактического выполнения указанного пакета. Хотя этот процесс проверки не обнаруживает все возможные ошибки, он проверяет некоторые общие точки ошибок. Другие этапы проверки можно выполнить вручную, например, проверить, существует ли каталог или есть ли у учетной записи выполнения разрешение на загрузку.</p>
<p>При разработке логики реагирования на ошибки обязательно определите гранулярность. Хотя обычно мы говорим об управлении ошибками на уровне задач, можно управлять ошибками на уровне строк. Управление ошибками на уровне строк обычно классифицируется как операция качества данных, а не как управление ошибками. Однако, поскольку одна неверная строка данных может прервать успешную загрузку, она становится частью этого домена. При выборе стратегии управления ошибками на уровне строк дизайн становится более сложным: <em>что мы делаем с плохими строками данных? Должен ли определенный процент неверных данных вызывать сбой всей нагрузки? </em>При реализации такого дизайна должна быть деловая ценность в загрузке хороших данных, в то время как пропуск (или загрузка в сортировку) плохих данных.</p>
<p>Детали логики ответа на ошибку будут разными для каждого процесса. Опять же, это часто деловые решения, а не технические. В конечном счете, дизайн любого процесса загрузки ETL должен включать в себя обеспечение операций после сбоя. Используя конструкцию с первым отказом, предположим, что каждый процесс ETL завершится с ошибкой, и выполните сборку соответствующим образом.</p>
<h4><strong>Сбой рано, если это возможно</strong></h4>
<p>При прочих равных условиях лучше потерпеть неудачу рано, чем поздно в процессе. Ранний сбой позволяет избежать ненужных накладных расходов, если весь процесс придется перезапускать в случае сбоя. Неудача раньше, чем позже, также снижает вероятность необходимости очистки данных после сбоя. Есть случаи, когда поздние неудачи неизбежны (или даже предпочтительнее). Тем не менее, для большинства сценариев загрузки ETL это правило остается верным: по возможности <em>сбой рано</em> .</p>
<h4><strong>логирование</strong></h4>
<p>Редко я пишу пост о ETL, в котором нет напоминания о регистрации . Нигде логирование не является более важным, чем в дизайне обработки ошибок. Если ваш процесс ETL ничего не делает после сбоя, как минимум, он должен регистрировать детали сбоя. Сбор информации о сбоях очень важен для улучшения сортировки и архитектуры. Это вдвойне верно, если ваш процесс ETL подавляет или предотвращает ошибки. Единственный механизм, который дает вам историческое понимание логики ошибок, &#8212; это хорошая подсистема журналирования. Независимо от того, используете ли вы инструменты, встроенные в ваше программное обеспечение ETL, или пишете собственные, убедитесь, что вы собираете достаточно информации для регистрации, чтобы полностью документировать любые и все сбои.</p>
<h4><strong>Логика ошибок тестирования</strong></h4>
<p>Ранее я отмечал, что логика ошибок часто является запоздалой мыслью. Это еще более верно для проверки логики ошибок. Построение тестов на основе логики предотвращения ошибок и ответов так же важно, как тестирование логики загрузки ядра. Я даже не могу вспомнить, сколько раз мне звонили, чтобы помочь с процессами ETL, чтобы выяснить, что не только сбой загрузки, но и логика ошибок тоже. Тестирование процессов загрузки является сложным, а тестирование обработки ошибок ETL еще более. Однако только правильное тестирование обнаружит недостатки в вашей логике ошибок.</p>
<h4><strong>Вывод</strong></h4>
<p>Управление ошибками в ETL должно занимать центральное место в разработке этих процессов. У хорошей стратегии ETL будут меры по предотвращению и реагированию на ошибки при правильной детализации. Благодаря хорошо спроектированной обработке ошибок ETL процессы становятся более надежными, предсказуемыми и обслуживаемыми.</p>
<h3><strong>Managing Bad Data (Управление неверными данными)</strong></h3>
<p><span style="color: #ff6600;"><strong>Managing Bad Data (Управление неверными данными).</strong></span> Когда обнаружены подозрительные данные, должна срабатывать система для очистки или иного реагирования по устранению несоответствующих строкам данных. В этой статье я поделюсь некоторыми шаблонами проектирования для обработки неверных данных.</p>
<p>В последнем посте из моей продолжающейся серии статей о передовых практиках ETL я обсуждал важность обработки ошибок в процессах ETL , рассматривал передовые практики для потока приложений для предотвращения или постепенного восстановления после систематической ошибки или аномалии данных. В этой статье я углублюсь в эту тему, чтобы изучить шаблоны проектирования для управления неверными данными в процессах ETL.</p>
<h4><strong>Что такое плохие данные?</strong></h4>
<p><em>Плохой</em> &#8212; это субъективный термин, и, соответственно, <em>плохие данные</em> . Следовательно, не существует единого неопровержимого определения неверных данных; она может и будет отличаться от одной организации к другой и от одного процесса ETL к другой. Тем не менее, вот общее руководство, которому я следую:</p>
<blockquote><p><em>Неверные данные &#8212; это данные, происхождение или точность которых являются подозрительными, и в результате риск их использования превышает потенциальную ценность для бизнеса.</em></p></blockquote>
<p>То, что считается плохими данными, будет широко варьироваться. При загрузке списка контактной информации для потенциальных потенциальных покупателей возможны пропущенные или неверные значения данных, которые, скорее всего, не являются дисквалифицирующим атрибутом. С другой стороны, при загрузке финансовых данных отсутствующее или недействительное значение для одной строки может сделать подозрительной всю загрузку данных. Точно так же происхождение данных может поставить под сомнение их значение (для любой загрузки в проверяемую систему) или может не оказать большого влияния (например, при расчете анализа настроений).</p>
<p>Часто первая и самая большая проблема при построении архитектуры ETL &#8212; решить, какие данные являются плохими. В конечном счете, бизнес-потребности &#8212; не обязательно технические требования &#8212; должны руководствоваться этой логикой.</p>
<p>Последний пункт определения границ неверных данных: это не всегда двоичное решение. На самом деле, большинство таких оценок являются «успешными / неудачными», но иногда возникает необходимость получить более детальную оценку качества данных. Создавайте эти относительные оценки качества данных, только если это необходимо; каждое создаваемое вами ведение увеличивает сложность и затраты на обслуживание.</p>
<h4><strong>Определение гранулярности</strong></h4>
<p>Определение гранулярности неправильной обработки данных обычно означает выбор одного из двух вариантов: строка за строкой или нагрузка в целом.</p>
<h4><strong>Управление подозрительными данными построчно</strong></h4>
<p>Обработка подозрительных данных обычно представляет собой построчную операцию. Из этих двух шаблонов проектирования обработка некорректных данных по очереди является гораздо более распространенным и более простым подходом. Используя этот подход, процесс ETL отфильтрует каждую подозрительную строку данных на основе критериев, установленных на предыдущем этапе, а затем очистит, перенаправит или удалит (подробнее об этих параметрах позже) каждую из этих строк.</p>
<h4><strong>Управление данными как нагрузка &#171;все или ничего&#187;</strong></h4>
<p>Существуют бизнес-кейсы, которые требуют подхода на уровне загрузки к неверным данным, когда весь процесс загрузки проходит успешно или завершается неудачей как единое целое. В этой схеме даже один подозрительный ряд данных среди миллионов может сделать недействительной всю нагрузку. Архитектура «все или ничего» требует механизма отката или удаления, который автоматически срабатывает в случае сбоя.</p>
<p>Прекрасным примером этого является процесс ETL, загружающий записи главной книги. В таких нагрузках исключение хотя бы одной строки данных из-за проблем с качеством данных может нарушить баланс всей нагрузки. Здесь лучше вообще не загружать данные, чем иметь частичный (и, следовательно, неверный) набор данных, записанных в место назначения.</p>
<p>Архитектура загрузки «все или ничего» более сложна, чем их построчная обработка ошибок. Используйте этот шаблон проектирования только в том случае, если этого требуют деловые или технические потребности; если есть сомнения, обработайте ошибки или другие аномалии на уровне строк.</p>
<h4><strong>Управление неверными данными в ETL</strong></h4>
<p>Как только определение неверных данных и детализация согласованы, следующим этапом является разработка тактического подхода к управлению неверными данными в ETL.</p>
<p>Хотя детали обработки неверных данных будут очень техническими, всегда имейте в виду, что деловые потребности должны определять поведение. Первой и главной проблемой при обработке неверных данных всегда должно быть влияние на бизнес.</p>
<h4><strong>Очистить в ETL</strong></h4>
<p>При обнаружении неверных данных используйте процесс ETL для очистки и продолжения обработки этих данных, если это возможно. Устранение недостатков данных в полете обычно имеет наименьшее количество остаточного багажа. Подозреваемые данные, которые могут быть очищены встроенными средствами, не страдают от задержки отдельного процесса (или, что еще хуже, вмешательства человека) для выполнения очистки перед использованием. Встроенная очистка данных также делает процесс очистки данных более четким, поскольку раздвоенный путь очистки обычно сливается с органически чистыми данными перед загрузкой в ​​место назначения.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_1.jpg"><img decoding="async" class="aligncenter size-full wp-image-1512" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_1.jpg" alt="" width="759" height="286" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_1.jpg 759w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_1-300x113.jpg 300w" sizes="(max-width: 759px) 100vw, 759px" /></a></p>
<p>Как показано на блок-схеме выше, этот шаблон хранит заведомо исправные данные и подозрительные данные в параллельных конвейерах, объединяя их вместе после устранения недостатков. Этот шаблон предполагает гранулярность на уровне строк.</p>
<p>Прямая очистка данных &#8212; мой предпочтительный метод обработки подозрительных данных. Однако я не хочу подразумевать, что очистка данных &#8212; это простой процесс. Определение бизнес-правил и технических частей для обнаружения и очистки данных обычно требует значительных временных затрат, особенно когда эти бизнес-правила сложны.</p>
<p>Большинство систем ETL имеют встроенную логику для обработки некоторых наиболее распространенных операций очистки данных, а также интерфейсы сценариев, позволяющие вам создавать собственные решения для обеспечения качества данных. Для более сложных задач стороннее решение может быть правильным решением. Например, вы можете написать свою собственную логику проверки адресов, но создание этой логики И поддержание точной базы данных адресов, вероятно, будет стоить больше времени и денег, чем использование стороннего поставщика, уже оборудованного для таких операций. Обратите внимание на влияние на производительность и ограничения объема данных при использовании поставщика для работы с качеством данных, так как большинство из них используют облачный сервис и лицензируют свое программное обеспечение на основе объема данных.</p>
<p>При построении встроенной архитектуры очистки данных для управления неверными данными в ETL следует учитывать следующие особенности проектирования:</p>
<ul>
<li>Поскольку этот процесс будет изменять данные во время полета, обязательно сохраняйте контрольный журнал очистки изменений.</li>
<li>Будут ли случаи, когда данные не могут быть исправлены? Если это так, создайте предохранительный клапан для сортировки (или удаления, если необходимо) неразрешимых неверных данных.</li>
<li>Поскольку каждая подозрительная строка данных будет обрабатываться индивидуально, помните о возможных узких местах производительности, если для операции очистки требуется много системных ресурсов.</li>
</ul>
<h4><strong>сортировка</strong></h4>
<p>Шаблон проектирования сортировки полезен для проблем качества данных, которые не могут быть решены в оперативном режиме. Здесь подозрительные строки остаются нетронутыми и записываются в альтернативное местоположение, которое будет рассматриваться в отдельном процессе. Процесс ETL становится системой с двумя выходами, где хорошие данные отправляются в свое обычное место назначения, в то время как подозрительные данные записываются в выходной сигнал сортировки.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_2.jpg"><img decoding="async" class="aligncenter size-full wp-image-1513" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_2.jpg" alt="" width="1018" height="455" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_2.jpg 1018w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_2-300x134.jpg 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_2-768x343.jpg 768w" sizes="(max-width: 1018px) 100vw, 1018px" /></a></p>
<p>Хотя эта блок-схема указывает на более простую конструкцию, чем встроенная архитектура очистки, это показывает только часть решения. Редко подозрительные данные остаются в сортировке навсегда; в большинстве случаев существуют дополнительные процессы &#8212; или, возможно, даже вмешательство человека &#8212; для исправления тригифицированных данных и загрузки их в конечный пункт назначения.</p>
<p>Этот шаблон проектирования полезен в случаях, когда исправление слишком сложно для моделирования в очищающем бизнес-правиле или когда бизнес-правила субъективны и требуют вмешательства человека для подтверждения любых изменений данных. Кроме того, этот шаблон может быть полезен, когда некоторые бизнес-правила зависят от агрегации всего набора данных, которые трудно обрабатывать в потоке.</p>
<p>Несколько вещей, которые следует иметь в виду при использовании вывода triage для сбора подозрительных данных:</p>
<ul>
<li>Обязательно тщательно протестируйте процесс (ы), которые взаимодействуют с обработанными данными. Недостаточно отправить подозрительные данные в triage, поэтому модульного тестирования вышеупомянутой архитектуры недостаточно.</li>
<li>При создании тех периферийных процессов, которые очищают данные в triage, не забудьте извлечь из triage все очищенные строки и записать их в окончательный вывод. В противном случае таблица сортировки будет продолжать расти, и производительность в конечном итоге пострадает.</li>
<li>Поскольку в этом шаблоне используются два (или, возможно, больше) выходных сигнала, возможно непреднамеренная потеря данных в конвейере ETL, если один из выходных сигналов не был правильно подключен. Настоятельно рекомендуется использовать аудит количества строк, чтобы убедиться, что все входящие строки данных учтены в одном из выходных данных.</li>
</ul>
<h4><strong>Удалить</strong></h4>
<p>Я стесняюсь даже привести этот шаблон дизайна по причинам, которые я перечислю в ближайшее время. Однако в интересах всестороннего освещения этой темы я кратко опишу схему удаления неверных данных. Короче говоря, этот шаблон проектирования выглядит очень похоже на шаблон сортировки, описанный выше, за исключением того, что неверные данные просто отбрасываются.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_3.jpg"><img decoding="async" class="aligncenter size-full wp-image-1514" src="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_3.jpg" alt="" width="1002" height="503" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_3.jpg 1002w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_3-300x151.jpg 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2022/01/ETL_Data_Cleansing_3-768x386.jpg 768w" sizes="(max-width: 1002px) 100vw, 1002px" /></a></p>
<p>Как показано на приведенной выше блок-схеме, сохраняются только хорошие данные. Строки, не прошедшие проверку качества данных, отправляются в область битов.</p>
<p>Положительным моментом является то, что этот шаблон дизайна отличается простотой разработки. Недостатком является то, что я не могу особо подчеркнуть серьезность этого момента, <em>вы потеряете данные</em> . Не только данные &#8212; вы также потеряете любой контрольный журнал, показывающий, что данные были обработаны, но отклонены. Кроме того, вы потеряете способность проверять логику управления качеством данных с использованием исторических неверных данных. В некоторых крайних случаях это может быть приемлемым. Этот шаблон проектирования следует учитывать для обработки подозрительных неверных данных только в том случае, если выполняются все следующие условия:</p>
<ul>
<li>Не существует практического способа устранения недостатка данных, приводящего к тому, что записи переходят в состояние ошибки</li>
<li>Нет никакого смысла в том, чтобы иметь какие-либо данные в любом столбце или поле в строке данных, которые не прошли проверку качества данных</li>
<li>Удаление одной или нескольких записей не влияет на достоверность или полноту импортированных данных.</li>
<li>В этом наборе данных нет процессов, требующих аудита</li>
<li>Нет планов по изменению критериев, определяющих хороший или плохой ряд данных.</li>
</ul>
<p>Лично, даже если все вышеприведенные утверждения верны, я все равно буду сопротивляться простому удалению этих подозрительных строк. <em>Я ненавижу потерять данные, даже если это специально</em> . Если ничего другого, хранение неверных данных в таблице дампа или файле может быть полезно для проверки логики оценки качества данных.</p>
<h4><strong>Гибридный подход</strong></h4>
<p>В действительности большинство конвейеров для управления неверными данными в ETL используют объединение вышеуказанных шаблонов проектирования. Часто я вижу встроенную очистку, используемую с шаблоном сортировки, при которой данные, которые невозможно очистить, отправляются в таблицу или файл сортировки. Кроме того, в проекте ETL, состоящем из множества отдельных процессов загрузки, обработка подозрительных данных может и будет варьироваться от одной загрузки к другой.</p>
<h4><strong>Аудиторская проверка</strong></h4>
<p>Я кратко упомянул об этом ранее, но это достаточно важно повторить. При создании процесса, который управляет неверными данными, убедитесь, что вы записываете цифровой контрольный журнал при манипулировании или фильтрации данных, прежде чем загружать их в конечный пункт назначения. Эта цепочка доказательств имеет решающее значение для устранения неполадок, документирования происхождения данных и, иногда, для целей CYA.</p>
<h4><strong>Вывод</strong></h4>
<p>Управление неверными данными в ETL является требованием во многих корпоративных проектах ETL. Данные могут быть очищены в ETL, сохранены в сортировке или просто отброшены, если обнаружены недостатки. Прежде всего, помните, что обработка подозрительных данных должна отвечать потребностям бизнеса.</p>
<h3><strong>Get Your Email Out Of My ETL (Получите ваш адрес электронной почты из моего ETL)</strong></h3>
<p><strong><span style="color: #ff6600;">Get Your Email Out Of My ETL (Получите ваш адрес электронной почты из моего ETL).</span></strong> Для каждой работы есть подходящий инструмент. Внедрение уведомлений по электронной почте непосредственно в процессы ETL добавляет ненужную сложность и возможные точки отказа.</p>
<p>Версия этого поста &#8212; я позволил моим процессам extract-transform-load делать только ETL и оставлять уведомления системе планирования, которой они принадлежат.</p>
<h4>Получите ваш электронный адрес из моего ETL</h4>
<p>Прежде чем читать дальше, вы должны знать, что я выздоравливающий писатель ETL. Не так много лет назад я бы включил все &#8212; и я имею в виду все &#8212; в свои процессы ETL (обычно с использованием SSIS). Даже вещи, которые на самом деле не имеют ничего общего с перемещением данных. Конечно, это включало задачи уведомления по электронной почте. Однако за прошедшие годы я усвоил очень ценный урок: для каждой работы есть подходящий инструмент . Быстрые исправления приносят быстрое облегчение, но часто за счет устойчивости и общей стоимости владения.</p>
<p>Начнем с рассмотрения причин, по которым вы могли бы в первую очередь включить логику уведомлений по электронной почте в процессы ETL. Безусловно, наиболее распространенной причиной является уведомление кого-либо (или группы людей), когда что-то идет не так в процессе ETL. Менее распространенные причины включают в себя необходимость уведомлений о завершении каждого процесса (плохая идея сама по себе, но я оставлю это обсуждение на другой день) или желание отправить подмножество или совокупность данных (например, количество строк или долларовая сумма) для проверки. Каждый крупный поставщик ETL включает возможности электронной почты, которые соблазнительно легко внедрить в существующие загрузки ETL. И давайте не будем ошибаться: некоторые уведомления имеют решающее значение, особенно те, которые предназначены для привлечения внимания людей, которые должны реагировать на сбои загрузки данных или аномалии. Тем не мение,</p>
<h4>В чем проблема?</h4>
<p>Что плохого в использовании процессов загрузки ETL для прямой отправки электронной почты? Позвольте мне сосчитать пути.</p>
<p><em>Это еще одна потенциальная точка отказа для процесса ETL</em> . Если загрузка ETL проходит нормально, но что-то идет не так с уведомлением по электронной почте, может показаться, что операция загрузки данных прервана, хотя на самом деле это всего лишь шаг электронной почты. Еще хуже, если уведомление по электронной почте происходит в середине загрузки с другими шагами за ним, теперь у вас остается частично завершенная загрузка &#8212; все из-за сбоя операции, даже не являющейся центральной для операций с данными.</p>
<p><em>С некоторыми низкоуровневыми сбоями вы никогда не получите уведомление</em> . Мой инструмент ETL &#8212; <a href="https://msdn.microsoft.com/en-us/library/ms141026.aspx">SSIS</a> , так что вот как это будет работать: некоторая часть структуры данных источника или назначения изменяется, и пакет SSIS обнаруживает, что ему нужно обновить метаданные. Поскольку этот этап проверки выполняется до начала какой-либо реальной работы, возможно, что ни одна часть пакета &#8212; даже обработка ошибок или логика уведомлений &#8212; не будет запущена. Дерево упадет в лес, и никто его не услышит.</p>
<p><em>Это удлиняет процесс разработки и тестирования</em> . Процессы ETL часто бывают сложными и требуют нескольких недель или месяцев. Зачем излишне загромождать процесс разработки и тестирования большим количеством движущихся частей, которые не являются основной частью перемещения данных?</p>
<p><em>Несогласованность</em> . В самой последней статье из серии ETL Best Practices я говорил о модульности кода . Одним из преимуществ модульных процессов является последовательность. Если вы вставляете множество специальных уведомлений об исключениях в пакеты ETL, их трудно поддерживать согласованными. Конечно, у вас может быть общий процесс, подобный тому, что я описал в модульном посте, но это требует дополнительной сложности, которая является второстепенной по отношению к основной цели процесса ETL.</p>
<p><em>Невозможно включить всю необходимую информацию для отладки в электронное письмо с уведомлением</em>, Когда я советую клиентам и слушателям курсов не отправлять уведомления непосредственно из ETL, общий аргумент заключается в том, что они хотят включить как можно больше отладочной информации в электронное письмо с уведомлением, чтобы дать отвечающему технику или инженеру все, что им нужно для начала работы над проблемой. Для включения всей этой информации необходим доступ во время выполнения к сообщениям об ошибках, таким образом, аргумент для отправки электронной почты непосредственно из загрузки ETL. Моя реплика такова: насколько реально, что вы включите в электронное письмо всю информацию, необходимую для фактической диагностики проблемы? Любой, кто просматривал журналы из любой системы ETL, может засвидетельствовать тот факт, что каждая ошибка порождает пять других, и так далее. Выяснить истинную причину &#8212; это не то, что вы можете автоматизировать,</p>
<p><em>Это неуклюжее</em> . Возможно, где-то есть лучшая мышеловка, но у систем ETL, с которыми я работал, есть интерфейсы электронной почты, которые в лучшем случае зачаточны. Задачи электронной почты в программном обеспечении ETL ограничены по функциональности и не совсем рассчитаны на надежность.</p>
<h4>Лучший путь</h4>
<p>Как я упоминал ранее, для каждой работы есть инструмент. При рассмотрении роли уведомлений по электронной почте это скорее механизм планирования, чем функция ETL. Поэтому я рекомендую всегда рассматривать ваш инструмент планирования в качестве основного средства для создания уведомлений об исключениях для нагрузок ETL. Каждый инструмент планирования предприятия, от агента SQL Server, включенного в состав SQL Server, до коммерческих продуктов, таких как Control-M или JAMS, имеет встроенные средства уведомления по электронной почте. Перенесите ваши уведомления об исключениях в любой инструмент, который планирует работу.</p>
<p>Чтобы ускорить процесс устранения неполадок, добавьте URL-адрес или другой ярлык к своим отчетам, содержащим информацию о вашей регистрации. Как отмечалось выше, пытаться втиснуть все связанные с этим ошибки в электронное письмо с уведомлением бесполезно, и в конце концов ответчик в любом случае просто перейдет к таблицам регистрации. Используйте уведомление по электронной почте, чтобы предоставить им этот ярлык.</p>
<p>Наконец, если вы убеждены в том, что вам действительно нужно включить информацию об ошибках в уведомления по электронной почте, вы можете воспользоваться для этого своими инструментами отчетности. Например, службы отчетов SQL Server позволят вам использовать управляемые данными подписки для отправки настроенных электронных писем для отправки отфильтрованных данных журнала нужным получателям.</p>
<h4><strong>Вывод</strong></h4>
<p>Использование уведомлений по электронной почте из вашего инструмента ETL может показаться быстрым и простым способом добавления предупреждений к загрузке данных, но в конечном итоге этот шаблон проектирования оказывается головной болью при обслуживании. Используйте правильный инструмент для работы, и пусть ваш инструмент планирования справится с этой задачей.</p>
<h3><strong>Using ETL Staging Tables (Использование промежуточных таблиц ETL)</strong></h3>
<p><strong><span style="color: #ff6600;">Using ETL Staging Tables (Использование промежуточных таблиц ETL).</span></strong> Часто использование промежуточных таблиц может повысить производительность и снизить сложность процессов ETL.</p>
<p>Большинство традиционных процессов ETL выполняют свои загрузки, используя три отдельных и последовательных процесса: извлечение с последующим преобразованием и, наконец, загрузку в место назначения. Однако для некоторых больших или сложных нагрузок использование промежуточных таблиц ETL может повысить производительность и снизить сложность.</p>
<p>Как часть моей продолжающейся серии по ETL передовой практике , в этой статье я буду некоторые рекомендации по использованию таблиц ETL стадирования.</p>
<h4><strong>Обычный трехступенчатый ETL</strong></h4>
<p>Процессы извлечения, преобразования и загрузки, как подразумевается в этой метке, обычно имеют следующий рабочий процесс:</p>
<ol>
<li>Получить (извлечь) данные из их источника, который может быть реляционной базой данных, простым файлом или облачным хранилищем</li>
<li>Изменять и очищать (преобразовывать) данные по мере необходимости, чтобы вписаться в схему назначения и применить любые правила очистки или бизнес-правила</li>
<li>Вставьте (загрузите) преобразованные данные в место назначения, которое обычно (но не всегда) является таблицей реляционной базы данных</li>
</ol>
<p>Этот типичный рабочий процесс предполагает, что каждый процесс ETL обрабатывает преобразование встроенно, обычно в памяти и до того, как данные попадают в место назначения. Для большинства потребностей ETL этот шаблон работает хорошо. Каждый инструмент ETL корпоративного класса построен со сложными инструментами преобразования, способными выполнять многие из этих общих задач очистки, дедупликации и преобразования. Этот трехэтапный процесс перемещения и манипулирования данными поддается простоте, а при прочих равных условиях чем проще, тем лучше.</p>
<p>Однако есть случаи, когда простое извлечение, преобразование и загрузка не подходят. Среди этих потенциальных случаев:</p>
<ul>
<li>Для каждой загружаемой строки требуется что-то из одной или нескольких других строк в том же наборе данных (например, определение порядка или группировки или промежуточного итога)</li>
<li>Исходные данные используются для обновления (а не для вставки в) назначения</li>
<li>Процесс ETL представляет собой инкрементную нагрузку, но объем данных является достаточно значительным, так что сравнение строк за строкой на этапе преобразования неэффективно</li>
<li>Преобразование данных требует нескольких шагов, и вывод одного шага преобразования становится вводом другого</li>
</ul>
<p>Хотя обычно все это можно выполнить с помощью одного этапа преобразования в процессе, это может привести к снижению производительности или излишней сложности. Я сторонник использования правильного инструмента для работы, и часто лучший способ обработать груз &#8212; это позволить базе данных назначения выполнить некоторые тяжелые работы.</p>
<h4><strong>Использование промежуточных таблиц ETL</strong></h4>
<p>Когда объем или детализация процесса преобразования приводит к плохой работе процессов ETL, рассмотрите возможность использования промежуточной таблицы в базе данных назначения в качестве средства для обработки результатов промежуточных данных. Промежуточные таблицы обычно рассматриваются как изменчивые таблицы, то есть они очищаются и перезагружаются каждый раз без сохранения результатов от одного выполнения к другому. Промежуточные таблицы следует использовать только для промежуточных результатов, а не для постоянного хранения.</p>
<p>При использовании схемы загрузки с промежуточными таблицами поток ETL выглядит примерно так:</p>
<ol>
<li>Удалить существующие данные в промежуточных таблицах</li>
<li>Извлечь данные из источника</li>
<li>Загрузите эти исходные данные в промежуточные таблицы</li>
<li>Выполните реляционные обновления (обычно используя T-SQL, PL / SQL или другой язык, специфичный для вашей СУБД), чтобы очистить или применить бизнес-правила к данным, повторяя этот этап преобразования по мере необходимости</li>
<li>Загрузите преобразованные данные из промежуточной таблицы (таблиц) в окончательную таблицу (таблицы) назначения</li>
</ol>
<p>Этот шаблон проектирования нагрузки имеет больше шагов, чем традиционный процесс ETL, но он также обеспечивает дополнительную гибкость. Загрузив данные сначала в промежуточные таблицы, вы сможете использовать ядро ​​базы данных для вещей, которые уже хорошо работают. Например, объединение двух наборов данных вместе для целей проверки или поиска может быть выполнено в большинстве инструментов ETL, но это тип задач, который механизм базы данных выполняет исключительно хорошо. То же самое с выполнением операций сортировки и агрегирования; Инструменты ETL могут делать эти вещи, но в большинстве случаев ядро ​​базы данных делает это тоже, но гораздо быстрее.</p>
<h4><strong>Варианты промежуточных столов</strong></h4>
<p>При использовании промежуточных таблиц для сортировки данных вы включаете поведения СУБД, которые, вероятно, недоступны при обычном преобразовании ETL. Например, вы можете создавать индексы для промежуточных таблиц, чтобы повысить производительность последующей загрузки в постоянные таблицы. Вы можете запустить несколько преобразований для одного и того же набора данных, не сохраняя их в памяти на время этих преобразований, что может снизить влияние на производительность.</p>
<p>Промежуточные таблицы также позволяют легко запрашивать эти промежуточные результаты с помощью простого запроса SQL. Кроме того, вы можете повторно использовать некоторые поэтапные данные в тех случаях, когда относительно статические данные используются несколько раз при одной и той же загрузке или в нескольких процессах загрузки.</p>
<p>Кроме того, для некоторых крайних случаев я использовал шаблон, который имеет несколько слоев промежуточных таблиц, и первая промежуточная таблица используется для загрузки второй промежуточной таблицы. Это шаблон проектирования, которым я редко пользуюсь, но он пригодился в тех случаях, когда форма или структура данных должна была существенно измениться в процессе загрузки.</p>
<h4><strong>Это все еще ETL?</strong></h4>
<p>Те, кто педантичен по поводу терминологии (в эту группу часто входит и я), захотят знать: при использовании этого сценария постановки процесса этот процесс все еще называется ETL? Как правило, вы увидите этот процесс, называемый ELT &#8212; извлечение, загрузка и преобразование &#8212; потому что загрузка до места назначения выполняется до того, как произойдет преобразование. Я видел много вариантов этого, включая ELTL (извлечение, загрузка, преобразование, загрузка). Тем не менее, я склонен использовать ETL в качестве широкой метки, которая определяет получение данных из некоторого источника, некоторую меру преобразования по пути, сопровождаемую загрузкой в ​​конечный пункт назначения. Семантически я считаю ELT и ELTL специфическими шаблонами проектирования в широкой категории ETL.</p>
<p>Также имейте в виду, что использование промежуточных таблиц должно оцениваться для каждого процесса отдельно. Промежуточная архитектура ETL является одним из нескольких шаблонов проектирования и не идеально подходит для всех нагрузок. Любая зрелая инфраструктура ETL будет иметь смесь обычных ETL, поэтапных ETL и других вариантов в зависимости от специфики каждой нагрузки.</p>
<h4><strong>Советы по использованию промежуточных таблиц ETL</strong></h4>
<p>Когда вы решите использовать промежуточные таблицы в процессах ETL, вот несколько соображений, о которых следует помнить:</p>
<p><em>Отделите промежуточные столы ETL от долговечных столов</em> . Должно быть некоторое логическое, если не физическое, разделение между стойкими таблицами и теми, которые используются для подготовки ETL. Вы получите наибольшее преимущество в производительности, если они существуют в одном экземпляре базы данных, но хранение этих промежуточных таблиц в отдельной схеме &#8212; или, возможно, даже в отдельной базе данных &#8212; прояснит разницу между промежуточными таблицами и их надежными аналогами. Разделение их физически на разные файлы также может снизить конфликт дискового ввода-вывода во время загрузки.</p>
<p><em>Используйте постоянные промежуточные таблицы, а не временные таблицы</em> . Основные поставщики реляционных баз данных позволяют создавать временные таблицы, которые существуют только на время соединения. Обычно я рекомендую избегать их, потому что запрос промежуточных результатов в этих таблицах (обычно для целей отладки) может оказаться невозможным вне рамок процесса ETL. Кроме того, некоторые инструменты ETL, включая службы интеграции SQL Server, могут сталкиваться с ошибками при попытке выполнить проверку метаданных по таблицам, которые еще не существуют.</p>
<p><em>Подумайте об индексации ваших промежуточных таблиц</em> . Не произвольно добавляйте индекс для каждой промежуточной таблицы, но подумайте, как вы используете эту таблицу на последующих шагах загрузки ETL. В некоторых случаях использование правильно размещенного индекса ускорит процесс.</p>
<p><em>Рассмотрите возможность очистки промежуточного стола до и после загрузки</em> . Вы наверняка захотите удалить данные из последней загрузки в начале выполнения процесса ETL, но подумайте и об их очистке позже. Особенно при работе с большими наборами данных очистка промежуточной таблицы приведет к сокращению времени и объема дискового пространства, необходимого для резервного копирования базы данных.</p>
<p><em>Вам нужно запустить несколько одновременных загрузок одновременно? </em>Для большинства нагрузок это не будет проблемой. Однако некоторые нагрузки могут выполняться целенаправленно для перекрытия &#8212; то есть два экземпляра одного и того же ETL-процесса могут выполняться в любой момент времени &#8212; и в этих случаях вам потребуется более тщательная разработка промежуточных таблиц. Как правило, промежуточные таблицы просто усекаются для удаления предыдущих результатов, но если промежуточные таблицы могут содержать данные из нескольких перекрывающихся каналов, вам необходимо добавить поле, идентифицирующее эту конкретную нагрузку, чтобы избежать конфликтов параллелизма.</p>
<p><em>Правильно </em><em>обрабатывать </em><em>данные</em> . Если ваши процессы ETL созданы для отслеживания происхождения данных , убедитесь, что ваши промежуточные таблицы ETL настроены для поддержки этого. Линия данных предоставляет цепочку доказательств от источника до конечного пункта назначения, обычно на уровне строк. Если вы отслеживаете происхождение данных, вам может потребоваться добавить один или два столбца в промежуточную таблицу, чтобы правильно отследить это.</p>
<h4><strong>Вывод</strong></h4>
<p>Хотя обычный трехэтапный процесс ETL очень хорошо обслуживает многие потребности в загрузке данных, бывают случаи, когда использование промежуточных таблиц ETL может повысить производительность и снизить сложность. Хороший шаблон проектирования для поэтапной загрузки ETL является неотъемлемой частью правильно оборудованного инструментария ETL.</p>
<h3><strong>Secure Your Data Prep Area (Защитите свою область подготовки данных)</strong></h3>
<p><span style="color: #ff6600;"><strong>Secure Your Data Prep Area (Защитите свою область подготовки данных).</strong></span> Staging или Landing area обрабатываемых в настоящее время данных не должна быть доступна потребителям данных. В противном случае вы можете получить неверные данные, противоречивую аналитику или потенциальные угрозы безопасности.</p>
<p>Я много лет строил процессы ETL, и я узнал две универсальные истины: подготовка данных грязная, и вы всегда должны защищать свою область подготовки данных. Область подготовки данных очень похожа на коммерческую кухню и так же, как клиенты не допускаются на кухню, поэтому следует избегать доступа потребителей к структурам данных в процессе.</p>
<h4>Что такое область подготовки данных?</h4>
<p>Прежде всего, давайте определимся с областью подготовки данных. Подготовка данных (prep) &#8212; это обычная фаза операций извлечения, преобразования и загрузки ( ETL ), в которой данные временно записываются для очистки, дедупликации, изменения формы или других изменений данных. Также иногда называемый областью посадки или промежуточной области, это общий шаблон проектирования при перемещении данных из хранилища данных, оптимизированных для оперативной обработки транзакций ( OLTP ), в модель данных, более удобную для аналитики или отчетности.</p>
<p>Область подготовки данных действительно очень похожа на кухню ресторана: иногда она хаотична, не удобна для потребителей и существует законный риск потребления полуфабрикатов.</p>
<h4><strong>Когда клиенты бродят по кухне</strong></h4>
<p>Несмотря на свое предназначение, потребители данных нередко имеют доступ к области подготовки данных. И я понял &#8212; иногда удобно позволить пользователям возиться с необработанными данными, особенно с навыками Excel на уровне мастера. Однако при открытии области подготовки данных для конечных пользователей существуют ощутимые риски:</p>
<ul>
<li><em>Данные находятся в промежуточном состоянии</em> . По определению область подготовки или подготовки данных предназначена для временного хранения текущих операций с данными. Предоставление потребителям данных доступа к этим данным сродни тому, чтобы подавать им частично приготовленную еду. Средне-редкая курица, кто-нибудь?</li>
<li><em>Нет единого источника правды</em> . Наихудший возможный результат любого перемещения или преобразования данных состоит в том, что существует несколько возможных источников данных, дающих ответы на одни и те же вопросы. Если область подготовки данных является временной остановкой на пути к хранилищу данных или ODS, предоставление доступа к этой промежуточной станции практически гарантирует, что содержащиеся в ней данные будут конкурировать с полностью обработанными и проверенными данными в DW или ODS.</li>
<li><em>Доступ пользователя может помешать подготовке данных</em> . Если пользователи выполняют дорогостоящие запросы во время выполнения процессов ETL, производительность обоих процессов может снизиться. В области подготовки данных процессы ETL должны иметь приоритет.</li>
<li><em>Возможные угрозы безопасности</em> . Хотя это не должно быть так, область подготовки данных иногда не получает такой же уровень контроля безопасности, как хранилище данных или другие структуры, ориентированные на пользователя. Если пользователи обращаются к этому временному хранилищу данных напрямую, они могут случайно получить доступ, которого у них обычно не должно быть.</li>
</ul>
<h4>Защитите свою область подготовки данных!</h4>
<p>Хотя это требует определенной институциональной дисциплины, я настоятельно рекомендую ограничить доступ пользователей к вашей области подготовки данных. Это помогает устранить некоторые риски получения плохих или противоречивых результатов и сохраняет эту зону посадки данных в соответствии с ее назначением.</p>
<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&amp;linkname=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fetl-best-practices-design-data-patterns%2F&#038;title=ETL%20Best%20Practices.%20ETL%20Design%20Patterns.%20%D0%A7%D1%82%D0%BE%20%D1%82%D0%B0%D0%BA%D0%BE%D0%B5%20ETL%3F" data-a2a-url="https://python.ivan-shamaev.ru/etl-best-practices-design-data-patterns/" data-a2a-title="ETL Best Practices. ETL Design Patterns. Что такое ETL?"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/etl-best-practices-design-data-patterns/">ETL Best Practices. ETL Design Patterns. Что такое ETL?</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/etl-best-practices-design-data-patterns/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>5 Полезных функций Python Pandas для Data Science</title>
		<link>https://python.ivan-shamaev.ru/5-useful-functions-of-pandas-python-for-data-science/</link>
					<comments>https://python.ivan-shamaev.ru/5-useful-functions-of-pandas-python-for-data-science/#respond</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Thu, 16 Apr 2020 02:26:43 +0000</pubDate>
				<category><![CDATA[Pandas. Обработка данных]]></category>
		<category><![CDATA[python pandas]]></category>
		<category><![CDATA[обучение Python pandas]]></category>
		<category><![CDATA[полезные функции pandas python]]></category>
		<category><![CDATA[учебник python pandas]]></category>
		<category><![CDATA[функции python pandas]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=962</guid>

					<description><![CDATA[<p>В повседневной обработке данных для проектов машинного обучения и data science библиотека Python Pandas является одной из наиболее часто используемых. shift() &#8212; функция Python Pandas Предположим, вы столкнулись с ситуацией, когда вам нужно сместить все строки в DataFrame или использовать цену акций предыдущего дня в DataFrame. Может быть, мы хотим построить среднюю температуру за последние [&#8230;]</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/5-useful-functions-of-pandas-python-for-data-science/">5 Полезных функций Python Pandas для Data Science</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&#038;title=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" data-a2a-url="https://python.ivan-shamaev.ru/5-useful-functions-of-pandas-python-for-data-science/" data-a2a-title="5 Полезных функций Python Pandas для Data Science"></a></p><p>В повседневной обработке данных для проектов машинного обучения и data science библиотека Python Pandas является одной из наиболее часто используемых.</p>
<h2><strong><span style="color: #ff6600;">shift()</span> &#8212; функция Python Pandas</strong></h2>
<p>Предположим, вы столкнулись с ситуацией, когда вам нужно сместить все строки в DataFrame или использовать цену акций предыдущего дня в DataFrame. Может быть, мы хотим построить среднюю температуру за последние три дня в наборе данных.</p>
<p><strong>Shift()</strong> будет идеальным способом для достижения всех этих целей.</p>
<p><strong>Функция Pandas Shift()</strong>, сдвигает индекс на желаемое количество периодов. Эта функция принимает скалярный параметр, называемый периодом, который представляет количество сдвигов для желаемой оси. Эта функция полезна при работе с данными временных рядов. Мы можем использовать <strong>fill_value</strong> для заполнения за пределами граничных значений.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np
df = pd.DataFrame({'DATE': [1, 2, 3, 4, 5],
                   'VOLUME': [100, 200, 300,400,500],
                   'PRICE': [214, 234, 253,272,291]})
print(df)

===РЕЗУЛЬТАТ===
    DATE  VOLUME  PRICE
0     1     100    214
1     2     200    234
2     3     300    253
3     4     400    272
4     5     500    291

print(df.shift(1))

===РЕЗУЛЬТАТ===
DATE  VOLUME  PRICE
0   NaN     NaN    NaN
1   1.0   100.0  214.0
2   2.0   200.0  234.0
3   3.0   300.0  253.0
4   4.0   400.0  272.0

# with fill_Value = 0
print(df.shift(1,fill_value=0))

===РЕЗУЛЬТАТ===
DATE  VOLUME  PRICE
0     0       0      0
1     1     100    214
2     2     200    234
3     3     300    253
4     4     400    272</pre>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/1_5_Elegant_Python_Pandas_Functions.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/1_5_Elegant_Python_Pandas_Functions.png" alt="" width="1400" height="1483" class="aligncenter size-full wp-image-967" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/1_5_Elegant_Python_Pandas_Functions.png 1400w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/1_5_Elegant_Python_Pandas_Functions-283x300.png 283w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/1_5_Elegant_Python_Pandas_Functions-967x1024.png 967w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/1_5_Elegant_Python_Pandas_Functions-768x814.png 768w" sizes="(max-width: 1400px) 100vw, 1400px" /></a></p>
<p><span>Теперь, если нам нужно получить цену акций предыдущего дня в виде нового столбца, мы можем использовать сдвиг с помощью функции shift():</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df['PREV_DAY_PRICE'] = df['PRICE'].shift(1,fill_value=0)
print(df)

===Результат===
DATE  VOLUME  PRICE  PREV_DAY_PRICE
0     1     100    214               0
1     2     200    234             214
2     3     300    253             234
3     4     400    272             253
4     5     500    291             272</pre>
<p><span>Мы можем легко рассчитать среднюю цену акций за последние три дня, как показано ниже, и создать новый столбец функций.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df['LAST_3_DAYS_AVE_PRICE'] = (df['PRICE'].shift(1,fill_value=0) + 
                               df['PRICE'].shift(2,fill_value=0) + 
                               df['PRICE'].shift(3,fill_value=0))/3</pre>
<p><span>Теперь DataFrame станет таким:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">DATE  VOLUME  PRICE     LAST_3_DAYS_AVE_PRICE
0     1     100    214               0.000000
1     2     200    234              71.333333
2     3     300    253             149.333333
3     4     400    272             233.666667
4     5     500    291             253.000000</pre>
<p>Мы также можем сдвигаться вперед, чтобы получить значение из следующего временного периода или следующего значения в ряду (не обязательно это должен быть период).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df['TOMORROW_PRICE'] = df['PRICE'].shift(-1,fill_value=0)</pre>
<p><span>Теперь фрейм данных будет:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">DATE  VOLUME  PRICE     TOMORROW_PRICE
0     1     100    214             234
1     2     200    234             253
2     3     300    253             272
3     4     400    272             291
4     5     500    291               0</pre>
<p><span>Более подробную информацию о параметрах и других настройках см. в </span><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.shift.html?highlight=shift#pandas.Series.shift" class="cq ih ks kt ku kv" target="_blank" rel="noopener nofollow noreferrer"><span>документации Pandas</span></a><span>.</span></p>
<h2><strong><span style="color: #ff6600;">value_counts()</span> &#8212; функция Python Pandas</strong></h2>
<p>Функция Pandas value_counts() возвращает объект, содержащий количество уникальных значений. Полученный объект можно отсортировать в порядке убывания или в порядке возрастания, включить NA или исключить NA посредством управления параметрами. Эта функция может использоваться с индексами в DataFrames или Pandas Series.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/2_5_Elegant_Python_Pandas_Functions-1.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/2_5_Elegant_Python_Pandas_Functions-1.png" alt="" width="947" height="579" class="aligncenter size-full wp-image-976" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/2_5_Elegant_Python_Pandas_Functions-1.png 947w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/2_5_Elegant_Python_Pandas_Functions-1-300x183.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/2_5_Elegant_Python_Pandas_Functions-1-768x470.png 768w" sizes="(max-width: 947px) 100vw, 947px" /></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">a = pd.Index([3,3,4,2,1,3, 1, 2, 3, 4, np.nan,4,6,7])
print(a.value_counts())

===РЕЗУЛЬТАТ===
3.0    4
4.0    3
1.0    2
2.0    2
7.0    1
6.0    1
dtype: int64</pre>
<p><span>Ниже приведен пример Series.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">#In
b = pd.Series(['ab','bc','cd',1,'cd','cd','bc','ab','bc',1,2,3,2,3,np.nan,1,np.nan])
b.value_counts()

#Out
bc    3
cd    3
1     3
3     2
ab    2
2     2
dtype: int64</pre>
<p><span><strong>Опция Bin</strong> может использоваться вместо подсчета уникальных значений значений, разделив индекс на указанное количество полуоткрытых <strong>Bins</strong>.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">#In
a = pd.Index([3,3,4,2,1,3, 1, 2, 3, 4, np.nan,4,6,7])
a.value_counts(bins=4)

#Out
(2.5, 4.0]      7
(0.993, 2.5]    4
(5.5, 7.0]      2
(4.0, 5.5]      0
dtype: int64</pre>
<p><span>Более подробную информацию о параметрах и других настройках см. в </span><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.value_counts.html" class="cq ih ks kt ku kv" target="_blank" rel="noopener nofollow noreferrer"><span>документации Pandas</span></a><span>.</span></p>
<h2><strong><span style="color: #ff6600;">mask()</span> &#8212; функция Python Pandas</strong></h2>
<p>Метод mask() является применением условия if-then для каждого элемента Series или DataFrame. Если Condition равно True, тогда он использует значение из Other (значение по умолчанию &#8212; NaN), в противном случае будет сохранено исходное значение. Этот метод mask() очень похож на where().</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/3_5_Elegant_Python_Pandas_Functions-1.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/3_5_Elegant_Python_Pandas_Functions-1.png" alt="" width="676" height="639" class="aligncenter size-full wp-image-980" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/3_5_Elegant_Python_Pandas_Functions-1.png 676w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/3_5_Elegant_Python_Pandas_Functions-1-300x284.png 300w" sizes="(max-width: 676px) 100vw, 676px" /></a></p>
<p><span>Ниже приведен DataFrame, в котором мы хотим изменить знак всех элементов, которые делятся на два без остатка.</span></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/4_5_Elegant_Python_Pandas_Functions-1.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/4_5_Elegant_Python_Pandas_Functions-1.png" alt="" width="635" height="266" class="aligncenter size-full wp-image-982" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/4_5_Elegant_Python_Pandas_Functions-1.png 635w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/4_5_Elegant_Python_Pandas_Functions-1-300x126.png 300w" sizes="(max-width: 635px) 100vw, 635px" /></a></p>
<p>Этого легко можно достигнуть с помощью функции mask():</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df = pd.DataFrame(np.arange(15).reshape(-1, 3), columns=['A', 'B','C'])
print(df)

#Out
    A   B   C
0   0   1   2
1   3   4   5
2   6   7   8
3   9  10  11
4  12  13  14

#mask operation to check if element is divided by 2 without any remainder. If match change the sign of the element as original
df.mask(df % 2 == 0,-df)

#Out
A   B   C
0   0   1  -2
1   3  -4   5
2  -6   7  -8
3   9 -10  11
4 -12  13 -14</pre>
<p><span>Более подробную информацию о параметрах и других настройках см. в </span><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.mask.html#pandas.DataFrame.mask" class="cq ih ks kt ku kv" target="_blank" rel="noopener nofollow noreferrer"><span>документации Pandas mask</span></a><span>.</span></p>
<h2><strong><span style="color: #ff6600;">nlargest()</span> &#8212; функция Python Pandas</strong></h2>
<p>Во многих случаях мы сталкиваемся с ситуациями, когда нам нужно найти 3 верхних (top) или 5 нижних (bottom) значений для Series или DataFrame (например, трех лучших учеников с самыми высокими показателями с их совокупным баллом или трех худших кандидатов с общим количеством голосов, полученных на выборах).<br />
Функции Python Pandas nlargest() и nsmallest() &#8212; лучший способ для такой обработки данных.<br />
В приведенном ниже примере показаны три самых больших значения из DataFrame из 10 наблюдений.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/5_5_Elegant_Python_Pandas_Functions-1.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/5_5_Elegant_Python_Pandas_Functions-1.png" alt="" width="441" height="1040" class="aligncenter size-full wp-image-984" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/5_5_Elegant_Python_Pandas_Functions-1.png 441w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/5_5_Elegant_Python_Pandas_Functions-1-127x300.png 127w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/5_5_Elegant_Python_Pandas_Functions-1-434x1024.png 434w" sizes="(max-width: 441px) 100vw, 441px" /></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np
df = pd.DataFrame({'HEIGHT': [170,78,99,160,160,130,155,70,70,20],
                   'WEIGHT': [50,60,70,80,90,90,90,50,60,70]},
                   index=['A','B','C','D','E','F','G','H','I','J'])
print(df)

HEIGHT  WEIGHT
A     170      50
B      78      60
C      99      70
D     160      80
E     160      90
F     130      90
G     155      90
H      70      50
I      70      60
J      20      70

dfl = df.nlargest(3,'HEIGHT')
print(dfl)

HEIGHT  WEIGHT
A     170      50
D     160      80
E     160      90</pre>
<p>Если есть связь, то есть несколько вариантов, которые можно разрешить с помощью «first», «last», «all» (по умолчанию «first»). Сохраняйте все случаи. Мы попытаемся найти две самые большие высоты в примерах ниже.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/6_5_Elegant_Python_Pandas_Functions-1.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/6_5_Elegant_Python_Pandas_Functions-1.png" alt="" width="883" height="821" class="aligncenter size-full wp-image-986" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/6_5_Elegant_Python_Pandas_Functions-1.png 883w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/6_5_Elegant_Python_Pandas_Functions-1-300x279.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/04/6_5_Elegant_Python_Pandas_Functions-1-768x714.png 768w" sizes="(max-width: 883px) 100vw, 883px" /></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">dfl = df.nlargest(2,'HEIGHT',keep='all')
print(dfl)

HEIGHT  WEIGHT
A     170      50
D     160      80
E     160      90</pre>
<p>Сохраните последнее вхождение.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">dfl = df.nlargest(2,'HEIGHT',keep='last')
print(dfl)

HEIGHT  WEIGHT
A     170      50
E     160      90</pre>
<p><span>Сохраните первое вхождение.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">dfl = df.nlargest(2,'HEIGHT',keep='first')
print(dfl)

HEIGHT  WEIGHT
A     170      50
D     160      80</pre>
<p><span>Более подробную информацию о параметрах и других настройках см. в </span><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.nlargest.html" class="cq ih ks kt ku kv" target="_blank" rel="noopener nofollow noreferrer"><span>документации Pandas nlargest()</span></a><span>.</span></p>
<h2><strong><span style="color: #ff6600;">nsmallest()</span> &#8212; функция Python Pandas</strong></h2>
<p>nsmallest() также работает аналогичным образом, но с учетом самого маленького фильтра. Обратитесь к примеру ниже, в котором осуществляется поиск двух наименьших веса.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np
df = pd.DataFrame({'HEIGHT': [170,78,99,160,160,130,155,70,70,20],
                   'WEIGHT': [50,60,70,80,90,90,90,50,60,70]},
                   index=['A','B','C','D','E','F','G','H','I','J'])
print(df)

HEIGHT  WEIGHT
A     170      50
B      78      60
C      99      70
D     160      80
E     160      90
F     130      90
G     155      90
H      70      50
I      70      60
J      20      70

dfs = df.nsmallest(3,'WEIGHT')
print(dfs)

HEIGHT  WEIGHT
A     170      50
H      70      50
B      78      60</pre>
<p><span>Более подробную информацию о параметрах и других настройках см. в </span><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.Series.nsmallest.html#pandas.Series.nsmallest" class="cq ih ks kt ku kv" target="_blank" rel="noopener nofollow noreferrer"><span>документации Pandas nsmallest</span></a><span>.</span></p>
<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&amp;linkname=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2F5-useful-functions-of-pandas-python-for-data-science%2F&#038;title=5%20%D0%9F%D0%BE%D0%BB%D0%B5%D0%B7%D0%BD%D1%8B%D1%85%20%D1%84%D1%83%D0%BD%D0%BA%D1%86%D0%B8%D0%B9%20Python%20Pandas%20%D0%B4%D0%BB%D1%8F%20Data%20Science" data-a2a-url="https://python.ivan-shamaev.ru/5-useful-functions-of-pandas-python-for-data-science/" data-a2a-title="5 Полезных функций Python Pandas для Data Science"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/5-useful-functions-of-pandas-python-for-data-science/">5 Полезных функций Python Pandas для Data Science</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/5-useful-functions-of-pandas-python-for-data-science/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Очистка данных. Качество данных. Руководство по Data Cleaning</title>
		<link>https://python.ivan-shamaev.ru/data-cleaning-guide-data-quality/</link>
					<comments>https://python.ivan-shamaev.ru/data-cleaning-guide-data-quality/#respond</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Wed, 11 Mar 2020 05:53:41 +0000</pubDate>
				<category><![CDATA[Pandas. Обработка данных]]></category>
		<category><![CDATA[Data Cleaning]]></category>
		<category><![CDATA[Data Profiling]]></category>
		<category><![CDATA[Data Quality]]></category>
		<category><![CDATA[Качество данных]]></category>
		<category><![CDATA[Очистка данных]]></category>
		<category><![CDATA[Руководство по Data Cleaning]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=675</guid>

					<description><![CDATA[<p>Введение. Почему в сфере работы с данными важно уделять внимание очистке данных и качеству данных? Независимо от вашего опыта работы с данными и построения отчетности &#8212; плохие данные практически всегда приводят к неверным решениям. Независимо от класса информационных систем, профессиональности специалистов по работе с данными, всегда выполняется условие: Мусор на входе =&#62; мусор на выходе. [&#8230;]</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/data-cleaning-guide-data-quality/">Очистка данных. Качество данных. Руководство по Data Cleaning</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&#038;title=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" data-a2a-url="https://python.ivan-shamaev.ru/data-cleaning-guide-data-quality/" data-a2a-title="Очистка данных. Качество данных. Руководство по Data Cleaning"></a></p><h2><strong>Введение. Почему в сфере работы с данными важно уделять внимание очистке данных и качеству данных?</strong></h2>
<p>Независимо от вашего опыта работы с данными и построения отчетности &#8212; плохие данные практически всегда приводят к неверным решениям.</p>
<blockquote><p>Независимо от класса информационных систем, профессиональности специалистов по работе с данными, всегда выполняется условие:</p>
<p><strong>Мусор на входе =&gt; мусор на выходе.</strong></p></blockquote>
<p><strong>На качество данных в первую очередь влияют бизнес-процессы</strong>, которые организованы в компании <strong>по занесению бизнес-сущностей в информационную систему</strong>.</p>
<p><em>Например, как вводятся накладные, как разносятся накладные по платежкам, как выставляются счета. Все ли взаимосвязано для расчета дебиторской задолженности в автоматическом режиме и т.д. </em></p>
<p>За все это как раз и отвечают бизнес-процессы. Если компания маленькая, то все можно собрать в ручном режиме и бизнес-процессы (точнее их отсутствие) не оказывают большого влияния на бизнес. Но для среднего и крупного бизнеса бизнес-процессы по занесению и ведению информации &#8212; очень критичный вид деятельности.</p>
<p>Для любого специалиста по работе с данными очень важным &#171;параметром деятельности&#187; является авторитет данных, заработать который зачастую не так-то просто, а вот потерять его можно очень быстро.<br />
Если Вы на основе грязных данных разработаете отчеты, а потом скажете своей компании сделать что-то с этими результатами, которые окажутся неверными, то у Вас будет много неприятностей!</p>
<p>Неверные или противоречивые данные приводят к ложным выводам. То, насколько хорошо вы очищаете и понимаете данные, оказывает большое влияние на качество результатов.</p>
<p>Зачастую простой алгоритм может превзойти сложный алгоритм только потому, что ему были предоставлены более качественные данные.</p>
<blockquote><p><strong>Качество данных превосходит модные алгоритмы.</strong></p></blockquote>
<h2><strong>Что это означает качество данных? Каковы показатели качества данных?</strong></h2>
<p><span>Прежде чем предпринимать какие-либо действия, важно понять Вашу цель. Что Вы пытаетесь достичь, куда Вы хотите попасть в конце пути?</span></p>
<h3><strong>Качество данных &#8212; Data Quality (</strong><strong>Validity, A</strong><strong>ccuracy, </strong><strong>Completeness, </strong><strong>Consistency, </strong><strong>Uniformity)</strong></h3>
<p>Существует много определений качества данных, в общем, <strong>качество данных</strong> &#8212; это оценка того, насколько данные пригодны для использования и соответствуют его контексту обслуживания. Многие факторы помогают измерять качество данных, такие как: Согласованность данных, Точность данных, Уникальность данных, Полнота данных, Своевременность данных, Доступность и т.д.</p>
<h4 id="c093" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Достоверность данных &#8212; Validity</strong></h4>
<p id="4c27" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Степень, в которой данные соответствуют определенным бизнес-правилам или ограничениям.</span></p>
<ul class="">
<li id="4943" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm lj lk ll" data-selectable-paragraph=""><strong class="jd mb"><em class="jn"><span>Ограничения типа данных (Data-Type Constraints):</span></em></strong><span> значения в определенном столбце должны иметь определенный тип данных, например, логическое, числовое, формат даты и т.д.</span></li>
<li id="67a1" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><strong class="jd mb"><em class="jn"><span>Ограничения диапазона (Range Constraints):</span></em></strong><span> как правило, числа или даты должны попадать в определенный диапазон.</span></li>
<li id="c31b" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><strong class="jd mb"><em class="jn"><span>Обязательные ограничения (Mandatory Constraints)</span></em></strong><em class="jn"><span>:</span></em><span> некоторые столбцы не могут быть пустыми.</span></li>
<li id="e57b" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><strong class="jd mb"><em class="jn"><span>Ограничения уникальности (Unique Constraints):</span></em></strong><span> поле или комбинация полей должны быть уникальными в наборе данных.</span></li>
<li id="b2c4" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><strong class="jd mb"><em class="jn"><span>Ограничения Set-Membership</span></em><span>:</span></strong><span> значения столбца происходят из набора дискретных значений, например, пол человека может быть &#171;мужской&#187; или &#171;женский&#187;. Т.е. фиксированный, редко изменяемый набор значений (или никогда не изменяющийся).</span></li>
<li id="1ff7" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><strong class="jd mb"><em class="jn"><span>Ограничения внешнего ключа</span></em><span>:</span></strong><span> как и в реляционных базах данных, столбец внешнего ключа не может иметь значение, которого нет в указанном первичном ключе.</span></li>
<li id="f9b0" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><em><strong class="jd mb">Шаблоны регулярных выражений:</strong></em><span> текстовые поля, которые должны быть в определенном шаблоне. Например, для телефонных номеров может потребоваться шаблон (999) 999–9999.</span></li>
<li id="9ae1" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><em><strong>Проверка</strong></em><span><em><strong> между полями (Cross-field validation):</strong></em> должны выполняться определенные условия, охватывающие несколько полей. Например, дата выписки пациента из больницы не может быть раньше даты госпитализации.</span></li>
</ul>
<h4 id="beed" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Точность &#8212; Accuracy</strong></h4>
<p id="095c" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Степень, в которой данные близки к истинным значениям.</span></p>
<p id="40ab" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Хотя определение всех возможных допустимых значений позволяет легко обнаружить недействительные значения, это не означает, что они являются точными.</span></p>
<p id="d789" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span></span><em class="jn"><span>Действительный</span></em><span> почтовый адрес не может существовать на самом деле. А </span><em class="jn"><span>действительный</span></em><span> цвет глаз человека, скажем, синий, может быть действительным, но не соответствовать реальности.</span></p>
<p id="9883" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Еще одна вещь, которую следует отметить, это разница между достоверностью и точностью. Сказать, что вы живете на земле, на самом деле правда. Но не точно. Где на земле? Точнее сказать, что вы живете по определенному адресу.</span></p>
<h4 id="c93a" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Завершенность &#8212; Completeness</strong></h4>
<p id="e0a7" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Степень, в которой все необходимые данные известны.</span></p>
<p id="999b" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Отсутствие данных случается по разным причинам. Можно смягчить эту проблему, по возможности, задавая вопрос первоисточнику, скажем, повторное интервьюирование человека.</span></p>
<p id="94d1" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Скорее всего, субъект либо даст другой ответ, либо ответ будет трудно снова найти.</span></p>
<h4 id="7b19" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Консистенция &#8212; Consistency</strong></h4>
<p id="74e9" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Степень соответствия данных в одном наборе данных или в нескольких наборах данных.</span></p>
<p id="19e4" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Несоответствие возникает, когда два значения в наборе данных противоречат друг другу.</span></p>
<p id="d3cf" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Допустимый </span><em class="jn"></em><span>возраст, скажем, 10, может не совпадать с семейным положением, скажем, в разводе. Клиент записывается в две разные таблицы с двумя разными адресами.</span></p>
<p id="3201" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Какой из них является правдой?</span></p>
<h4 id="ee31" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Единообразие &#8212; Uniformity</strong></h4>
<p id="7427" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Степень, в которой данные указываются с использованием одной и той же единицы измерения.</span></p>
<p id="2685" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Вес может быть записан в фунтах или килограммах. Дата может соответствовать формату США или европейскому формату. Валюта иногда в долларах, а иногда в иенах.</span></p>
<p id="4306" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>И поэтому данные должны быть преобразованы в одну единицу измерения.</span></p>
<h3 id="dff3" class="lr kr cm ap ao ks fk ls fm lt lu lv lw lx ly lz ma"><strong>Рабочий процесс &#8212; Workflow (inspection, cleaning, verifying, reporting)</strong></h3>
<p id="2c73" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Рабочий процесс представляет собой последовательность из трех этапов, направленных на получение высококачественных данных, с учетом всех критериев, о которых мы говорили.</span></p>
<ol class="">
<li id="a074" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm mc lk ll" data-selectable-paragraph=""><strong class="jd mb"><span>Проверка (Inspection):</span></strong><span> обнаружение неожиданных, неправильных и противоречивых данных.</span></li>
<li id="636d" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm mc lk ll" data-selectable-paragraph=""><strong class="jd mb"><span>Очистка (Cleaning):</span></strong><span> исправить или удалить обнаруженные аномалии.</span></li>
<li id="2a00" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm mc lk ll" data-selectable-paragraph=""><strong class="jd mb"><span>Проверка (Verifying):</span></strong><span> После очистки результаты проверяются для проверки правильности.</span></li>
<li id="4a13" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm mc lk ll" data-selectable-paragraph=""><strong class="jd mb"><span>Отчетность (Reporting):</span></strong><span> записывается отчет об изменениях и качестве сохраненных данных.</span></li>
</ol>
<p id="1fcc" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>То, что вы видите как последовательный процесс, на самом деле является итеративным, бесконечным процессом. Можно переходить от проверки к проверке, когда обнаруживаются новые недостатки в данных.</span></p>
<h4 id="3def" class="lr kr cm ap ao ks fk ls fm lt lu lv lw lx ly lz ma"><strong>Проверка &#8212; Inspection</strong></h4>
<p id="99c3" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Проверка данных занимает много времени и требует использования многих методов для исследования основных данных для обнаружения ошибок. Вот некоторые из них:</span></p>
<h5 id="e545" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Профилирование данных &#8212; Data profiling</strong></h5>
<p id="7486" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span class="jd mb"><strong>Сводные </strong><b>статистические данные</b></span><span> о данных, которые называются профилирование данных, очень полезно, чтобы дать общее представление о качестве данных.</span></p>
<p id="ebc3" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Например, проверьте, соответствует ли определенный столбец определенным стандартам или образцу. Столбец данных записан в виде строки или числа?</span></p>
<p id="f9ae" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Сколько значений пропущено? Сколько уникальных значений в столбце и какого их распределение? Связан ли этот набор данных с другим набором данных?</span></p>
<h5 id="83d9" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Зрительные &#8212; Visualizations</strong></h5>
<p id="6bd6" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span><strong>Анализируя и визуализируя данные</strong> с использованием статистических методов, таких как среднее значение, стандартное отклонение, диапазон или квантили, можно найти значения, которые являются неожиданными и, наиболее вероятно, ошибочными.</span></p>
<p id="b455" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Например, визуализируя средний доход по странам, можно увидеть, что есть некоторые </span><strong class="jd mb"><span>выбросы</span></strong><span>. </span></p>
<p data-selectable-paragraph=""><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/some_outliers_data_quality.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/some_outliers_data_quality.png" alt="" width="869" height="453" class="aligncenter size-full wp-image-720" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/some_outliers_data_quality.png 869w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/some_outliers_data_quality-300x156.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/some_outliers_data_quality-768x400.png 768w" sizes="(max-width: 869px) 100vw, 869px" /></a></p>
<p class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>В некоторых странах есть люди, которые зарабатывают намного больше, чем кто-либо другой. <strong>Эти выбросы заслуживают изучения, но не обязательно, это это неверные данные.</strong></span><strong class="jd mb"></strong><em class="jn"><span></span></em><span></span></p>
<h5 id="98b3" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Пакеты программ &#8212; Software packages</strong></h5>
<p id="49fe" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Несколько пакетов программного обеспечения или библиотек, доступных на вашем языке, позволят вам указать ограничения и проверить данные на предмет нарушения этих ограничений.</span></p>
<p id="dd97" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Более того, они могут не только создать отчет о том, какие правила были нарушены и сколько раз, но также создать график того, какие столбцы связаны с какими правилами.</span></p>
<p data-selectable-paragraph=""><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality.png" alt="" width="1716" height="768" class="aligncenter size-full wp-image-692" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality.png 1716w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality-300x134.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality-1024x458.png 1024w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality-768x344.png 768w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality-1536x687.png 1536w" sizes="(max-width: 1716px) 100vw, 1716px" /></a> <a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality_2.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality_2.png" alt="" width="1406" height="1202" class="aligncenter size-full wp-image-693" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality_2.png 1406w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality_2-300x256.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality_2-1024x875.png 1024w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/edit_violation_frequency_of_top_10_edits_python_data_quality_2-768x657.png 768w" sizes="(max-width: 1406px) 100vw, 1406px" /></a><span>Возраст, например, не может быть отрицательным, а значит и рост. </span><span>Другие правила могут включать несколько столбцов в одной строке или в наборах данных.</span></p>
<h4 id="b498" class="lr kr cm ap ao ks fk ls fm lt lu lv lw lx ly lz ma"><strong>Очистка &#8212; Cleaning</strong></h4>
<p id="2960" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Очистка данных включает различные методы, основанные на проблемах и типах данных. Различные методы могут быть применены с каждым атрибутом данных, но имеют свои собственные особенности применения.</span></p>
<p id="b575" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>В целом, неверные данные либо удаляются, исправляются, либо присваиваются.</span></p>
<h5 id="d863" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Нерелевантные данные &#8212; Irrelevant data</strong></h5>
<p id="69df" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span><strong>Нерелевантные данные</strong> &#8212; это те, которые на самом деле не нужны и не вписываются в контекст проблемы, которую мы пытаемся решить.</span></p>
<p id="f178" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Например, если бы мы анализировали данные об общем состоянии здоровья населения, номер телефона не был бы необходим</span><span>.</span></p>
<p id="601f" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Точно так же, если бы вы были заинтересованы только в одной конкретной стране, вы не хотели бы включать в набор данных все другие страны. Или изучать только тех пациентов, которые ходили на операцию, мы бы не включали всех пациентов клиники</span><span>.</span></p>
<p id="c613" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>Только если</span></strong><span> вы уверены, что часть данных не важна, вы можете удалить ее. В противном случае изучите матрицу корреляции между атрибутами объекта.</span></p>
<p id="f7cb" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>И даже если вы не заметили никакой корреляции, вы должны спросить кого-то, кто является экспертом в области. Вы никогда не знаете, что функция, которая кажется неактуальной, может быть очень актуальной с точки зрения предметной области, например с клинической точки зрения.</span></p>
<h5 id="dfac" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Дубликаты &#8212; Duplicates</strong></h5>
<p id="f532" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span><strong>Дубликаты</strong> &#8212; это значения, которые повторяются в вашем наборе данных (повторяться могут как транзакции, так и сущности в различных справочниках).</span></p>
<p id="79f7" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong>Дублирование часто случается, когда, например,</strong></p>
<ul class="">
<li id="2e9b" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm lj lk ll" data-selectable-paragraph=""><span>Данные объединены из разных источников</span></li>
<li id="5884" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><span>Пользователь может дважды нажать кнопку «Отправить», думая, что форма фактически не была отправлена.</span></li>
<li id="6872" class="jb jc cm ap jd b gb lm gd ln jg lo ji lp jk lq jm lj lk ll" data-selectable-paragraph=""><span>Запрос на онлайн-бронирование был подан дважды, исправляя неверную информацию, которая была введена случайно в первый раз.</span></li>
</ul>
<p id="d7da" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Распространенным симптомом является случай, когда два пользователя имеют одинаковый идентификационный номер. Или одна и та же статья была отменена дважды.</span></p>
<p id="f906" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>И поэтому они просто должны быть удалены.</span></p>
<h5 id="bc9d" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Тип преобразования &#8212; Type conversion</strong></h5>
<p id="d2d6" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Убедитесь, что числа хранятся в виде числовых типов данных. Дата должна храниться в виде объекта даты или метки времени Unix (количество секунд) и т.д.</span></p>
<p id="3a23" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Категориальные значения могут быть преобразованы в/из чисел при необходимости.</span></p>
<p id="5d2a" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Это можно быстро определить, взглянув на типы данных каждого столбца в сводке (мы обсуждали выше).</span></p>
<p id="bcee" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span><strong>Предупреждение:</strong> значения, которые нельзя преобразовать в указанный тип, следует преобразовать в значение NA (или любое другое) с отображением <strong>предупреждения</strong>. Это указывает на неправильное значение, которое должно быть исправлено.</span></p>
<h5 id="1d29" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Синтаксические ошибки &#8212; Syntax errors</strong></h5>
<p id="3ee0" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>Удалить пробелы:</span></strong><span> следует удалить лишние пробелы в начале или конце строки.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">"   hello world  " =&gt; "hello world"</pre>
<p data-selectable-paragraph=""><strong>Строки заполнения:</strong><span> строки могут быть дополнены пробелами или другими символами до определенной ширины. </span><span>Например, некоторые числовые коды часто представлены с предшествующими нулями, чтобы они всегда имели одинаковое количество цифр.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">313 =&gt; 000313 (6 digits)</pre>
<p><strong class="jd mb"><span>Исправьте опечатки:</span></strong><span> строки могут быть введены разными способами, и неудивительно, что могут быть ошибки.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">Gender
m
Male
fem.
FemalE
Femle</pre>
<p><span>Считается, что эта категориальная переменная имеет 5 разных классов, а не 2, как ожидалось: мужской и женский, поскольку каждое значение различно.</span></p>
<blockquote><p>Bar plot полезно визуализировать все уникальные значения. Можно заметить, что некоторые значения различны, но означают одно и то же, то есть <strong>«information_technology» </strong>и<strong> «IT»</strong>. Или, возможно, разница только в заглавных буквах, то есть в <strong>«other»</strong> и <strong>«Other»</strong>.</p></blockquote>
<p id="8cdb" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Следовательно, наша обязанность состоит в том, чтобы по приведенным выше данным определить, является ли каждое значение мужским или женским. Как мы можем сделать это?.</span></p>
<p id="f147" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span><span style="color: #ff6600;"><strong>Первое решение</strong></span> состоит в том, чтобы вручную </span><strong class="jd mb"><span>сопоставить</span></strong><span> каждое значение с «мужской» или «женский».</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">dataframe['gender'].map({'m': 'male', fem.': 'female', ...})</pre>
<p><span><span style="color: #ff6600;"><strong>Второе решение</strong></span> &#8212; использовать </span><strong class="jd mb"><span>сопоставление с образцом</span></strong><span>. Например, мы можем искать вхождение m или M в поле в начале строки.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">re.sub (r "\ ^ m \ $", ' Male ', ' male ', flags = re. IGNORECASE )</pre>
<p><span><span style="color: #ff6600;"><strong>Третье решение</strong></span> заключается в использовании </span><strong class="jd mb"><span>нечеткого сопоставления</span></strong><span>: алгоритм, который определяет расстояние между ожидаемой строкой(-ами) и каждой из заданных. Его базовая реализация подсчитывает, сколько операций необходимо, чтобы превратить одну строку в другую.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">Gender   male  female
m         3      5
Male      1      3
fem.      5      3
FemalE    3      2
Femle     3      1</pre>
<p><span>Кроме того, если у вас есть переменная, такая как название города, вы подозреваете, что опечатки или похожие строки должны обрабатываться одинаково. </span></p>
<p><span>Например, “lisbon” можно ввести как “lisboa”, “lisbona”, “Lisbon”, и т.д.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">City     Distance from "lisbon"
lisbon       0
lisboa       1
Lisbon       1
lisbona      2
london       3
...</pre>
<p id="b3cc" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Если это так, то мы должны заменить все значения, которые означают одно и то же, на одно уникальное значение. В этом случае замените первые 4 строки на «lisbon».</span></p>
<blockquote class="jw jx jy">
<p id="cee5" class="jb jc cm jn jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Следите за значениями, такими как «0», «Не применимо», «NA», «None», «Null» или «INF», они могут означать одно и то же: <strong>значение отсутствует.</strong></span></p>
</blockquote>
<div class="n p">
<div class="z ab ac ae af fg ah ai">
<h5 id="c86b" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Стандартизация данных</strong></h5>
<p id="633b" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Наша обязанность &#8212; не только распознать опечатки, но и поместить каждое значение в один и тот же стандартизированный формат.</span></p>
<p id="4eec" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Для строк убедитесь, что все значения указаны в нижнем или верхнем регистре.</span></p>
<p id="441a" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Для числовых значений убедитесь, что все значения имеют определенную единицу измерения.</span></p>
<p id="45ec" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Высота, например, может быть в метрах и сантиметрах. Разница в 1 метр считается такой же, как разница в 1 сантиметр. Итак, задача здесь состоит в том, чтобы преобразовать высоты в одну единицу.</span></p>
<p id="6829" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Для дат, версия для США отличается от европейской версии. Запись даты в качестве метки времени (количество миллисекунд) не совпадает с записью даты в качестве объекта даты.</span></p>
<h5 id="d078" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Масштабирование / Преобразование &#8212; Scaling / Transformation</strong></h5>
<p id="f9b6" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Масштабирование означает преобразование ваших данных таким образом, чтобы они соответствовали определенному масштабу, например 0–100 или 0–1.</span></p>
<p id="6dc0" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Например, баллы по экзамену студента могут быть пересчитаны в процентах (0–100) вместо среднего балла (0–5).</span></p>
<p id="bf07" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Это также может помочь </span><span>упростить построение определенных типов данных</span><span>. Например, мы могли бы хотеть уменьшить асимметрию, чтобы помочь в построении графика (когда есть такое большое количество выбросов). Наиболее часто используемые функции &#8212; это log, square root и инверсия.</span></p>
<p id="b075" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Масштабирование также может выполняться для данных, которые имеют разные единицы измерения.</span></p>
<p id="5743" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Счета учеников на разных экзаменах, скажем, SAT и ACT, не могут сравниваться, поскольку эти два экзамена имеют разную шкалу. Разница в 1 балл SAT считается такой же, как разница в 1 балл ACT. В этом случае нам нужно </span><a href="https://medium.com/omarelgabrys-blog/statistics-probability-probability-distribution-35818d301cf4#fbef" class="bm dc ix iy iz ja" target="_blank" rel="noopener noreferrer"><span>изменить шкалу SAT и ACT,</span></a><span> чтобы взять числа, скажем, между 0–1.</span></p>
<blockquote>
<p id="b502" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong>Масштабируя, мы можем построить и сравнить различные оценки.</strong></p>
</blockquote>
<h5 id="4acb" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Нормализация &#8212; Normalization</strong></h5>
<p id="3451" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>В то время как нормализация также изменяет значения в диапазоне от 0 до 1, цель здесь состоит в том, чтобы преобразовать данные так, чтобы они нормально распределялись. </span></p>
<p class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><strong><em class="jn">Почему?</em></strong></p>
<p id="ea74" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>В большинстве случаев мы нормализуем данные, если будем использовать статистические методы, основанные на нормально распределенных данных. </span></p>
<p class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong><em class="jn">Как?</em></strong></p>
<p id="dc5a" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Можно использовать log функцию или, возможно, </span><a href="https://en.wikipedia.org/wiki/Normalization_(statistics)#Examples" class="bm dc ix iy iz ja" target="_blank" rel="noopener nofollow noreferrer"><span>использовать один из этих методов</span></a><span> .</span></p>
<blockquote class="jw jx jy">
<p id="c6d7" class="jb jc cm jn jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>В зависимости от используемого метода масштабирования форма распределения данных может измениться.Например, «</span><a href="https://en.wikipedia.org/wiki/Standard_score" class="bm dc ix iy iz ja" target="_blank" rel="noopener nofollow noreferrer"><span>Стандартная оценка Z</span></a><span>» и «</span><a href="https://en.wikipedia.org/wiki/Student%27s_t-statistic" class="bm dc ix iy iz ja" target="_blank" rel="noopener nofollow noreferrer"><span>t-статистика Стьюдента</span></a><span>» (приведенные в ссылке выше) сохраняют форму, в то время как log функция не может.</span></p>
</blockquote>
<p data-selectable-paragraph=""><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/Normalization_vs_Scaling_using_Feature_scaling_1.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/Normalization_vs_Scaling_using_Feature_scaling_1.png" alt="" width="640" height="480" class="aligncenter size-full wp-image-695" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/Normalization_vs_Scaling_using_Feature_scaling_1.png 640w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/Normalization_vs_Scaling_using_Feature_scaling_1-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></a> <a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/Normalization_vs_Scaling_using_Feature_scaling_2.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/Normalization_vs_Scaling_using_Feature_scaling_2.png" alt="" width="640" height="480" class="aligncenter size-full wp-image-696" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/Normalization_vs_Scaling_using_Feature_scaling_2.png 640w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/Normalization_vs_Scaling_using_Feature_scaling_2-300x225.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>
<h5 id="cbda" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Недостающие значения &#8212; Missing values</strong></h5>
<p id="ccf6" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Учитывая тот факт, что отсутствующие значения неизбежны, возникает вопрос: что делать, когда мы сталкиваемся с ними? <strong>Игнорирование пропущенных данных</strong> &#8212; это то же самое, что создание дыр в лодке &#8212; она будет тонуть.</span></p>
<p id="d84c" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Есть три, или, возможно, больше, способов справиться с ними.</span></p>
<h6 id="8ade" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>&#8212; Первый способ. Удаление &#8212; Drop.</strong></h6>
<p id="b4de" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Если пропущенные значения в столбце встречаются редко и происходят случайным образом, то самое простое и прямое решение &#8212; отбросить наблюдения (строки) с пропущенными значениями.</span></p>
<p id="8b39" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Если большинство значений столбца отсутствуют и встречаются случайным образом, типичным решением является удаление всего столбца.</span></p>
<p id="a930" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Это особенно полезно при проведении статистического анализа, поскольку заполнение пропущенных значений может привести к неожиданным или необъективным результатам.</span></p>
<h6 id="e0af" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>&#8212; Второй способ. Внести значение &#8212; Impute.</strong></h6>
<p id="695f" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Это значит рассчитать недостающее значение на основе других наблюдений. Есть много способов сделать это.</span></p>
<p id="54aa" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>&#8212; Сначала</span></strong><span> используются </span><strong class="jd mb"><span>статистические значения,</span></strong><span> такие как среднее значение, медиана. Тем не менее, ни один из них не гарантирует непредвзятых данных, особенно если есть много пропущенных значений.</span></p>
<p id="51fb" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Среднее значение наиболее полезно, когда исходные данные не </span><span>искажены</span><span>, а </span><span>медиана более устойчива</span><span>, не чувствительна к выбросам и, таким образом, используется при искажении данных.</span></p>
<p id="d499" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>В нормально распределенных данных можно получить все значения, которые находятся в пределах 2 стандартных отклонений от среднего. Затем, заполните пропущенные значения, генерируя случайные числа между </span><code class="im nk nl nm nc b">(mean — 2 * std) &amp; (mean + 2 * std)</code></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">rand = np.random.randint(average_age - 2*std_age, average_age + 2*std_age, size = count_nan_age)
dataframe["age"][np.isnan(dataframe["age"])] = rand</pre>
<p id="d43b" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>Второе</span></strong><span>. Используя </span><strong class="jd mb"><span>линейную регрессию</span></strong><span>. На основании существующих данных можно рассчитать линию наилучшего соответствия между двумя переменными, скажем, цена дома против размера м².</span></p>
<p id="9edb" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Стоит отметить, что модели линейной регрессии чувствительны к выбросам.</span></p>
<p id="db08" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>&#8212; в-третьих</span></strong><span>. </span><strong class="jd mb"><span>Hot-deck</span></strong><span>: Копирование значений из других похожих записей. Это полезно, только если у вас достаточно доступных данных. И это может быть применено к числовым и категориальным данным.</span></p>
<p id="ab57" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Можно использовать случайный подход, где мы заполняем отсутствующее значение </span><strong class="jd mb"><span>случайным</span></strong><span> значением. Сделав этот подход еще на шаг вперед, можно сначала разделить набор данных на </span><strong class="jd mb"><span>две группы (страты)</span></strong><span> на основе некоторой характеристики, например, пола, а затем заполнить пропущенные значения для разных полов по отдельности, случайным образом.</span></p>
<p id="2d8d" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>При </span><strong class="jd mb"><span>последовательном</span></strong><span> вменении «горячей колоды» столбец, содержащий пропущенные значения, сортируется в соответствии со </span><span>вспомогательной(-ыми</span><span> ) переменной(-ами), поэтому записи, имеющие похожие вспомогательные элементы, появляются последовательно. Затем каждое пропущенное значение заполняется значением первой следующей доступной записи.</span></p>
<p id="2ad5" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Что еще интереснее, так это то, что </span><strong class="jd mb"><span>вложение ближайшего</span></strong><span> соседа, которое классифицирует похожие записи и объединяет их, также может быть использовано. Пропущенное значение затем заполняется путем нахождения первых ? записей, ближайших к записи с пропущенными значениями. Затем значение выбирается из (или вычисляется из) ? ближайших соседей. В случае вычислений могут использоваться статистические методы, такие как среднее (как обсуждалось ранее).</span></p>
<h6 id="c9d0" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>&#8212; Третье. Flag.</strong></h6>
<p id="f953" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Некоторые утверждают, что заполнение пропущенных значений приводит к потере информации, независимо от того, какой метод вменения мы использовали.</span></p>
<p id="5281" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Это потому, что утверждение о том, что данные отсутствуют, само по себе информативно, и алгоритм должен знать об этом. В противном случае мы просто усиливаем шаблон, уже существующий другими функциями.</span></p>
<p id="1d8b" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Это особенно важно, когда пропущенные данные не случаются случайно. Возьмем, к примеру, проведенный опрос, в котором большинство людей из определенной расы отказываются отвечать на определенный вопрос.</span></p>
<p id="0230" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Пропущенные </span><strong class="jd mb"><span>числовые данные</span></strong><span> можно заполнить, скажем, 0, но эти нули необходимо игнорировать при вычислении любого статистического значения или построении графика распределения.</span></p>
<p id="ff76" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>В то время как </span><strong class="jd mb"><span>категориальные данные</span></strong><span> могут быть заполнены, скажем, «Отсутствует»: новая категория, которая сообщает, что этот фрагмент данных отсутствует.</span></p>
<h6 id="6eb9" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>&#8212; Принимать во внимание …</strong></h6>
<p id="6c2f" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Отсутствующие значения не совпадают со значениями по умолчанию. Например, ноль можно интерпретировать как отсутствующий или по умолчанию, но не оба.</span></p>
<p id="c328" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Отсутствующие значения не являются «неизвестными». Проведенное исследование, в котором некоторые люди не помнят, подвергались ли они издевательствам в школе или нет, должно рассматриваться и обозначаться как неизвестное и не пропущенное.</span></p>
<p id="c575" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Каждый раз, когда мы отбрасываем или приписываем значение, мы теряем информацию. Таким образом, пометка может прийти на помощь.</span></p>
<h5 id="ff4c" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Выпадающие значения &#8212; Outliers</strong></h5>
<p id="567f" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Это значения, которые значительно отличаются от всех других наблюдений. Любое значение данных, которое </span><a href="https://medium.com/omarelgabrys-blog/statistics-probability-exploratory-data-analysis-714f361b43d1#48f7" class="bm dc ix iy iz ja" target="_blank" rel="noopener noreferrer"><span>находится на расстоянии более (1,5 * IQR) от квартилей Q1 и Q3,</span></a><span> считается выбросом.</span></p>
<p id="65aa" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Выбросы невиновны, пока их вина не доказана. С учетом сказанного, их не следует удалять, если для этого нет веских причин.</span></p>
<p id="c610" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Например, можно заметить некоторые странные, подозрительные значения, которые вряд ли произойдут, и поэтому решает удалить их. Тем не менее, они заслуживают расследования, прежде чем удалить.</span></p>
<p id="50c7" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Стоит также отметить, что некоторые модели, такие как линейная регрессия, очень чувствительны к выбросам. Другими словами, выбросы могут отбросить модель, из которой собрана большая часть данных.</span></p>
<h5 id="f083" class="kq kr cm ap ao ks kt ku kv kw kx ky kz la lb lc ld"><strong>Ошибки в записях и между наборами данных &#8212; In-record &amp; cross-datasets errors</strong></h5>
<p id="4ecd" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Эти ошибки возникают из-за наличия двух или более значений в одной строке или между наборами данных, которые противоречат друг другу.</span></p>
<p id="f197" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Например, если у нас есть набор данных о стоимости жизни в городах. Общая колонка должна быть эквивалентна сумме арендной платы, транспорта и еды.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">city       rent  transportation food  total
libson     500        20         40    560
paris      750        40         60    850</pre>
<p id="284b" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Точно так же ребенок не может быть женат. Заработная плата работника не может быть меньше рассчитанных налогов.</span></p>
<p id="f319" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Та же идея применима к связанным данным в разных наборах данных.</span></p>
<h4 id="d05b" class="lr kr cm ap ao ks fk ls fm lt lu lv lw lx ly lz ma"><strong>Проверка (Верификация) &#8212; Verifying</strong></h4>
<p id="0cee" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Когда это сделано, следует проверить правильность, повторно проверив данные и убедившись, что они соблюдают правила и ограничения.</span></p>
<p id="10ee" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Например, после заполнения отсутствующих данных они могут нарушить любое из правил и ограничений.</span></p>
<p id="3c6c" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Это может потребовать некоторой ручной коррекции, если не возможно иначе.</span></p>
<h4 id="2380" class="lr kr cm ap ao ks fk ls fm lt lu lv lw lx ly lz ma"><strong>Составление отчетов &#8212; Reporting</strong></h4>
<p id="b8e6" class="jb jc cm ap jd b gb le gd lf jg lg ji lh jk li jm fb" data-selectable-paragraph=""><span>Отчет о том, насколько здоровы данные, одинаково важен для очистки.</span></p>
<p id="d430" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Как упоминалось ранее, программные пакеты или библиотеки могут генерировать отчеты о внесенных изменениях, какие правила были нарушены и сколько раз.</span></p>
<p id="874c" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Помимо регистрации нарушений, следует учитывать причины этих ошибок. Почему они произошли в первую очередь?</span></p>
<h2 id="751c" class="lr kr cm ap ao ks fk ls fm lt lu lv lw lx ly lz ma"><strong>Заключительная часть</strong></h2>
<p id="00ba" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Независимо от того, насколько надежным и сильным является процесс проверки и очистки, он будет страдать по мере поступления новых данных.</span></p>
<p id="fe28" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Лучше защититься от болезни, чем тратить время и силы на ее устранение.</span></p>
<p id="8044" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Эти вопросы помогают оценить и улучшить качество данных:</span></p>
<p id="883d" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>Как собираются данные и при каких условиях? </span></strong><span>Среда, в которой были собраны данные, </span><em class="jn"><span>имеет</span></em><span> значение. Окружающая среда включает в себя, помимо прочего, местоположение, время, погодные условия и т.д.</span></p>
<p id="1841" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><span>Опрос субъектов по поводу их мнения относительно </span><em class="jn"><span>независимо</span></em><span>, пока они находятся на пути к работе не то же самое, в то время как они у себя дома. Пациенты в исследовании, которые испытывают трудности с использованием таблеток для ответа на вопросник, могут отбросить результаты.</span></p>
<p id="38d8" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>Что представляют собой данные? </span></strong><span>Они включают всех? Только люди в городе? Или, возможно, только те, кто решил ответить, потому что у них было твердое мнение по теме.</span></p>
<p id="09bd" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>Какие методы используются для очистки данных и почему? </span></strong><span>Различные методы могут быть лучше в разных ситуациях или с разными типами данных.</span></p>
<p id="7a3c" class="jb jc cm ap jd b gb je gd jf jg jh ji jj jk jl jm fb" data-selectable-paragraph=""><strong class="jd mb"><span>Вы вкладываете время и деньги в улучшение процесса? </span></strong><span>Инвестиции в людей и процесс так же важны, как и инвестиции в технологии.</span></p>
<h2><strong>Профилирование данных в Python 3 с помощью Pandas</strong></h2>
<p><span>Любой, кто работает с данными в Python, знаком с пакетом pandas. </span><span>Если это не так, pandas &#8212; это пакет для большинства данных, отформатированных по строкам и столбцам. </span><span>Если у вас еще нет библиотеки Pandas, обязательно установите ее, используя pip install в предпочитаемом вами терминале:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">pip install pandas</pre>
<p><span>Теперь давайте посмотрим, что может сделать для нас реализация pandas по умолчанию:</span></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_1.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_1.png" alt="" width="790" height="498" class="aligncenter size-full wp-image-744" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_1.png 790w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_1-300x189.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_1-768x484.png 768w" sizes="(max-width: 790px) 100vw, 790px" /></a></p>
<p>Любой &#8216;DataFrame&#8217; в Pandas имеет метод .describe(), который возвращает приведенную выше сводку. Однако обратите внимание, что в выходных данных этого метода категориальные переменные отсутствуют. В приведенном выше примере столбец «method» полностью исключен из вывода!</p>
<h3><strong>Pandas Data Profiling</strong></h3>
<p>В этом разделе будет описана библиотека <strong>&#171;Pandas Profiling&#187;. </strong>Эта библиотека формирует многостраничный отчет (на картинке ниже только небольшая часть этого отчета).</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_2.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_2.png" alt="" width="843" height="528" class="aligncenter size-full wp-image-747" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_2.png 843w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_2-300x188.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_2-768x481.png 768w" sizes="(max-width: 843px) 100vw, 843px" /></a></p>
<p id="e2c1" class="hw hx dt ar hy b hz ia ib ic id ie if ig ih ii ij dl" data-selectable-paragraph=""><span>Как бы вам понравилось, если бы я сказал вам, что смогу создать следующую статистику всего с 3 строками Python </span><em class="kl"><span>(фактически, только с </span></em><strong class="hy jq"><em class="kl"><span>1 строкой, если мы не посчитаем наш импорт.)</span></em><span> :</span></strong></p>
<ul class="">
<li id="b8c4" class="hw hx dt ar hy b hz ia ib ic id ie if ig ih ii ij ko kp kq" data-selectable-paragraph=""><strong class="hy jq"><span>Основы</span></strong><span> : тип, уникальные значения, пропущенные значения</span></li>
<li id="af4e" class="hw hx dt ar hy b hz kr ib ks id kt if ku ih kv ij ko kp kq" data-selectable-paragraph=""><strong class="hy jq"><span>Квантильная статистика,</span></strong><span> такая как минимальное значение, Q1, медиана, Q3, максимум, диапазон, межквартильный диапазон</span></li>
<li id="5b59" class="hw hx dt ar hy b hz kr ib ks id kt if ku ih kv ij ko kp kq" data-selectable-paragraph=""><strong class="hy jq"><span>Описательные статистические данные,</span></strong><span> такие как среднее значение, мода, стандартное отклонение, сумма, среднее абсолютное отклонение, коэффициент вариации, эксцесс, асимметрия</span></li>
<li id="a9b9" class="hw hx dt ar hy b hz kr ib ks id kt if ku ih kv ij ko kp kq" data-selectable-paragraph=""><strong class="hy jq"><span>Наиболее частые значения</span></strong></li>
<li id="9275" class="hw hx dt ar hy b hz kr ib ks id kt if ku ih kv ij ko kp kq" data-selectable-paragraph=""><strong class="hy jq"><span>Гистограмма</span></strong></li>
<li id="094e" class="hw hx dt ar hy b hz kr ib ks id kt if ku ih kv ij ko kp kq" data-selectable-paragraph=""><strong class="hy jq"><span>Выделение корреляций</span></strong><span> высококоррелированных переменных, матрицы Спирмена, Пирсона и Кендалла</span></li>
<li id="370e" class="hw hx dt ar hy b hz kr ib ks id kt if ku ih kv ij ko kp kq" data-selectable-paragraph=""><strong class="hy jq"><span></span></strong><span>Матрица <strong class="hy jq">отсутствующих значений</strong> , счетчик, тепловая карта и дендрограмма отсутствующих значений</span></li>
</ul>
<p id="f512" class="hw hx dt ar hy b hz ia ib ic id ie if ig ih ii ij dl" data-selectable-paragraph=""><em class="kl"><span>(Список функций прямо из </span></em><a href="https://github.com/pandas-profiling/pandas-profiling" class="cq fx jm jn jo jp" target="_blank" rel="noopener nofollow noreferrer"><em class="kl"><span>GitHub для профилирования Pandas</span></em></a><em class="kl"><span> )</span></em></p>
<p data-selectable-paragraph=""><span>Используя пакет Pandas Profiling!</span><br />
<span>Чтобы установить пакет Pandas Profiling, просто используйте pip install в своем терминале:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">pip install pandas_profiling</pre>
<p><span>Опытные аналитики данных на первый взгляд могут посмеяться над тем, что они пушистые и кричащие, но это, безусловно, может быть полезно для быстрого получения непосредственного представления о ваших данных:</span></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_3.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_3.png" alt="" width="904" height="65" class="aligncenter size-full wp-image-748" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_3.png 904w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_3-300x22.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_3-768x55.png 768w" sizes="(max-width: 904px) 100vw, 904px" /></a></p>
<p id="9fb2" class="hw hx dt ar hy b hz ia ib ic id ie if ig ih ii ij dl" data-selectable-paragraph=""><span>Первое, что вы увидите, это </span><strong class="hy jq"><span>обзор</span></strong><span> (см. Рисунок выше), который дает вам очень высокую статистику ваших данных и переменных, а также </span><strong class="hy jq"><span>предупреждения,</span></strong><span> такие как высокая корреляция между переменными, высокая асимметрия и многое другое.</span></p>
<p id="8418" class="hw hx dt ar hy b hz ia ib ic id ie if ig ih ii ij dl" data-selectable-paragraph=""><span>Но это даже не близко ко всему. Прокручивая вниз, мы обнаруживаем, что этот отчет состоит из нескольких частей. Просто показывать результат этого 1-линейного с картинками не будет справедливо, поэтому я вместо этого сделал GIF:</span></p>
<p data-selectable-paragraph=""><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_4.gif"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2020/03/data_profiling_python_3_pandas_4.gif" alt="" width="600" height="555" class="aligncenter size-full wp-image-749" /></a></p>
<p data-selectable-paragraph=""><span>Я настоятельно рекомендую вам изучить возможности этого пакета самостоятельно &#8212; в конце концов &#8212; это всего лишь одна строка кода, и вы можете найти ее полезной для дальнейшего анализа данных.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import pandas_profiling
pd.read_csv('https://raw.githubusercontent.com/mwaskom/seaborn-data/master/planets.csv').profile_report()</pre>
</div>
</div>
<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&amp;linkname=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fdata-cleaning-guide-data-quality%2F&#038;title=%D0%9E%D1%87%D0%B8%D1%81%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%9A%D0%B0%D1%87%D0%B5%D1%81%D1%82%D0%B2%D0%BE%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85.%20%D0%A0%D1%83%D0%BA%D0%BE%D0%B2%D0%BE%D0%B4%D1%81%D1%82%D0%B2%D0%BE%20%D0%BF%D0%BE%20Data%20Cleaning" data-a2a-url="https://python.ivan-shamaev.ru/data-cleaning-guide-data-quality/" data-a2a-title="Очистка данных. Качество данных. Руководство по Data Cleaning"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/data-cleaning-guide-data-quality/">Очистка данных. Качество данных. Руководство по Data Cleaning</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/data-cleaning-guide-data-quality/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python 3 Tutorial &#8212; Data Wrangling &#8212; Обработка данных по криптовалютам</title>
		<link>https://python.ivan-shamaev.ru/python-data-wrangling-tutorial-for-cryptocurrency/</link>
					<comments>https://python.ivan-shamaev.ru/python-data-wrangling-tutorial-for-cryptocurrency/#respond</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Fri, 29 Nov 2019 22:30:33 +0000</pubDate>
				<category><![CDATA[Pandas. Обработка данных]]></category>
		<category><![CDATA[Python Finance]]></category>
		<category><![CDATA[Cryptocurrency Data Wrangling]]></category>
		<category><![CDATA[Data Wrangling]]></category>
		<category><![CDATA[Data Wrangling Tutorial]]></category>
		<category><![CDATA[Python Cryptocurrency]]></category>
		<category><![CDATA[Python Data Wrangling]]></category>
		<category><![CDATA[Python For Finance]]></category>
		<category><![CDATA[Python Tutorial]]></category>
		<category><![CDATA[Обработка данных по криптовалютам]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=366</guid>

					<description><![CDATA[<p>Вводная часть по Python 3 Tutorial &#8212; Data Wrangling Биткойн и криптовалюта сейчас в тренде&#8230; но как специалисты по данным, мы эмпиристы, верно? Мы не хотим просто поверить на слово другим&#8230; мы хотим посмотреть на данные из первых рук! В этом уроке будут описаны общие и мощные методы обработки данных в Python. Python 3 Tutorial [&#8230;]</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/python-data-wrangling-tutorial-for-cryptocurrency/">Python 3 Tutorial &#8212; Data Wrangling &#8212; Обработка данных по криптовалютам</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&#038;title=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" data-a2a-url="https://python.ivan-shamaev.ru/python-data-wrangling-tutorial-for-cryptocurrency/" data-a2a-title="Python 3 Tutorial — Data Wrangling — Обработка данных по криптовалютам"></a></p><h2><strong>Вводная часть по Python 3 Tutorial &#8212; Data Wrangling</strong></h2>
<p><strong>Биткойн и криптовалюта сейчас в тренде</strong>&#8230; но как специалисты по данным, мы эмпиристы, верно? Мы не хотим просто поверить на слово другим&#8230; мы хотим посмотреть на данные из первых рук! <strong>В этом уроке будут описаны общие и мощные методы обработки данных в Python.</strong></p>
<blockquote>
<p><span style="color: #993366;"><em>Python 3 Tutorial &#8212; Data Wrangling</em></span></p>
</blockquote>
<p>Вообще говоря, <strong>обработка данных (Data Wrangling)</strong> &#8212; это процесс преобразования, агрегирования, разделения или иного преобразования ваших данных из одного формата в более подходящий.</p>
<p>Например, мы хотим <strong>провести пошаговый анализ очень элементарной торговой стратегии</strong>, которая выглядит следующим образом:</p>
<ol>
<li>В начале каждого месяца мы покупаем криптовалюту, которая имела наибольший прирост цены за последние 7, 14, 21 или 28 дней. Мы хотим оценить каждое из этих временных окон.</li>
<li>Затем мы держим ровно 7 дней и продаем нашу позицию. Обратите внимание: это целенаправленно простая стратегия, которая предназначена только для иллюстративных целей.</li>
</ol>
<p><strong>Как мы будем оценивать эту стратегию?</strong></p>
<p>Это хороший вопрос для демонстрации методов обработки данных, потому что вся тяжелая работа заключается в преобразовании вашего набора данных в правильный формат. Когда у вас есть соответствующая аналитическая базовая таблица (analytical base table, ABT), ответить на вопрос становится просто.</p>
<p><strong>Чем это руководство не является:</strong></p>
<p>Это не руководство по инвестиционным или торговым стратегиям, и не призыв за или против торговли криптовалютами. Потенциальные инвесторы должны самостоятельно формировать свои взгляды, но в этом руководстве будут представлены инструменты для этого.</p>
<p>Опять же, основное внимание в этом руководстве уделяется методам обработки данных и возможности преобразования необработанных наборов данных в форматы, которые помогут вам ответить на интересные вопросы.</p>
<p><strong>Быстрый совет, прежде чем мы начнем:</strong></p>
<p>Этот учебник предназначен для быстрого ознакомления, и он не будет охватывать ни одну тему слишком подробно. Ознакомьтесь дополнительно с <a href="https://python.ivan-shamaev.ru/pandas-series-and-dataframe-objects-build-index/" target="_blank" rel="noopener noreferrer"><strong>Tutorial по библиотеке Pandas</strong></a>.</p>
<h2><strong>Содержание учебника по обработке данных Python &#8212; Data Wrangling Tutorial</strong></h2>
<p><strong>Вот шаги, которые мы пройдем в рамках нашего анализа:</strong></p>
<ol>
<li>Настройка среды.</li>
<li>Импорт библиотек и наборов данных.</li>
<li>Первичное знакомство с данными.</li>
<li>Фильтр нежелательных наблюдений (подмножеств).</li>
<li>Вращение набора данных &#8212; Pivot the dataset.</li>
<li>Сдвиг развернутого набора данных &#8212; Shift the pivoted dataset.</li>
<li>Melt сдвинутого набора данных &#8212; Melt the shifted dataset.</li>
<li>Уменьшение-объединение (Reduce-merge) melted data.</li>
<li>Агрегация данных с помощью group-by.</li>
</ol>
<h3><strong>Шаг 1. Настройка среды программирования Python</strong></h3>
<p><strong>Сначала убедитесь, что на вашем компьютере установлено ПО:</strong></p>
<ul>
<li>Python 2.7+ или Python 3</li>
<li>Pandas</li>
<li>Jupyter Notebook (необязательно, но рекомендуется)</li>
</ul>
<p>Мы настоятельно рекомендуем установить дистрибутив <a href="https://www.anaconda.com/" target="_blank" rel="noopener noreferrer"><strong>Anaconda</strong></a>, который поставляется со всеми этими пакетами. Просто следуйте инструкциям на этой странице загрузки.</p>
<blockquote>
<p><strong>Jupyter Notebook</strong> – это бесплатная интерактивная оболочка для языка программирования <strong>Python</strong>, позволяющая объединить <em><strong>код, изображения, комментарии, формулы и графики/диаграммы</strong></em>.</p>
</blockquote>
<p>После установки Anaconda запустите Jupyter Notebook (Anaconda3):</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_notebook_anaconda3.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_notebook_anaconda3.png" alt="" width="513" height="678" class="aligncenter size-full wp-image-381" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_notebook_anaconda3.png 513w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_notebook_anaconda3-227x300.png 227w" sizes="(max-width: 513px) 100vw, 513px" /></a></p>
<p>Откроется окно в браузере. В нем создайте новое окно Python3:</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_create_new_notebook_with_python3.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_create_new_notebook_with_python3.png" alt="" width="1365" height="425" class="aligncenter size-full wp-image-382" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_create_new_notebook_with_python3.png 1365w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_create_new_notebook_with_python3-300x93.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_create_new_notebook_with_python3-1024x319.png 1024w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_create_new_notebook_with_python3-768x239.png 768w" sizes="(max-width: 1365px) 100vw, 1365px" /></a></p>
<p>Откроется новая вкладка, на ней Вы можете поменять название документа.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_new_doc_name_line_program.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_new_doc_name_line_program.png" alt="" width="852" height="337" class="aligncenter size-full wp-image-384" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_new_doc_name_line_program.png 852w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_new_doc_name_line_program-300x119.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step1_jupyter_new_doc_name_line_program-768x304.png 768w" sizes="(max-width: 852px) 100vw, 852px" /></a></p>
<h4>Интерфейс Jupyter Notebook</h4>
<p><strong>В Jupyter Notebook</strong> есть два важных термина: <strong>cells (ячейки)</strong> и <strong>kernels (ядра)</strong> являются ключом как к пониманию Jupyter.</p>
<ul>
<li><strong>kernel (Ядро)</strong> – это <strong>«вычислительный движок»</strong>, который выполняет код, содержащийся в документе Notebook.</li>
<li><strong>cell (Ячейка)</strong> – это контейнер для текста, который будет отображаться в Notebook, или код, который будет выполняться ядром записной книжки.</li>
</ul>
<h4><strong>Запуск и прерывание выполнения кода в Jupyter Notebook</strong></h4>
<p><span>Если ваша программа зависла, то можно прервать ее выполнение выбрав на панели меню пункт <strong>Kernel -&gt; Interrupt.</strong></span></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_kernel_interrupt.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_kernel_interrupt.png" alt="" width="746" height="246" class="aligncenter size-full wp-image-422" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_kernel_interrupt.png 746w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_kernel_interrupt-300x99.png 300w" sizes="(max-width: 746px) 100vw, 746px" /></a></p>
<p><span>Для добавления новой ячейки используйте <strong>Insert-&gt;Insert Cell Above</strong> и <strong>Insert-&gt;Insert Cell Below</strong>.</span></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_insert_cell_above_below.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_insert_cell_above_below.png" alt="" width="589" height="182" class="aligncenter size-full wp-image-424" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_insert_cell_above_below.png 589w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_insert_cell_above_below-300x93.png 300w" sizes="(max-width: 589px) 100vw, 589px" /></a></p>
<p><span>Для запуска ячейки используете команды из меню <strong>Cell</strong>, либо следующие сочетания клавиш:</span></p>
<ul>
<li><span><strong>Ctrl+Enter</strong> – выполнить содержимое ячейки.</span></li>
<li><span><strong>Shift+Enter</strong> – выполнить содержимое ячейки и перейти на ячейку ниже.</span></li>
<li><span><strong>Alt+Enter</strong> – выполнить содержимое ячейки и вставить новую ячейку ниже.</span></li>
</ul>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_cell_run_cells_all_above_below_menu_python3.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_cell_run_cells_all_above_below_menu_python3.png" alt="" width="558" height="309" class="aligncenter size-full wp-image-425" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_cell_run_cells_all_above_below_menu_python3.png 558w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/jupyter_cell_run_cells_all_above_below_menu_python3-300x166.png 300w" sizes="(max-width: 558px) 100vw, 558px" /></a></p>
<h3><strong>Шаг 2: Импортируем библиотеки и загружаем набор данных</strong></h3>
<p>Сначала мы импортируем библиотеку Pandas (лучшая библиотека для обработки реляционных наборов данных в табличном формате).<br>Библиотеке Pandas мы дадим alias (псевдоним). Позже мы сможем вызывать библиотеку с помощью pd.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Pandas for managing datasets
import pandas as pd</pre>
<p>Далее, давайте немного подправим параметры отображения чисел. Во-первых, давайте отобразим числа с плавающей точкой с двумя десятичными разрядами, чтобы сделать таблицы менее загруженными. Не волнуйтесь &#8212; это только настройка дисплея, которая не снижает основную точность. Давайте также расширим ограничения на количество отображаемых строк и столбцов.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Display floats with 2 decimal places
pd.options.display.float_format = '{:,.2f}'.format
 
# Expand display limits
pd.options.display.max_rows = 200
pd.options.display.max_columns = 100</pre>
<p>В этом уроке мы будем использовать набор данных о ценах Brave New Coin и распространяемый в Quandl. Полная версия отслеживает индексы цен для 1900+ фиат-крипто трейдинговых пар, но требует премиальной подписки, поэтому мы предоставили небольшую выборку с небольшим количеством криптовалют.</p>
<p>Чтобы использовать набор данных в своей программе скачайте файл <strong><a href="https://drive.google.com/file/d/1zgKTySGWDzrf4OE9Cs22ueS0_ZNg69YJ/view?usp=sharing" target="_blank" rel="noopener noreferrer">BNC2_sample.csv</a></strong>.</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_dataset_crypto.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_dataset_crypto.png" alt="" width="1365" height="505" class="aligncenter size-full wp-image-393" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_dataset_crypto.png 1365w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_dataset_crypto-300x111.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_dataset_crypto-1024x379.png 1024w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_dataset_crypto-768x284.png 768w" sizes="(max-width: 1365px) 100vw, 1365px" /></a></p>
<p>После того, как вы скачали набор данных, разместите его в том же каталоге, что и сохраненный блокнот.</p>
<p>Набор данных можно загрузить как непосредственно в директорию на диске в windows:</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_directory.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_directory.png" alt="" width="835" height="395" class="aligncenter size-full wp-image-395" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_directory.png 835w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_directory-300x142.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_directory-768x363.png 768w" sizes="(max-width: 835px) 100vw, 835px" /></a></p>
<p>Также можно загрузить файл из интерфейса Jupyter:</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_upload_dataset_file_into_jupyter_folder.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_upload_dataset_file_into_jupyter_folder.png" alt="" width="1365" height="584" class="aligncenter size-full wp-image-396" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_upload_dataset_file_into_jupyter_folder.png 1365w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_upload_dataset_file_into_jupyter_folder-300x128.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_upload_dataset_file_into_jupyter_folder-1024x438.png 1024w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_upload_dataset_file_into_jupyter_folder-768x329.png 768w" sizes="(max-width: 1365px) 100vw, 1365px" /></a></p>
<p>Если Вы все правильно сделали, то файл разместится рядом с вашим проектом:</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_zagruzenniy_dataset_v_directoriu.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_zagruzenniy_dataset_v_directoriu.png" alt="" width="1168" height="303" class="aligncenter size-full wp-image-397" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_zagruzenniy_dataset_v_directoriu.png 1168w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_zagruzenniy_dataset_v_directoriu-300x78.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_zagruzenniy_dataset_v_directoriu-1024x266.png 1024w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_python_zagruzenniy_dataset_v_directoriu-768x199.png 768w" sizes="(max-width: 1168px) 100vw, 1168px" /></a></p>
<p>Далее запускаем следующий код, чтобы прочитать набор данных из csv файла и создать DataFrame (набор данных библиотеки Pandas). Далее выводим примеры записей.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Read BNC2 sample dataset
df = pd.read_csv('BNC2_sample.csv',
                 names=['Code', 'Date', 'Open', 'High', 'Low', 
                        'Close', 'Volume', 'VWAP', 'TWAP'])
 
# Display first 5 observations
df.head()</pre>
<p><strong>Запускаем наш скрипт и получим следующий результат:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_run_script_python_pandas.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_run_script_python_pandas.png" alt="" width="739" height="438" class="aligncenter size-full wp-image-402" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_run_script_python_pandas.png 739w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step2_run_script_python_pandas-300x178.png 300w" sizes="(max-width: 739px) 100vw, 739px" /></a></p>
<p>Обратите внимание, что мы используем аргумент <code class="EnlighterJSRAW" data-enlighter-language="python">names =</code> для <code class="EnlighterJSRAW" data-enlighter-language="python">pd.read_csv()</code>, чтобы установить наши собственные имена столбцов, потому что исходный набор данных не содержит заголовка таблицы (наименования столбцов).</p>
<p><strong>Словарь данных (для кода GWA_BTC):</strong></p>
<ul>
<li><strong>Date:</strong> день, в который были рассчитаны значения индекса.</li>
<li><strong>Open:</strong> дневной индекс цен на биткойны в долларах США.</li>
<li><strong>High:</strong> максимальное значение индекса цен на биткойны в долларах США за день на дату.</li>
<li><strong>Low:</strong> самое низкое значение индекса цен на биткойны в долларах США за день на дату.</li>
<li><strong>Close:</strong> дневной индекс цен на биткойны в долларах США.</li>
<li><strong>Volume:</strong> объем торговли биткойнами в этот день.</li>
<li><strong>VWAP:</strong> средневзвешенная цена за биткойн, торгуемая в этот день.</li>
<li><strong>TWAP:</strong> средневзвешенная по времени цена Биткойна, торгуемая в этот день.</li>
</ul>
<h3 id="step-3"><strong>Шаг 3: Понимание данных. Изучение данных</strong></h3>
<p><span>Одна из наиболее распространенных причин для обработки данных &#8212; это когда «слишком много» информации упаковано в одну таблицу, особенно при работе с данными временных рядов.</span></p>
<p><strong><span>Как правило, все наблюдения (записи/транзакции) должны быть эквивалентны по степени&nbsp;</span><span>детализации</span><span>&nbsp;и в </span><span>единицах</span><span> измерения.</span></strong></p>
<p><span>Существуют исключения, но по большей части это правило поможет вам избежать многих головных болей.</span></p>
<ul>
<li><strong><span>Эквивалентность в гранулярности &#8212;&nbsp;</span></strong><span>&nbsp;например, вы можете иметь 10 строк данных по 10 разным криптовалютам.&nbsp;Однако у вас&nbsp;</span><strong><span>не</span></strong><span>&nbsp;должно быть 11-й строки со средними или суммарными значениями из других 10 строк.&nbsp;Эта 11-я строка будет&nbsp;</span><em><span>агрегацией </span></em><span>и, следовательно, не эквивалентна по гранулярности с другими 10.</span></li>
<li><strong><span>Эквивалентность в единицах &#8212; у</span></strong><span>&nbsp;вас может быть 10 строк с ценами в долларах США, собранных на разные даты.&nbsp;Однако у вас&nbsp;</span><strong><span>не</span></strong><span>&nbsp;должно быть еще 10 строк с ценами, указанными в евро.&nbsp;Любые агрегаты, распределения, визуализации или статистика станут бессмысленными.</span></li>
</ul>
<p><strong><span>Наш текущий набор необработанных данных нарушает оба эти правила!</span></strong></p>
<p><span>Данные, хранящиеся в CSV-файлах или базах данных, часто имеют формат «стопки» или «запись».&nbsp;Они используют один столбец&nbsp;</span><span id="crayon-5de292fa5d0bd739628329" class="crayon-syntax crayon-syntax-inline  crayon-theme-classic crayon-theme-classic-inline crayon-font-monaco"><span class="crayon-pre crayon-code"><span class="crayon-s"><span>«Код»</span></span></span></span><span>&nbsp;в качестве универсального для метаданных.&nbsp;Например, в примере набора данных у нас есть следующие коды:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Unique codes in the dataset
print( df.Code.unique() )</pre>
<p><strong>Результат выполнения:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_code_unique_in_dataset.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_code_unique_in_dataset.png" alt="" width="617" height="176" class="aligncenter size-full wp-image-407" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_code_unique_in_dataset.png 617w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_code_unique_in_dataset-300x86.png 300w" sizes="(max-width: 617px) 100vw, 617px" /></a></p>
<p><span>Во-первых, посмотрите, что некоторые коды начинаются с&nbsp;</span><strong><span>GWA,</span></strong><span>&nbsp;а другие &#8212; с&nbsp;</span><strong><span>MWA</span></strong><span>?&nbsp;На самом деле это абсолютно разные типы индикаторов согласно&nbsp;</span><strong><a href="https://www.quandl.com/data/BNC2-BNC-Digital-Currency-Indexed-EOD/documentation/introduction" target="_blank" rel="noopener noreferrer">странице документации</a></strong><span>.</span></p>
<ul>
<li><span>MWA означает <strong>«</strong></span><strong>средневзвешенное значение</strong><span><strong>&nbsp;по&nbsp;рынку»</strong>, и они показывают региональные цены.&nbsp;Существует несколько кодов MWA для каждой криптовалюты, по одному на каждую местную фиатную валюту.</span></li>
<li><span>С другой стороны, GWA означает <strong>«</strong></span><strong>средневзвешенное значение по</strong><span><strong>&nbsp;всему миру»</strong>, которое показывает глобально проиндексированные цены. Таким образом, GWA &#8212; это совокупность MWA, а не эквивалентность по гранулярности. (Примечание: в образец набора данных включен только поднабор региональных кодов MWA)</span></li>
</ul>
<p><strong>Например, давайте посмотрим на коды Биткойн в ту же дату:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Example of GWA and MWA relationship
df[df.Code.isin(['GWA_BTC', 'MWA_BTC_JPY', 'MWA_BTC_EUR']) &amp; (df.Date == '2018-01-01')]</pre>
<p>&nbsp;Результат выполнения команды:</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_example_GWA_MWA_relationship.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_example_GWA_MWA_relationship.png" alt="" width="889" height="187" class="aligncenter size-full wp-image-411" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_example_GWA_MWA_relationship.png 889w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_example_GWA_MWA_relationship-300x63.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step3_example_GWA_MWA_relationship-768x162.png 768w" sizes="(max-width: 889px) 100vw, 889px" /></a><span>Как видите, у нас есть несколько записей для криптовалюты на данную дату.&nbsp;Чтобы еще больше усложнить ситуацию, региональные данные MWA выражены в местной валюте (то есть в неэквивалентных единицах), поэтому вам также понадобятся исторические обменные курсы.</span></p>
<p><span style="color: #000000;"><strong>Наличие разных уровней детализации и/или разных единиц делает анализ в лучшем случае громоздким, а в худшем &#8212; невозможным.</strong></span></p>
<p><span>К счастью, как только мы обнаружили эту проблему, исправить ее на самом деле тривиально!</span></p>
<h3 id="step-4"><strong>Шаг 4: Отфильтруем нежелательные наблюдения (записи/строки)</strong></h3>
<p><span>Одним из самых простых, но наиболее полезных методов обработки данных является удаление нежелательных наблюдений.</span></p>
<p><span>На предыдущем этапе мы узнали, что коды <strong>GWA</strong> являются агрегированием региональных кодов <strong>MWA</strong>.&nbsp;Поэтому для проведения нашего анализа нам нужно только сохранить глобальные коды GWA:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Number of observations in dataset
print( 'Before:', len(df) )
 
# Get all the GWA codes
gwa_codes = [code for code in df.Code.unique() if 'GWA_' in code]
 
# Only keep GWA observations
df = df[df.Code.isin(gwa_codes)]
 
# Number of observations left
print( 'After:', len(df) )</pre>
<p><strong>Результат работы скрипта Python 3</strong> в Jupyter Notebook:</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step4_keep_only_GWA_observations_check_number_of_observations.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step4_keep_only_GWA_observations_check_number_of_observations.png" alt="" width="590" height="256" class="aligncenter size-full wp-image-414" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step4_keep_only_GWA_observations_check_number_of_observations.png 590w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step4_keep_only_GWA_observations_check_number_of_observations-300x130.png 300w" sizes="(max-width: 590px) 100vw, 590px" /></a></p>
<p><span>Теперь, когда у нас остались только коды GWA, все наши наблюдения эквивалентны по степени детализации и единицах измерения.&nbsp;</span><span>Мы можем продолжать обработку данных.</span></p>
<h3><strong>Шаг 5: Pivot the dataset &#8212; Развернем набор данных</strong></h3>
<p>Далее, чтобы проанализировать нашу стратегию торговли по импульсам, описанную выше, для каждой криптовалюты нам потребуется рассчитать <strong>доходность за предыдущие 7, 14, 21 и 28 дней</strong> для первого дня каждого месяца.</p>
<p>Тем не менее, было бы очень сложно производить этот расчет с текущим <strong>«сложенным» набором данных (&#171;stacked&#187; dataset)</strong>. Это потребует написания вспомогательных функций, циклов и множества условной логики. Вместо этого мы будем использовать более элегантный подход.</p>
<p>Во-первых, мы повернем набор данных, оставив только один ценовой столбец. В этом уроке мы сохраним столбец VWAP (средневзвешенная цена).</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Pivot dataset
pivoted_df = df.pivot(index='Date', columns='Code', values='VWAP')
 
# Display examples from pivoted dataset
pivoted_df.tail()</pre>
<p><strong>Результат:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step5_pivot_dataset_display_example_from_pivoted_dataset.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step5_pivot_dataset_display_example_from_pivoted_dataset.png" alt="" width="597" height="316" class="aligncenter size-full wp-image-419" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step5_pivot_dataset_display_example_from_pivoted_dataset.png 597w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step5_pivot_dataset_display_example_from_pivoted_dataset-300x159.png 300w" sizes="(max-width: 597px) 100vw, 597px" /></a></p>
<p>Как видите, каждый столбец в нашем сводном наборе данных (pivoted dataset) теперь представляет цену за одну криптовалюту, а каждая строка содержит цены за одну дату. Все объекты теперь выровнены по дате.</p>
<h3><strong>Шаг 6: Сдвиг развернутого набора данных &#8212; Shift the pivoted dataset</strong></h3>
<p>Чтобы легко рассчитать <strong>returns</strong> за предыдущие <strong>7, 14, 21 и 28 дней</strong>, мы можем использовать <strong>метод shift из библиотеки Pandas</strong>.</p>
<p>Эта функция сдвигает индекс dataframe на указанное количество периодов. Например, вот что происходит, когда мы сдвигаем наш pivoted dataset на 1:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print( pivoted_df.tail(3) )</pre>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_1.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_1.png" alt="" width="585" height="151" class="aligncenter size-full wp-image-429" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_1.png 585w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_1-300x77.png 300w" sizes="(max-width: 585px) 100vw, 585px" /></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print( pivoted_df.tail(3).shift(1) )</pre>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_2.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_2.png" alt="" width="530" height="136" class="aligncenter size-full wp-image-431" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_2.png 530w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_2-300x77.png 300w" sizes="(max-width: 530px) 100vw, 530px" /></a></p>
<p>Обратите внимание, как смещенный набор данных теперь имеет значения за 1 день до этого? Мы можем воспользоваться этим, чтобы рассчитать prior returns для 7, 14, 21, 28 дней.</p>
<p>Например, для расчета доходности за 7 дней этого нам понадобится <code class="EnlighterJSRAW" data-enlighter-language="python">prices_today / prices_7_days_ago - 1.0</code>, что означает:</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_3_calc_return_over_7_days_prior.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_3_calc_return_over_7_days_prior.png" alt="" width="532" height="308" class="aligncenter size-full wp-image-432" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_3_calc_return_over_7_days_prior.png 532w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_3_calc_return_over_7_days_prior-300x174.png 300w" sizes="(max-width: 532px) 100vw, 532px" /></a></p>
<p>Рассчитать <strong>returns</strong> для всех наших периодов так же просто, как написать цикл и сохранить его в словаре:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Calculate returns over each window and store them in dictionary
delta_dict = {}
for offset in [7, 14, 21, 28]:
    delta_dict['delta_{}'.format(offset)] = pivoted_df / pivoted_df.shift(offset) - 1.0

# Display result "delta_dict"
delta_dict</pre>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_4_calc_return_over_each_period.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_4_calc_return_over_each_period.png" alt="" width="806" height="527" class="aligncenter size-full wp-image-433" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_4_calc_return_over_each_period.png 806w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_4_calc_return_over_each_period-300x196.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/Step6_Shift_pivoted_dataset_example_4_calc_return_over_each_period-768x502.png 768w" sizes="(max-width: 806px) 100vw, 806px" /></a></p>
<p>Полный список результата (out):</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">{'delta_7': Code        GWA_BTC  GWA_ETH  GWA_LTC  GWA_XLM  GWA_XRP
 Date                                                   
 2014-04-01      nan      nan      nan      nan      nan
 2014-04-02      nan      nan      nan      nan      nan
 2014-04-03      nan      nan      nan      nan      nan
 2014-04-04      nan      nan      nan      nan      nan
 2014-04-05      nan      nan      nan      nan      nan
 ...             ...      ...      ...      ...      ...
 2018-01-19    -0.18    -0.17    -0.18    -0.21    -0.22
 2018-01-20    -0.13    -0.19    -0.18    -0.23    -0.29
 2018-01-21    -0.15    -0.20    -0.22    -0.22    -0.30
 2018-01-22    -0.21    -0.24    -0.24    -0.25    -0.32
 2018-01-23    -0.11    -0.12    -0.13    -0.02    -0.04
 
 [1394 rows x 5 columns],
 'delta_14': Code        GWA_BTC  GWA_ETH  GWA_LTC  GWA_XLM  GWA_XRP
 Date                                                   
 2014-04-01      nan      nan      nan      nan      nan
 2014-04-02      nan      nan      nan      nan      nan
 2014-04-03      nan      nan      nan      nan      nan
 2014-04-04      nan      nan      nan      nan      nan
 2014-04-05      nan      nan      nan      nan      nan
 ...             ...      ...      ...      ...      ...
 2018-01-19    -0.29     0.05    -0.23    -0.27    -0.41
 2018-01-20    -0.26     0.13    -0.29    -0.26    -0.42
 2018-01-21    -0.29    -0.01    -0.32    -0.31    -0.51
 2018-01-22    -0.29    -0.13    -0.30    -0.28    -0.52
 2018-01-23    -0.31    -0.22    -0.32    -0.24    -0.48
 
 [1394 rows x 5 columns],
 'delta_21': Code        GWA_BTC  GWA_ETH  GWA_LTC  GWA_XLM  GWA_XRP
 Date                                                   
 2014-04-01      nan      nan      nan      nan      nan
 2014-04-02      nan      nan      nan      nan      nan
 2014-04-03      nan      nan      nan      nan      nan
 2014-04-04      nan      nan      nan      nan      nan
 2014-04-05      nan      nan      nan      nan      nan
 ...             ...      ...      ...      ...      ...
 2018-01-19    -0.22     0.42    -0.24     0.88     0.02
 2018-01-20    -0.05     0.60    -0.09     0.57    -0.26
 2018-01-21    -0.11     0.51    -0.12     0.47    -0.28
 2018-01-22    -0.19     0.36    -0.19     0.05    -0.35
 2018-01-23    -0.25     0.13    -0.29    -0.10    -0.39
 
 [1394 rows x 5 columns],
 'delta_28': Code        GWA_BTC  GWA_ETH  GWA_LTC  GWA_XLM  GWA_XRP
 Date                                                   
 2014-04-01      nan      nan      nan      nan      nan
 2014-04-02      nan      nan      nan      nan      nan
 2014-04-03      nan      nan      nan      nan      nan
 2014-04-04      nan      nan      nan      nan      nan
 2014-04-05      nan      nan      nan      nan      nan
 ...             ...      ...      ...      ...      ...
 2018-01-19    -0.17     0.57    -0.24     1.30     0.65
 2018-01-20    -0.13     0.60    -0.27     1.23     0.53
 2018-01-21    -0.12     0.65    -0.27     1.22     0.45
 2018-01-22    -0.20     0.38    -0.33     1.09     0.30
 2018-01-23    -0.31     0.29    -0.37     1.16     0.29
 
 [1394 rows x 5 columns]}</pre>
<p><strong>Примечание.</strong> Для расчета returns путем смещения набора данных необходимо выполнить 2 допущения:</p>
<ol>
<li>наблюдения отсортированы ascending by date и</li>
<li>отсутствуют пропущенные даты. Этого шага нет в статье, чтобы сделать этот урок лаконичным, рекомендуется проверить это самостоятельно.</li>
</ol>
<h3><strong>Шаг 7: Сплавка смещенного набора данных &#8212; Melt the shifted dataset</strong></h3>
<p>Теперь, когда мы вычислили возвраты с использованием развернутого набора данных (Pivot dataset), мы собираемся «разворачивать (unpivot)» возвраты. Развернув (Unpivot) или расплавив данные, мы можем позже создать аналитическую базовую таблицу (АБТ &#8212; analytical base table, ABT), где каждая строка содержит всю необходимую информацию для конкретной монеты на определенную дату.</p>
<p>Мы не могли напрямую сместить исходный набор данных, потому что данные для разных монет были сложены друг на друга, поэтому границы могли бы перекрываться. Другими словами, данные BTC попадут в расчеты ETH, данные ETH попадут в расчеты LTC и так далее.</p>
<p><strong>Чтобы расплавить данные, нам требуется:</strong></p>
<ul>
<li><strong>reset_index()</strong>, чтобы мы могли вызывать столбцы по имени;</li>
<li>Вызовите метод <strong>melt()</strong>;</li>
<li>Передайте столбец (столбцы), чтобы сохранить в аргумент <strong>id_vars=</strong>;</li>
<li>Назовите растопленный столбец (melted column), используя аргумент <strong>value_name=</strong>.</li>
</ul>
<p><strong>Вот как это выглядит для одного dataframe:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Melt delta_7 returns
melted_7 = delta_7.reset_index().melt(id_vars=['Date'], value_name='delta_7')
 
# Melted dataframe examples
melted_7.tail()</pre>
<p>Результат:</p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step7_melted_dataframe_examples_delta_7_returns.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step7_melted_dataframe_examples_delta_7_returns.png" alt="" width="735" height="300" class="aligncenter size-full wp-image-443" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step7_melted_dataframe_examples_delta_7_returns.png 735w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step7_melted_dataframe_examples_delta_7_returns-300x122.png 300w" sizes="(max-width: 735px) 100vw, 735px" /></a></p>
<p>Чтобы сделать это для всех возвращаемых <strong>DataFrame</strong>, мы можем просто перебрать <strong>delta_dict</strong>, вот так:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Melt all the delta dataframes and store in list
melted_dfs = []
for key, delta_df in delta_dict.items():
    melted_dfs.append( delta_df.reset_index().melt(id_vars=['Date'], value_name=key) )

melted_dfs</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">[            Date     Code  delta_7
 0     2014-04-01  GWA_BTC      nan
 1     2014-04-02  GWA_BTC      nan
 2     2014-04-03  GWA_BTC      nan
 3     2014-04-04  GWA_BTC      nan
 4     2014-04-05  GWA_BTC      nan
 ...          ...      ...      ...
 6965  2018-01-19  GWA_XRP    -0.22
 6966  2018-01-20  GWA_XRP    -0.29
 6967  2018-01-21  GWA_XRP    -0.30
 6968  2018-01-22  GWA_XRP    -0.32
 6969  2018-01-23  GWA_XRP    -0.04
 
 [6970 rows x 3 columns],             Date     Code  delta_14
 0     2014-04-01  GWA_BTC       nan
 1     2014-04-02  GWA_BTC       nan
 2     2014-04-03  GWA_BTC       nan
 3     2014-04-04  GWA_BTC       nan
 4     2014-04-05  GWA_BTC       nan
 ...          ...      ...       ...
 6965  2018-01-19  GWA_XRP     -0.41
 6966  2018-01-20  GWA_XRP     -0.42
 6967  2018-01-21  GWA_XRP     -0.51
 6968  2018-01-22  GWA_XRP     -0.52
 6969  2018-01-23  GWA_XRP     -0.48
 
 [6970 rows x 3 columns],             Date     Code  delta_21
 0     2014-04-01  GWA_BTC       nan
 1     2014-04-02  GWA_BTC       nan
 2     2014-04-03  GWA_BTC       nan
 3     2014-04-04  GWA_BTC       nan
 4     2014-04-05  GWA_BTC       nan
 ...          ...      ...       ...
 6965  2018-01-19  GWA_XRP      0.02
 6966  2018-01-20  GWA_XRP     -0.26
 6967  2018-01-21  GWA_XRP     -0.28
 6968  2018-01-22  GWA_XRP     -0.35
 6969  2018-01-23  GWA_XRP     -0.39
 
 [6970 rows x 3 columns],             Date     Code  delta_28
 0     2014-04-01  GWA_BTC       nan
 1     2014-04-02  GWA_BTC       nan
 2     2014-04-03  GWA_BTC       nan
 3     2014-04-04  GWA_BTC       nan
 4     2014-04-05  GWA_BTC       nan
 ...          ...      ...       ...
 6965  2018-01-19  GWA_XRP      0.65
 6966  2018-01-20  GWA_XRP      0.53
 6967  2018-01-21  GWA_XRP      0.45
 6968  2018-01-22  GWA_XRP      0.30
 6969  2018-01-23  GWA_XRP      0.29
 
 [6970 rows x 3 columns]]</pre>
<p>Наконец, мы можем создать другой расплавленный фрейм данных, который содержит прогнозные 7-дневные возвраты. Это будет нашей <strong>«целевой переменной» для оценки нашей торговой стратегии</strong>.</p>
<p>Просто сдвиньте сводный набор данных на &#8212; 7, чтобы получить «будущие» цены, например:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Calculate 7-day returns after the date
return_df = pivoted_df.shift(-7) / pivoted_df - 1.0
 
# Melt the return dataset and append to list
melted_dfs.append( return_df.reset_index().melt(id_vars=['Date'], value_name='return_7') )</pre>
<p>Теперь у нас есть 5 расплавленных фреймов данных, сохраненных в списке <strong>melted_dfs</strong>, по одному для каждого из ретроспективных <strong>7, 14, 21 и 28-дневных возвратов</strong> и один для <strong>прогнозных 7-дневных возвратов</strong>.</p>
<h3><strong>Шаг 8: Уменьшить-объединить расплавленные данные &#8212; Reduce-merge the melted data</strong></h3>
<p>Все, что осталось сделать &#8212; это объединить наши расплавленные DataFrames в единую аналитическую базовую таблицу. Нам понадобятся два инструмента.</p>
<p>Первый инструмент &#8212; это функция слияния Pandas, которая работает как JOIN в SQL. Например, для того, чтобы объединить первые два расплавленных DataFrames:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null"># Merge two dataframes
pd.merge(melted_dfs[0], melted_dfs[1], on=['Date', 'Code']).tail()</pre>
<p><strong>Результат:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_merge_two_dataframes_delta7_delta14.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_merge_two_dataframes_delta7_delta14.png" alt="" width="640" height="249" class="aligncenter size-full wp-image-444" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_merge_two_dataframes_delta7_delta14.png 640w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_merge_two_dataframes_delta7_delta14-300x117.png 300w" sizes="(max-width: 640px) 100vw, 640px" /></a></p>
<p>Посмотрите, теперь у нас delta_7 и delta_14 в одной строке! Это начало нашей аналитической базовой таблицы. Все, что нам нужно сделать сейчас &#8212; это объединить все наши расплавленные DataFrames с базовым DataFrame других функций, которые нам могут понадобиться.</p>
<p>Самый элегантный способ сделать это &#8212; использовать встроенную функцию уменьшения Python. Сначала нам нужно её импортировать:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">from functools import reduce</pre>
<p>Далее, прежде чем использовать эту функцию, давайте создадим список <strong>feature_dfs</strong>, который содержит базовые элементы из исходного набора данных плюс расплавленные наборы данных.</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Grab features from original dataset
base_df = df[['Date', 'Code', 'Volume', 'VWAP']]
 
# Create a list with all the feature dataframes
feature_dfs = [base_df] + melted_dfs</pre>
<p>Теперь мы готовы использовать функцию <strong>Reduce</strong>.</p>
<p><strong>Reduce</strong> применяет функцию двух аргументов кумулятивно к объектам в последовательности (например, список). <br>Например,</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">reduce(lambda x,y: x+y, [1,2,3,4,5])</pre>
<p>вычисляет</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">((((1+2)+3)+4)+5)</pre>
<p>Таким образом, мы можем уменьшить-объединить все функции следующим образом:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Reduce-merge features into analytical base table
abt = reduce(lambda left,right: pd.merge(left,right,on=['Date', 'Code']), feature_dfs)
 
# Display examples from the ABT
abt.tail(10)</pre>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_reduce_merge_features_into_analytical_base_table.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_reduce_merge_features_into_analytical_base_table.png" alt="" width="862" height="428" class="aligncenter size-full wp-image-448" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_reduce_merge_features_into_analytical_base_table.png 862w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_reduce_merge_features_into_analytical_base_table-300x149.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_reduce_merge_features_into_analytical_base_table-768x381.png 768w" sizes="(max-width: 862px) 100vw, 862px" /></a></p>
<p>Словарь данных для нашей&nbsp;<em><strong><span>аналитической базовой таблицы (ABT):</span></strong></em></p>
<ul>
<li><strong><span>Date (Дата):</span></strong><span>&nbsp;&nbsp;день, в который были рассчитаны значения индекса.</span></li>
<li><strong><span>Code (Код):</span></strong><span>&nbsp; пара, какая криптовалюта.</span></li>
<li><strong><span>VWAP:</span></strong><span>&nbsp; средневзвешенная цена за день торгов на дату .</span></li>
<li><strong><span>delta_7:</span></strong><span>&nbsp;&nbsp;возврат за предыдущие 7 дней (1.0 = 100% возврат).</span></li>
<li><strong><span>delta_14:</span></strong><span>&nbsp;&nbsp;возврат за предыдущие 14 дней (1.0 = 100% возврат).</span></li>
<li><strong><span>delta_21:</span></strong><span>&nbsp;&nbsp;возврат за предыдущие 21 день (1.0 = 100% возврат).</span></li>
<li><strong><span>delta_28:</span></strong><span>&nbsp;&nbsp;возврат за предыдущие 28 дней (1.0 = 100% возврат).</span></li>
<li><strong><span>return_7:</span></strong><span>&nbsp; будущий возврат в течение следующих 7 дней (1.0 = 100% возврат).</span></li>
</ul>
<p>Кстати, обратите внимание, что последние 7 наблюдений не имеют значений для функции return_7? Это ожидаемо, так как мы не можем рассчитать «будущие 7-дневные доходы» за последние 7 дней набора данных.</p>
<p>Технически, с этой ABT, мы уже можем ответить на нашу первоначальную цель. Например, если мы хотим выбрать монету, которая имела наибольший импульс 1 сентября 2017 года, мы могли бы просто отобразить строки для этой даты и посмотреть на 7, 14, 21 и 28-дневный возврат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Data from Sept 1st, 2017
abt[abt.Date == '2017-09-01']</pre>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_print_returns_ABT.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_print_returns_ABT.png" alt="" width="863" height="249" class="aligncenter size-full wp-image-450" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_print_returns_ABT.png 863w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_print_returns_ABT-300x87.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_print_returns_ABT-768x222.png 768w" sizes="(max-width: 863px) 100vw, 863px" /></a></p>
<p><span>И если вы хотите программно выбрать криптовалюту (пару для торгов) с наибольшим импульсом (например, за предыдущие 28 дней), вы должны написать:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">max_momentum_id = abt[abt.Date == '2017-09-01'].delta_28.idxmax()
abt.loc[max_momentum_id, ['Code','return_7']]</pre>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_max_momentum_dataframe_loc.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_max_momentum_dataframe_loc.png" alt="" width="598" height="116" class="aligncenter size-full wp-image-452" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_max_momentum_dataframe_loc.png 598w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step8_max_momentum_dataframe_loc-300x58.png 300w" sizes="(max-width: 598px) 100vw, 598px" /></a></p>
<p><span>Тем не менее, поскольку мы заинтересованы в торговле только в первый день каждого месяца, мы можем упростить ситуацию для себя&#8230;</span></p>
<h3><strong>Шаг 9: (Необязательно) Агрегация через Group By &#8212; Aggregate with group-by</strong></h3>
<p>В качестве последнего шага, если мы хотим сохранить только первые дни каждого месяца. Для этого мы можем использовать группирование с последующей агрегацией.</p>
<p>Сначала создайте новую функцию &#8216;month&#8217; из первых 7 символов строк Date.<br>Затем сгруппируйте наблюдения по «Коду» и «месяцу». Pandas создадут «ячейки» данных, которые разделяют наблюдения по коду и месяцу.<br>Наконец, в каждой группе просто возьмите .first() и сбросьте индекс.<br>Примечание. Мы предполагаем, что ваш фрейм данных по-прежнему правильно отсортирован по дате.</p>
<p>Вот как все это выглядит вместе:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python"># Create 'month' feature
abt['month'] = abt.Date.apply(lambda x: x[:7])
 
# Group by 'Code' and 'month' and keep first date
gb_df = abt.groupby(['Code', 'month']).first().reset_index()
 
# Display examples
gb_df.tail()</pre>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step9_display_example_group_by_keep_first_date.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step9_display_example_group_by_keep_first_date.png" alt="" width="906" height="351" class="aligncenter size-full wp-image-455" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step9_display_example_group_by_keep_first_date.png 906w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step9_display_example_group_by_keep_first_date-300x116.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/11/step9_display_example_group_by_keep_first_date-768x298.png 768w" sizes="(max-width: 906px) 100vw, 906px" /></a></p>
<p><strong>Как видите, теперь у нас есть правильная Аналитическая базовая таблица АБТ с:</strong></p>
<ul>
<li>Только соответствующие данные с 1-го числа каждого месяца.</li>
<li>Импульсные характеристики рассчитаны за предыдущие 7, 14, 21 и 28 дней.</li>
<li>Прогноз будущих возвратов (future returns) через 7 дней.</li>
</ul>
<p>Другими словами, у нас есть именно то, что нам нужно, чтобы оценить простую торговую стратегию, которую мы предложили в начале статьи!</p>


<h2 class="wp-block-heading" id="complete"><strong>Полный код от начала до конца</strong></h2>



<p>Вот весь основной код в одном месте, в одном скрипте.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group=""># 2. Import libraries and dataset
import pandas as pd
pd.options.display.float_format = '{:,.2f}'.format
pd.options.display.max_rows = 200
pd.options.display.max_columns = 100
 
df = pd.read_csv('BNC2_sample.csv',
                 names=['Code', 'Date', 'Open', 'High', 'Low', 
                        'Close', 'Volume', 'VWAP', 'TWAP'])
 
# 4. Filter unwanted observations
gwa_codes = [code for code in df.Code.unique() if 'GWA_' in code]
df = df[df.Code.isin(gwa_codes)]
 
# 5. Pivot the dataset
pivoted_df = df.pivot(index='Date', columns='Code', values='VWAP')
 
# 6. Shift the pivoted dataset
delta_dict = {}
for offset in [7, 14, 21, 28]:
    delta_dict['delta_{}'.format(offset)] = pivoted_df / pivoted_df.shift(offset) - 1
    
# 7. Melt the shifted dataset
melted_dfs = []
for key, delta_df in delta_dict.items():
    melted_dfs.append( delta_df.reset_index().melt(id_vars=['Date'], value_name=key) )
 
return_df = pivoted_df.shift(-7) / pivoted_df - 1.0
melted_dfs.append( return_df.reset_index().melt(id_vars=['Date'], value_name='return_7') )
 
# 8. Reduce-merge the melted data
from functools import reduce
 
base_df = df[['Date', 'Code', 'Volume', 'VWAP']]
feature_dfs = [base_df] + melted_dfs
 
abt = reduce(lambda left,right: pd.merge(left,right,on=['Date', 'Code']), feature_dfs)
 
# 9. Aggregate with group-by.
abt['month'] = abt.Date.apply(lambda x: x[:7])
gb_df = abt.groupby(['Code', 'month']).first().reset_index()</pre>



<figure class="wp-block-image size-large"><img decoding="async" width="788" height="367" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/step_final_return.png" alt="" class="wp-image-459" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/step_final_return.png 788w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/step_final_return-300x140.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/step_final_return-768x358.png 768w" sizes="(max-width: 788px) 100vw, 788px" /></figure>



<div class="wp-block-file"><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/Notebook.html"><strong>Пример Jupyter Notebook Python 3</strong></a><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/12/Notebook.html" class="wp-block-file__button" download><strong>Скачать</strong></a></div>
<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&amp;linkname=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython-data-wrangling-tutorial-for-cryptocurrency%2F&#038;title=Python%203%20Tutorial%20%E2%80%94%20Data%20Wrangling%20%E2%80%94%20%D0%9E%D0%B1%D1%80%D0%B0%D0%B1%D0%BE%D1%82%D0%BA%D0%B0%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%BF%D0%BE%20%D0%BA%D1%80%D0%B8%D0%BF%D1%82%D0%BE%D0%B2%D0%B0%D0%BB%D1%8E%D1%82%D0%B0%D0%BC" data-a2a-url="https://python.ivan-shamaev.ru/python-data-wrangling-tutorial-for-cryptocurrency/" data-a2a-title="Python 3 Tutorial — Data Wrangling — Обработка данных по криптовалютам"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/python-data-wrangling-tutorial-for-cryptocurrency/">Python 3 Tutorial &#8212; Data Wrangling &#8212; Обработка данных по криптовалютам</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/python-data-wrangling-tutorial-for-cryptocurrency/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Предыдущий и следующий элемент в dataframe pandas. Shift Python</title>
		<link>https://python.ivan-shamaev.ru/pandas-get-previous-dataframe-shift-example/</link>
					<comments>https://python.ivan-shamaev.ru/pandas-get-previous-dataframe-shift-example/#respond</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Sat, 17 Aug 2019 11:16:47 +0000</pubDate>
				<category><![CDATA[Pandas. Обработка данных]]></category>
		<category><![CDATA[Примеры скриптов (кода) Python 3]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=169</guid>

					<description><![CDATA[<p>Результат выполнения скрипта</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/pandas-get-previous-dataframe-shift-example/">Предыдущий и следующий элемент в dataframe pandas. Shift Python</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&#038;title=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" data-a2a-url="https://python.ivan-shamaev.ru/pandas-get-previous-dataframe-shift-example/" data-a2a-title="Предыдущий и следующий элемент в dataframe pandas. Shift Python"></a></p>
<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd
data = pd.DataFrame(np.random.rand(6, 1),
                  columns=['close'],
                 index=['a', 'b', 'c', 'd', 'e', 'f'])

data['shift_plus_1'] = data.close.shift(1)

data.loc[data.close.shift(+1) &lt; data.close, 'TrendUp'] = 1

print(data)</pre>



<p><strong>Результат выполнения скрипта</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">      close  shift_plus_1  TrendUp
a  0.743436           NaN      NaN
b  0.254870      0.743436      NaN
c  0.689602      0.254870      1.0
d  0.233681      0.689602      NaN
e  0.100933      0.233681      NaN
f  0.391622      0.100933      1.0</pre>
<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&amp;linkname=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-get-previous-dataframe-shift-example%2F&#038;title=%D0%9F%D1%80%D0%B5%D0%B4%D1%8B%D0%B4%D1%83%D1%89%D0%B8%D0%B9%20%D0%B8%20%D1%81%D0%BB%D0%B5%D0%B4%D1%83%D1%8E%D1%89%D0%B8%D0%B9%20%D1%8D%D0%BB%D0%B5%D0%BC%D0%B5%D0%BD%D1%82%20%D0%B2%20dataframe%20pandas.%20Shift%20Python" data-a2a-url="https://python.ivan-shamaev.ru/pandas-get-previous-dataframe-shift-example/" data-a2a-title="Предыдущий и следующий элемент в dataframe pandas. Shift Python"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/pandas-get-previous-dataframe-shift-example/">Предыдущий и следующий элемент в dataframe pandas. Shift Python</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/pandas-get-previous-dataframe-shift-example/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python3 Pandas DataFrame To_Sql &#8212; запись данных в таблицу</title>
		<link>https://python.ivan-shamaev.ru/python3-pandas-dataframe-to-sql-write-data-in-table/</link>
					<comments>https://python.ivan-shamaev.ru/python3-pandas-dataframe-to-sql-write-data-in-table/#respond</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Mon, 13 May 2019 19:52:18 +0000</pubDate>
				<category><![CDATA[Pandas. Обработка данных]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=116</guid>

					<description><![CDATA[<p>Введение &#8212; перевод документации (pandas.pydata.org) Базовый синтаксис: Записывает записи, хранящиеся в DataFrame, в базу данных SQL. Поддерживаются базы данных, поддерживаемые SQLAlchemy. Таблицы могут быть заново созданы, добавлены или перезаписаны. Пояснения для параметров метода to_sql: name : stringИмя таблицы SQL. con : sqlalchemy.engine.Engine или sqlite3.ConnectionИспользование SQLAlchemy позволяет использовать любую БД, поддерживаемую этой библиотекой. schema : string, [&#8230;]</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/python3-pandas-dataframe-to-sql-write-data-in-table/">Python3 Pandas DataFrame To_Sql &#8212; запись данных в таблицу</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&#038;title=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" data-a2a-url="https://python.ivan-shamaev.ru/python3-pandas-dataframe-to-sql-write-data-in-table/" data-a2a-title="Python3 Pandas DataFrame To_Sql — запись данных в таблицу"></a></p>
<h2 class="wp-block-heading">Введение &#8212; перевод документации (pandas.pydata.org)</h2>



<p>Базовый синтаксис:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">DataFrame.to_sql(
	name,
	con,
	schema=None,
	if_exists='fail',
	index=True,
	index_label=None,
	chunksize=None,
	dtype=None,
	method=None
)</pre>



<p>Записывает записи, хранящиеся в DataFrame, в базу данных SQL. Поддерживаются базы данных, поддерживаемые SQLAlchemy. Таблицы могут быть заново созданы, добавлены или перезаписаны. Пояснения для параметров метода to_sql:</p>



<blockquote class="wp-block-quote is-layout-flow wp-block-quote-is-layout-flow"><p><strong>name : string</strong><br>Имя таблицы SQL.<br></p><p><strong>con : sqlalchemy.engine.Engine или sqlite3.Connection</strong><br>Использование SQLAlchemy позволяет использовать любую БД, поддерживаемую этой библиотекой. <br></p><p><strong>schema : string, optional</strong><br>Укажите схему (если это поддерживает база данных). Если схема не указана, то будет использована схема по-умолчанию.<br></p><p><strong>if_exists : {‘fail’, ‘replace’, ‘append’}, default ‘fail’</strong><br>Параметр описывает поведение, если таблица уже существует.<br><strong>fail</strong>: вызвать ошибку ValueError.<br><strong>replace</strong>: Drop table перед вставкой новых значений.<br><strong>append</strong>: вставить новые значения в существующую таблицу.<br></p><p><strong>index : bool, по-умолчанию True</strong><br>Запишет индекс DataFrame в виде столбца. Использует index_label в качестве имени столбца в таблице.<br></p><p><strong>index_label : string или sequence, по-умолчанию отсутствует</strong><br>Метка столбца для индексных столбцов. Если указано None (по-умолчанию), а index &#8212; True, тогда используются имена индексов. Последовательность должна быть задана, если DataFrame использует MultiIndex.<br></p><p><strong>chunksize : int, необязательный параметр</strong><br>Строки будут записаны партиями заданного размера за раз. По-умолчанию строки пишутся одновременно.<br></p><p><strong>dtype : dict, необязательный параметр</strong><br>Указание типа данных для столбцов. Ключи должны быть именами столбцов, а значения &#8212; типами или строками.<br></p><p><strong>method : {None, ‘multi’, callable}, по-умолчанию None</strong><br>Контролирует SQL Insert<br>None : используется стандартный SQL INSERT (по одному на строку).<br> ‘multi’: передать несколько значений в одном INSERT.<br> callable:вызывается с подписью (pd_table, conn, keys, data_iter).</p><cite><a href="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html" target="_blank" rel="noreferrer noopener" aria-label="https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html (откроется в новой вкладке)">https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.to_sql.html</a></cite></blockquote>



<h2 class="wp-block-heading">Пример записи данных из DataFrame &#8216;data&#8217; в таблицу</h2>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import psycopg2
from sqlalchemy import create_engine

# предполагаем, что у нас есть DataFrame с названием 'date'

# Подключаемся к базе данных PGSQL
engine = create_engine('postgresql+psycopg2://user_name:password@host_name_or_ip/database_name')

# Пишем в PGSQL
data.to_sql('table_name', con=engine, schema = 'dbo', if_exists='replace')</pre>
<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&amp;linkname=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpython3-pandas-dataframe-to-sql-write-data-in-table%2F&#038;title=Python3%20Pandas%20DataFrame%20To_Sql%20%E2%80%94%20%D0%B7%D0%B0%D0%BF%D0%B8%D1%81%D1%8C%20%D0%B4%D0%B0%D0%BD%D0%BD%D1%8B%D1%85%20%D0%B2%20%D1%82%D0%B0%D0%B1%D0%BB%D0%B8%D1%86%D1%83" data-a2a-url="https://python.ivan-shamaev.ru/python3-pandas-dataframe-to-sql-write-data-in-table/" data-a2a-title="Python3 Pandas DataFrame To_Sql — запись данных в таблицу"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/python3-pandas-dataframe-to-sql-write-data-in-table/">Python3 Pandas DataFrame To_Sql &#8212; запись данных в таблицу</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/python3-pandas-dataframe-to-sql-write-data-in-table/feed/</wfw:commentRss>
			<slash:comments>0</slash:comments>
		
		
			</item>
		<item>
		<title>Python 3 Pandas: Объекты Series и DataFrame. Построение Index</title>
		<link>https://python.ivan-shamaev.ru/pandas-series-and-dataframe-objects-build-index/</link>
					<comments>https://python.ivan-shamaev.ru/pandas-series-and-dataframe-objects-build-index/#comments</comments>
		
		<dc:creator><![CDATA[Шамаев Иван]]></dc:creator>
		<pubDate>Tue, 23 Apr 2019 02:32:09 +0000</pubDate>
				<category><![CDATA[Pandas. Обработка данных]]></category>
		<category><![CDATA[pandas dataframe]]></category>
		<category><![CDATA[pandas dataframe tutorial]]></category>
		<category><![CDATA[python 3]]></category>
		<category><![CDATA[python 3 pandas]]></category>
		<category><![CDATA[python pandas]]></category>
		<category><![CDATA[обработка dataframe]]></category>
		<category><![CDATA[обучение dataframe]]></category>
		<category><![CDATA[обучение Python pandas]]></category>
		<category><![CDATA[учебник python pandas]]></category>
		<guid isPermaLink="false">https://python.ivan-shamaev.ru/?p=79</guid>

					<description><![CDATA[<p>Что такое Pandas DataFrame? Pandas — более новый пакет, надстройка над библиотекой NumPy, обеспечивающий эффективную реализацию класса DataFrame. Объекты DataFrame — многомерные массивы с метками для строк и столбцов, а также зачастую с неоднородным типом данных и/или пропущенными данными. Помимо удобного интерфейса для хранения маркированных данных, библиотека Pandas реализует множество операций для работы с данными [&#8230;]</p>
<p>Сообщение <a href="https://python.ivan-shamaev.ru/pandas-series-and-dataframe-objects-build-index/">Python 3 Pandas: Объекты Series и DataFrame. Построение Index</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></description>
										<content:encoded><![CDATA[<p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&#038;title=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" data-a2a-url="https://python.ivan-shamaev.ru/pandas-series-and-dataframe-objects-build-index/" data-a2a-title="Python 3 Pandas: Объекты Series и DataFrame. Построение Index"></a></p>
<h2 class="wp-block-heading">Что такое Pandas DataFrame?</h2>


<p><span><strong>Pandas</strong> — более новый пакет, надстройка над библиотекой NumPy, обеспечивающий эффективную реализацию класса DataFrame. </span></p>
<p><span><strong>Объекты DataFrame</strong> — многомерные массивы с метками для строк и столбцов, а также зачастую с неоднородным типом данных и/или пропущенными данными. </span></p>
<p><span>Помимо удобного интерфейса для <strong>хранения маркированных данных</strong>, библиотека <strong>Pandas</strong> реализует <strong>множество операций для работы с данными</strong> хорошо знакомых пользователям фреймворков баз данных и электронных таблиц.</span></p>


<h2 class="wp-block-heading">Импорт библиотек NumPy и Pandas</h2>



<p>На самом примитивном уровне объекты библиотеки Pandas можно считать расширенной версией структурированных массивов библиотеки NumPy, в которых строки и столбцы идентифицируются метками, а не простыми числовыми индексами. Библиотека Pandas предоставляет множество полезных утилит, методов и функциональности в дополнение к базовым структурам данных, но все последующее изложение потребует понимания этих базовых структур. Позвольте познакомить вас с тремя фундаментальными структурами данных библиотеки Pandas: классами Series, DataFrame и Index.</p>



<p>Начнем наш сеанс программирования с обычных импортов библиотек NumPy и Pandas:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd</pre>



<h2 class="wp-block-heading">Объект Series библиотеки Pandas</h2>



<p><strong>Объект Series</strong> библиотеки Pandas — одномерный массив индексированных данных. Его можно создать из списка или массива следующим образом:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

data = pd.Series([0.25, 0.5, 0.75, 1.0])
print(data)</pre>



<p><strong>Результат:</strong></p>



<div class="wp-block-image"><figure class="aligncenter"><img decoding="async" width="130" height="85" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/pandas_series_ex1.jpg" alt="" class="wp-image-82"/></figure></div>



<p>Как мы видели из предыдущего результата, объект Series служит адаптером как для последовательности значений, так и последовательности индексов, к которым можно получить доступ посредством атрибутов values и index. Атрибут values представляет собой массив NumPy:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

data = pd.Series([0.25, 0.5, 0.75, 1.0])
print(data.values)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">[0.25 0.5  0.75 1.  ]</pre>



<p><strong>Index</strong> — массивоподобный объект типа <strong>pd.Index</strong>:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

data = pd.Series([0.25, 0.5, 0.75, 1.0])
print(data.index)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">RangeIndex(start=0, stop=4, step=1)</pre>



<p>Аналогично массивам библиотеки NumPy, к данным можно обращаться по соответствующему им индексу посредством нотации с использованием квадратных скобок языка Python:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

data = pd.Series([0.25, 0.5, 0.75, 1.0])
print('data[1]:')
print(data[1])

print('data[1:3]:')
print(data[1:3])</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data[1]:
0.5
data[1:3]:
1    0.50
2    0.75
dtype: float64</pre>



<p>Однако объект Series библиотеки Pandas намного универсальнее и гибче, чем эмулируемый им одномерный массив библиотеки NumPy.</p>



<h3 class="wp-block-heading">Объект Series как обобщенный массив NumPy</h3>



<p>Может показаться, что объект <strong>Series </strong>и <strong>одномерный массив библиотеки NumPy</strong> взаимозаменяемы. Основное различие между ними — <strong>индекс</strong>. В то время как <strong>индекс массива NumPy</strong>, используемый для доступа к значениям, — целочисленный и описывается неявно, <strong>индекс объекта Series библиотеки Pandas</strong> описывается явно и связывается со значениями.<br></p>



<p><strong>Явное описание индекса</strong> расширяет возможности объекта Series. Такой индекс не должен быть целым числом, а может состоять из значений любого нужного типа. Например, при желании мы можем использовать в качестве индекса строковые значения:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

data = pd.Series([0.25, 0.5, 0.75, 1.0],
                 index=['a', 'b', 'c', 'd'])
print(data)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">a    0.25
b    0.50
c    0.75
d    1.00
dtype: float64</pre>



<p>При этом доступ к элементам работает обычным образом:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

data = pd.Series([0.25, 0.5, 0.75, 1.0],
                 index=['a', 'b', 'c', 'd'])
print(data['b'])</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">0.5</pre>



<h3 class="wp-block-heading">Объект Series как специализированный словарь</h3>



<p><strong>Объект Series</strong> библиотеки Pandas можно рассматривать как специализированную разновидность словаря языка Python. <strong>Словарь </strong>— структура, задающая соответствие произвольных ключей набору произвольных значений, а объект <strong>Series </strong>— структура, задающая соответствие типизированных ключей набору типизированных значений. </p>



<p><strong>Типизация важна:</strong> точно так же, как соответствующий типу специализированный код для массива библиотеки NumPy при выполнении определенных операций делает его эффективнее, чем стандартный список Python, информация о типе в объекте Series библиотеки Pandas делает его намного более эффективным для определенных операций, чем словари Python.<br></p>



<p>Можно сделать аналогию «объект Series — словарь» еще более наглядной, сконструировав объект Series непосредственно из словаря Python.</p>



<p>По умолчанию при этом будет создан объект Series с полученным из отсортированных ключей индексом. Следовательно, для него возможен обычный доступ к элементам, такой же, как для словаря. Объект Series поддерживает операции &#171;срезы&#187;.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

# Словарь
population_dict = {'California': 38332521,
                   'Texas': 26448193,
                   'New York': 19651127,
                   'Florida': 19552860,
                   'Illinois': 12882135}
population = pd.Series(population_dict)
print('population:')
print(population)

# Доступ к элементам
print("population['California']:")
print(population['California'])

# Срез
print("population['California':'New York']:")
print(population['California':'New York'])</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">population:
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135
dtype: int64

population['California']:
38332521

population['California':'New York']:
California    38332521
Texas         26448193
New York      19651127
dtype: int64</pre>



<h3 class="wp-block-heading">Создание объектов Series</h3>



<p>Мы уже изучили несколько способов создания объектов Series библиотеки Pandas с нуля.</p>



<p>Все они представляют собой различные варианты следующего <strong>синтаксиса Pandas Series</strong> (общий вид синтаксиса):</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">pd.Series(data, index=index)</pre>



<p>где <strong>index </strong>— необязательный аргумент, а <strong>data </strong>может быть одной из множества сущностей.</p>



<p>Например, аргумент data может быть списком или массивом NumPy. В этом случае index по умолчанию будет целочисленной последовательностью:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

data = pd.Series([2, 4, 6])
print(data)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">0    2
1    4
2    6
dtype: int64</pre>



<p>Аргумент data может быть скалярным значением, которое будет повторено нужное количество раз для заполнения заданного индекса:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

data = pd.Series(5, index=[100, 200, 300])
print(data)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">100    5
200    5
300    5
dtype: int64</pre>



<p>Аргумент data может быть словарем, в котором index по умолчанию является отсортированными ключами этого словаря:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

data = pd.Series({2:'a', 1:'b', 3:'c'})
print(data)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">2    a
1    b
3    c
dtype: object</pre>



<p>В каждом случае индекс можно указать вручную, если необходимо получить другой результат:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

data = pd.Series({2:'a', 1:'b', 3:'c'}, index=[3, 2])
print(data)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">3    c
2    a
dtype: object</pre>



<p>Обратите внимание, что объект Series заполняется только заданными явным образом ключами.</p>



<h2 class="wp-block-heading">Объект DataFrame библиотеки Pandas</h2>



<p>Следующая базовая структура библиотеки Pandas — <strong>объект DataFrame</strong>. Как и объект Series, объект DataFrame можно рассматривать или как обобщение массива NumPy, или как специализированную версию словаря Python. Изучим оба варианта.</p>



<h3 class="wp-block-heading">DataFrame как обобщенный массив NumPy</h3>



<p>Если объект <strong>Series </strong>— аналог одномерного массива с гибкими индексами, объект <strong>DataFrame </strong>— аналог двумерного массива с гибкими индексами строк и гибкими именами столбцов. Аналогично тому, что двумерный массив можно рассматривать как упорядоченную последовательность выровненных столбцов, объект DataFrame можно рассматривать как упорядоченную последовательность выровненных объектов Series. <strong>Под «выровненными» имеется в виду то, что они используют один и тот же индекс.</strong></p>



<p>Чтобы продемонстрировать это, сначала создадим новый объект Series, содержащий площадь каждого из пяти упомянутых в предыдущем разделе штатов:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

area_dict = {'California': 423967,
             'Texas': 695662,
             'New York': 141297,
             'Florida': 170312,
             'Illinois': 149995}
area = pd.Series(area_dict)
print(area)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
dtype: int64</pre>



<p>Воспользовавшись объектом population класса <strong>Series</strong>, сконструируем на основе словаря единый двумерный объект, содержащий всю эту информацию:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

# Словарь площадь штатов
area_dict = {'California': 423967,
             'Texas': 695662,
             'New York': 141297,
             'Florida': 170312,
             'Illinois': 149995}
area = pd.Series(area_dict)

# Словарь население
population_dict = {'California': 38332521,
                   'Texas': 26448193,
                   'New York': 19651127,
                   'Florida': 19552860,
                   'Illinois': 12882135}
population = pd.Series(population_dict)

# Создаем DataFrame
states = pd.DataFrame({'population': population, 'area': area})
print(states)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">            population    area
California    38332521  423967
Texas         26448193  695662
New York      19651127  141297
Florida       19552860  170312
Illinois      12882135  149995</pre>



<p>Аналогично объекту Series у объекта DataFrame имеется атрибут <strong>index</strong>, обеспечивающий доступ к меткам индекса. Еще у объекта DataFrame есть атрибут <strong>columns</strong>, представляющий собой содержащий метки столбцов объект Index.</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

# Словарь площадь штатов
area_dict = {'California': 423967,
             'Texas': 695662,
             'New York': 141297,
             'Florida': 170312,
             'Illinois': 149995}
area = pd.Series(area_dict)

# Словарь население
population_dict = {'California': 38332521,
                   'Texas': 26448193,
                   'New York': 19651127,
                   'Florida': 19552860,
                   'Illinois': 12882135}
population = pd.Series(population_dict)

# Создаем DataFrame
states = pd.DataFrame({'population': population, 'area': area})

print('Индексы - states.index:')
print(states.index)
print('')
print('Колонки - states.columns:')
print(states.columns)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Индексы - states.index:
Index(['California', 'Texas', 'New York', 'Florida', 'Illinois'], dtype='object')

Колонки - states.columns:
Index(['population', 'area'], dtype='object')</pre>



<p>Таким образом, объект DataFrame можно рассматривать как обобщение двумерного массива NumPy, где как у строк, так и у столбцов есть обобщенные индексы для доступа к данным.</p>



<h3 class="wp-block-heading">Объект DataFrame как специализированный словарь</h3>



<p><strong>DataFrame </strong>можно рассматривать как специализированный словарь. Если словарь задает соответствие ключей значениям, то DataFrame задает соответствие имени столбца объекту <strong>Series </strong>с данными этого столбца. Например, запрос данных по атрибуту &#8216;area&#8217; приведет к тому, что будет возвращен объект Series, содержащий площади штатов:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

# Словарь площадь штатов
area_dict = {'California': 423967,
             'Texas': 695662,
             'New York': 141297,
             'Florida': 170312,
             'Illinois': 149995}
area = pd.Series(area_dict)

# Словарь население
population_dict = {'California': 38332521,
                   'Texas': 26448193,
                   'New York': 19651127,
                   'Florida': 19552860,
                   'Illinois': 12882135}
population = pd.Series(population_dict)

# Создаем DataFrame
states = pd.DataFrame({'population': population, 'area': area})

print(states['area'])</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">California    423967
Texas         695662
New York      141297
Florida       170312
Illinois      149995
Name: area, dtype: int64</pre>



<h3 class="wp-block-heading">Создание объектов DataFrame</h3>



<p>Существует множество способов создания объектов DataFrame библиотеки Pandas. Вот несколько примеров.</p>



<h4 class="wp-block-heading">Из одного объекта Series</h4>



<p><strong>Объект DataFrame</strong> — набор объектов Series. </p>



<p>DataFrame, состоящий из одного столбца, можно создать на основе одного объекта Series:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

# Словарь население
population_dict = {'California': 38332521,
                   'Texas': 26448193,
                   'New York': 19651127,
                   'Florida': 19552860,
                   'Illinois': 12882135}
population = pd.Series(population_dict)

df = pd.DataFrame(population, columns=['population'])

print(df)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">            population
California    38332521
Texas         26448193
New York      19651127
Florida       19552860
Illinois      12882135</pre>



<h4 class="wp-block-heading">Из списка словарей</h4>



<p>Любой список словарей можно преобразовать в объект DataFrame. Мы воспользуемся простым списковым включением для создания данных:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

data = [{'a': i, 'b': 2 * i}
        for i in range(3)]

print('data:')
print(data)
print('')

df = pd.DataFrame(data)
print('df:')
print(df)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">data:
[{'a': 0, 'b': 0}, {'a': 1, 'b': 2}, {'a': 2, 'b': 4}]

df:
   a  b
0  0  0
1  1  2
2  2  4</pre>



<p>Даже если некоторые ключи в словаре отсутствуют, библиотека Pandas просто заполнит их значениями NaN (то есть Not a number — «не является числом»):</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

df = pd.DataFrame([{'a': 1, 'b': 2}, {'b': 3, 'c': 4}])
print('df:')
print(df)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">df:
     a  b    c
0  1.0  2  NaN
1  NaN  3  4.0</pre>



<h4 class="wp-block-heading">Из словаря объектов Series</h4>



<p>Объект DataFrame также можно создать на основе словаря объектов Series (этот пример был приведен ранее):</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

# Словарь площадь штатов
area_dict = {'California': 423967,
             'Texas': 695662,
             'New York': 141297,
             'Florida': 170312,
             'Illinois': 149995}
area = pd.Series(area_dict)

# Словарь население
population_dict = {'California': 38332521,
                   'Texas': 26448193,
                   'New York': 19651127,
                   'Florida': 19552860,
                   'Illinois': 12882135}
population = pd.Series(population_dict)

# Создаем DataFrame
df = pd.DataFrame({'population': population,
                   'area': area})

print(df)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">            population    area
California    38332521  423967
Texas         26448193  695662
New York      19651127  141297
Florida       19552860  170312
Illinois      12882135  149995 </pre>



<h4 class="wp-block-heading">Из двумерного массива NumPy</h4>



<p>Если у нас есть двумерный массив данных, мы можем создать объект DataFrame с любыми заданными именами столбцов и индексов. Для каждого из пропущенных значений будет использоваться целочисленный индекс:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

df = pd.DataFrame(np.random.rand(3, 2),
                  columns=['foo', 'bar'],
                  index=['a', 'b', 'c'])
print(df)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">        foo       bar
a  0.290872  0.647270
b  0.690850  0.950563
c  0.468706  0.344193</pre>



<h4 class="wp-block-heading">Из структурированного массива NumPy</h4>



<p>Объект DataFrame библиотеки Pandas ведет себя во многом аналогично структурированному массиву библиотеки NumPy и может быть создан непосредственно из него:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import numpy as np
import pandas as pd

A = np.zeros(3, dtype=[('A', 'i8'), ('B', 'f8')])
print('A:')
print(A)
print('')

df = pd.DataFrame(A)
print('df:')
print(df)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">A:
[(0, 0.) (0, 0.) (0, 0.)]

df:
   A    B
0  0  0.0
1  0  0.0
2  0  0.0</pre>



<h2 class="wp-block-heading">Объект Index библиотеки Pandas</h2>



<p>Как объект <strong>Series</strong>, так и объект <strong>DataFrame </strong>содержат явный <strong>индекс</strong>, обеспечивающий возможность ссылаться на данные и модифицировать их.</p>



<p><strong>Объект Index</strong> можно рассматривать или как неизменяемый массив (immutable array), или как упорядоченное множество (ordered set) (формально мультимножество, так как объекты Index могут содержать повторяющиеся значения). Из этих способов его представления следуют некоторые интересные возможности операций над объектами Index. В качестве простого примера создадим Index из списка целых чисел:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

ind = pd.Index([2, 3, 5, 7, 11])
print(ind)</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Int64Index([2, 3, 5, 7, 11], dtype='int64')</pre>



<h3 class="wp-block-heading">Объект Index как неизменяемый массив</h3>



<p><strong>Объект Index</strong> во многом ведет себя аналогично массиву. Например, для извлечения из него значений или срезов можно использовать стандартную нотацию индексации языка Python. У объектов Index есть много атрибутов.</p>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">ind[1]
3

ind[::2]
Int64Index([2, 5, 11], dtype='int64')

ind.size, ind.shape, ind.ndim, ind.dtype
5 (5,) 1 int64</pre>



<p>Одно из различий между объектами Index и массивами NumPy — <strong>неизменяемость индексов</strong>, то есть их нельзя модифицировать стандартными средствами:</p>



<pre class="EnlighterJSRAW" data-enlighter-language="python" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">import pandas as pd

ind = pd.Index([2, 3, 5, 7, 11])
ind[1] = 0</pre>



<p><strong>Результат:</strong></p>



<pre class="EnlighterJSRAW" data-enlighter-language="generic" data-enlighter-theme="" data-enlighter-highlight="" data-enlighter-linenumbers="" data-enlighter-lineoffset="" data-enlighter-title="" data-enlighter-group="">Traceback (most recent call last):
  File "C:/Users/User/Desktop/test.py", line 4, in &lt;module>
    ind[1] = 0
  File "C:\Users\User\AppData\Local\Programs\Python\Python37-32\lib\site-packages\pandas\core\indexes\base.py", line 3938, in __setitem__
    raise TypeError("Index does not support mutable operations")
TypeError: Index does not support mutable operations</pre>



<p>Неизменяемость делает безопаснее совместное использование индексов несколькими объектами DataFrame и массивами, исключая возможность побочных эффектов в виде случайной модификации индекса по неосторожности.</p>


<h1 class="ff b fg fn cn"><strong>Выбор подмножеств данных в Pandas</strong></h1>
<h2>Анатомия Python Pandas DataFrame &#8212; Column, Index, Data</h2>
<p>Рассмотрим изображение контейнера данных DataFrame (библиотеки Pandas):</p>
<p><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/python_pandas_dataframe_structure_anatomy.png" alt="" width="1258" height="412" class="alignnone wp-image-245 size-full" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/python_pandas_dataframe_structure_anatomy.png 1258w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/python_pandas_dataframe_structure_anatomy-300x98.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/python_pandas_dataframe_structure_anatomy-768x252.png 768w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/python_pandas_dataframe_structure_anatomy-1024x335.png 1024w" sizes="(max-width: 1258px) 100vw, 1258px" /></p>
<p><strong>Три компонента DataFrame:</strong></p>
<p><strong>DataFrame</strong> состоит из трех различных компонентов: <strong>индекса , столбцов и данных.</strong> Данные также известны как значения.</p>
<p><strong>Индекс</strong> &#8212; это последовательность значений в левой части DataFrame. Каждое отдельное значение индекса называется index label, Иногда индекс упоминается как заголовки строк. В приведенном выше примере метки строк не очень интересны и представляют собой целые числа, начиная с 0 до n-1, где n &#8212; количество строк в таблице.<br /><strong></strong></p>
<p><strong>Столбцы</strong> представляют собой последовательность значений в самой верхней части DataFrame.</p>
<p>Все остальное является <strong>данными или значениями</strong>. Иногда вы будете слышать, как датафреймы называют<strong> табличными данными</strong>. Это просто еще одно имя для данных прямоугольной таблицы со строками и столбцами.</p>
<p><strong>Каждая строка имеет метку, каждая колонка имеет метку</strong></p>
<p>Основной вывод из <strong>анатомии DataFrame</strong> заключается в том, что каждая строка имеет метку, каждый столбец имеет метку. Эти <strong>метки используются для ссылки на конкретные строки или столбцы</strong> в DataFrame.</p>
<h2 id="2636" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Что такое выбор подмножества?</span></h2>
<p id="1500" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Прежде чем мы начнем делать выбор подмножества, было бы хорошо определить, что это такое. <strong>Выбор подмножества</strong> &#8212; это просто выбор определенных строк и столбцов данных из <strong>DataFrame</strong> (или Series). Это может означать выбор всех строк и некоторых столбцов, некоторых строк и всех столбцов или некоторых строк и столбцов.</span></p>
<h2 id="c635" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выбор при помощи []</span></h2>
<h3>Загружаем данные из CSV в Pandas DataFrame (Python 3)</h3>
<p>В совокупности <strong>[], .loc и .iloc</strong> называются <strong>индексаторами</strong>. Это самые распространенные способы выбора данных.</p>
<p><strong>Скачать файл для использования в примерах:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/SampleData_Pandas.csv"><em><strong>SampleData_Pandas.csv</strong></em></a></p>
<p><strong>Код загрузки данных из csv в Pandas DataFrame:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';', index_col=0)
print(df)</pre>
<p><strong>Результат:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/dataframe_pandas_data_example.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/dataframe_pandas_data_example.png" alt="" width="681" height="418" class="aligncenter size-full wp-image-254" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/dataframe_pandas_data_example.png 681w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/dataframe_pandas_data_example-300x184.png 300w" sizes="(max-width: 681px) 100vw, 681px" /></a></p>
<p><strong>Вариант 2 загрузки данных из CSV (Index генерируется самостоятельно)</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')
print(df)</pre>
<p><strong>Результат:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/dataframe_pandas_data_example2.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/dataframe_pandas_data_example2.png" alt="" width="634" height="531" class="aligncenter size-full wp-image-256" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/dataframe_pandas_data_example2.png 634w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/dataframe_pandas_data_example2-300x251.png 300w" sizes="(max-width: 634px) 100vw, 634px" /></a></p>
<h3 id="5c39" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Извлечение отдельных компонентов DataFrame</span></h3>
<p id="b25d" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Ранее мы упоминали три компоненты DataFrame. <strong>Индекс, столбцы и данные (значения).</strong> Мы можем извлечь каждый из этих компонентов в свои переменные. Давайте сделаем это, а затем осмотрим их:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

index = df.index
columns = df.columns
values = df.values

index_list = df.index.tolist()
columns_list = df.columns.tolist()
values_list = df.values.tolist()

print('+++++ БЕЗ TOLIST() +++++')
print(index)
print('==========================')
print(columns)
print('==========================')
print(values)
print('==========================')


print('+++++ С TOLIST() +++++')
print(index_list)
print('==========================')
print(columns_list)
print('==========================')
print(values_list)</pre>
<p><strong>Результат:</strong></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/view_dataframe_pandas_index_columns_values_tolist.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/view_dataframe_pandas_index_columns_values_tolist.png" alt="" width="925" height="504" class="aligncenter size-full wp-image-263" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/view_dataframe_pandas_index_columns_values_tolist.png 925w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/view_dataframe_pandas_index_columns_values_tolist-300x163.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/view_dataframe_pandas_index_columns_values_tolist-768x418.png 768w" sizes="(max-width: 925px) 100vw, 925px" /></a></p>
<h3 id="ddf0" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Типы данных компонентов</span></h3>
<p id="ec73" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Давайте выведем тип каждого компонента, чтобы точно понять, что это за объект.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

index = df.index
columns = df.columns
values = df.values

index_list = df.index.tolist()
columns_list = df.columns.tolist()
values_list = df.values.tolist()

print('+++++ БЕЗ TOLIST() +++++')
print(type(index))
print('==========================')
print(type(columns))
print('==========================')
print(type(values))
print('==========================')


print('+++++ С TOLIST() +++++')
print(type(index_list))
print('==========================')
print(type(columns_list))
print('==========================')
print(type(values_list))</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">+++++ БЕЗ TOLIST() +++++
&lt;class 'pandas.core.indexes.range.RangeIndex'&gt;
==========================
&lt;class 'pandas.core.indexes.base.Index'&gt;
==========================
&lt;class 'numpy.ndarray'&gt;
==========================

+++++ С TOLIST() +++++
&lt;class 'list'&gt;
==========================
&lt;class 'list'&gt;
==========================
&lt;class 'list'&gt;</pre>
<h4 id="2665" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Понимание этих типов</span></h4>
<p id="2f50" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Интересно, что и индекс, и столбцы имеют одинаковый тип. Они оба </span><code class="gw gx gy gz ha b"></code><strong class="hd js">Index-</strong><span>объект Pandas. Этот объект сам по себе довольно мощный, но сейчас вы можете думать о нем как о последовательности меток для строк или столбцов.</span></p>
<p id="eaa7" class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho" data-selectable-paragraph=""><span>Значения (ячейки таблицы) &#8212; это </span><strong class="hd js">numpy.ndarray</strong><span>, который обозначает n-мерный массив и является основным контейнером данных в библиотеке <strong>NumPy</strong>. </span></p>
<blockquote>
<p class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho" data-selectable-paragraph=""><strong>Pandas построен непосредственно поверх NumPy, и именно этот массив отвечает за большую часть рабочей нагрузки.</strong></p>
</blockquote>
<h3 id="01b1" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выбор одного столбца как серии</span></h3>
<p id="f598" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Чтобы выбрать один столбец данных, просто поместите имя столбца в скобках. Давайте выберем столбец <strong>Подразделение</strong>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df['Подразделение'])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">0            Отдел продаж
1       Отдел продвижения
2       Отдел продвижения
3       Отдел продвижения
              ...        
2662         Отдел продаж
2663         Отдел продаж
2664         Отдел продаж
2665    Отдел продвижения
2666    Отдел продвижения
2667    Отдел продвижения
2668    Отдел продвижения
Name: Подразделение, Length: 2669, dtype: object</pre>
<h4 id="8f6b" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Анатомия Series, возвращаемой при выборе 1 столбца</span></h4>
<p id="347d" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Выбор одного столбца данных возвращает другой контейнер данных <strong>Pandas Series</strong>. </span></p>
<p class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span><strong>Series</strong> &#8212; это одномерная последовательность помеченных данных. Существует два основных компонента Серии: </span><strong class="hd js"><span>указатель</span></strong><span> и </span><strong class="hd js"><span>данные</span></strong><span> (или </span><strong class="hd js"><span>значения</span></strong><span> . В серии нет колонок.</span></p>
<p id="20c7" class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho" data-selectable-paragraph=""><span>Визуальное отображение Series &#8212; это просто текст, в отличие от красиво оформленной таблицы для DataFrames.</span></p>
<p id="cf25" class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho" data-selectable-paragraph=""><span>Вы также заметите две дополнительные части данных в нижней части <strong>Series</strong>. </span></p>
<p class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho" data-selectable-paragraph=""><span><strong>Name</strong> из <strong>Series</strong> становится старое имя колонки. Вы также увидите тип данных или <strong>dtype</strong></span><strong class="hd js"> </strong><span>серии. Вы можете игнорировать оба этих элемента на данный момент. А также количество элементов <strong>Length</strong>.</span></p>
<h3 id="f7c1" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выбор нескольких столбцов с помощью оператора индексации</span></h3>
<p id="4f39" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Можно выбрать несколько столбцов только с помощью оператора индексации, передав ему список имен столбцов. Давайте выберем <em><strong>&#8216;Подразделение&#8217;, &#8216;Менеджер&#8217;, &#8216;Номенклатура&#8217;, &#8216;Продажи&#8217;</strong></em></span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df[['Подразделение','Менеджер','Номенклатура','Продажи']])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">          Подразделение    Менеджер Номенклатура       Продажи
0          Отдел продаж      Петров         Лыжи   956898,3051
1     Отдел продвижения     Сидоров   Велосипеды   1841949,153
2     Отдел продвижения     Сидоров        Доски   1052542,373
3     Отдел продвижения     Сидоров      Палатки   74478,81356
4          Отдел продаж    Илинская   Велосипеды   1649745,763
5          Отдел продаж    Илинская        Доски   1263241,525
...                 ...         ...          ...           ...
2661       Отдел продаж      Петров       Прочее   423,7288136
2662       Отдел продаж    Илинская         Лыжи  -15254,23729
2663       Отдел продаж      Петров         Лыжи   8176271,186
2664       Отдел продаж      Петров       Прочее   171186,4407
2665  Отдел продвижения  Охлобыстин       Прочее   16949,15254
2666  Отдел продвижения    Розницов         Лыжи   15254,23729
2667  Отдел продвижения    Розницов       Одежда   1444915,254
2668  Отдел продвижения    Розницов       Прочее   3389,830508

[2669 rows x 4 columns]</pre>
<h4 id="f1af" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выбор нескольких столбцов возвращает DataFrame</span></h4>
<p id="b2f8" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Выбор нескольких столбцов возвращает DataFrame. На самом деле вы можете выбрать один столбец как DataFrame со списком из одного элемента:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df[['Подразделение']])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">          Подразделение
0          Отдел продаж
1     Отдел продвижения
2     Отдел продвижения
...                 ...
2666  Отдел продвижения
2667  Отдел продвижения
2668  Отдел продвижения

[2669 rows x 1 columns]</pre>
<p><span>Хотя это напоминает <strong>Series</strong>, технически это <strong>DataFrame</strong>, другой объект.</span></p>
<h3 id="dfc4" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Порядок столбцов не имеет значения</span></h3>
<p id="7b89" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>При выборе нескольких столбцов вы можете выбрать их в любом порядке по вашему выбору. Это не должен быть тот же самый порядок как оригинальный DataFrame.</span></p>
<p data-selectable-paragraph=""><span>Например, давайте выберем <strong>Номенклатура, Подразделение</strong>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df[['Номенклатура','Подразделение']])</pre>
<p data-selectable-paragraph=""><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">     Номенклатура      Подразделение
0            Лыжи       Отдел продаж
1      Велосипеды  Отдел продвижения
2           Доски  Отдел продвижения
3         Палатки  Отдел продвижения
4      Велосипеды       Отдел продаж
...           ...                ...
2666         Лыжи  Отдел продвижения
2667       Одежда  Отдел продвижения
2668       Прочее  Отдел продвижения

[2669 rows x 2 columns]</pre>
<h3 id="205b" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Исключения, при выполнении скрипта</span></h3>
<p id="3152" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Есть несколько общих исключений, которые возникают при выполнении выборок только с помощью оператора индексации.</span></p>
<ul class="">
<li id="2d16" class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho is hv hw" data-selectable-paragraph=""><span>Если вы ошиблись словом, вы получите </span><strong class="hd js">KeyError</strong></li>
<li id="511a" class="hb hc cn ar hd b he ib hg ic hi id hk ie hm if ho is hv hw" data-selectable-paragraph=""><span>Если вы забыли использовать список, содержащий несколько столбцов, вы также получите </span><strong class="hd js">KeyError</strong></li>
</ul>
<pre class="EnlighterJSRAW" data-enlighter-language="null">print(df['ПодразделениЯ'])
Результат: 
KeyError: 'ПодразделениЯ'

print(df['Номенклатура','Подразделение'])
Результат:
KeyError: ('Номенклатура', 'Подразделение')</pre>
<p>В первом случае должно стоять <code class="EnlighterJSRAW">print(df['Подразделение'])</code>. А во-втором случае: <code class="EnlighterJSRAW" data-enlighter-language="null">print(df[['Номенклатура','Подразделение']])</code>.</p>
<h2>Выборка данных из Pandas DataFrame с помощью .loc</h2>
<p><span>В </span><strong class="hd js">.loc </strong><span>индексатор выбирает данные по-другому, чем просто оператор индексации. Он может выбирать подмножества строк и/или столбцов. Самое главное, он выбирает данные только по </span><strong class="hd js"><span>метке</span></strong><span><strong> (label)</strong> строк и столбцов.</span></p>
<h3 id="a176" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выберем одну строку как Series с .loc</span></h3>
<p id="0a00" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span></span><strong class="hd js">.loc &#8212; </strong><span>Индексатор возвращает одну строку в серии, когда указали одну метку строки (один индекс).</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[0])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">Дата                 01.01.2016
Подразделение      Отдел продаж
Контрагент           Абакус ООО
Менеджер                 Петров
Номенклатура               Лыжи
Продажи             956898,3051
Себестоимость       621983,8983
Валовая прибыль     334914,4068
Name: 0, dtype: object</pre>
<p>Теперь у нас есть Series, где старые имена столбцов теперь являются индексными метками.</p>
<h3 id="8c75" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выбираем несколько строк из DataFrame с помощью .loc</span></h3>
<p id="1ffb" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Чтобы выбрать несколько строк, поместите все метки строк, которые вы хотите выбрать, в список и передайте их <strong>.loc</strong></span><span>. Давайте выберем 3 и 20</span><span>.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[[3,20]])</pre>
<p data-selectable-paragraph=""><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">          Дата      Подразделение  ... Себестоимость Валовая прибыль
3   01.01.2016  Отдел продвижения  ...   55859,11017     18619,70339
20  01.01.2016       Отдел продаж  ...   80585,27542     26861,75847

[2 rows x 8 columns]</pre>
<h3 id="8449" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Обозначение среза для выборки диапазона строк с .loc</span></h3>
<p id="0752" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Можно «нарезать» строки DataFrame с </span><code class="gw gx gy gz ha b">.loc</code><span>помощью </span><strong class="hd js"><span>нотации среза</span></strong><span>. Для обозначения среза используется двоеточие для разделения значений </span><strong class="hd js"><span>начала</span></strong><span>, </span><strong class="hd js"><span>остановки</span></strong><span> и </span><strong class="hd js"><span>шага</span></strong><span> . Например, мы можем выбрать все строки из с 134 по 139</span><span>:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[134:139])</pre>
<p data-selectable-paragraph=""><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">           Дата      Подразделение  ... Себестоимость Валовая прибыль
134  01.01.2016  Отдел продвижения  ...   560,5932203     62,28813559
135  01.01.2016       Отдел продаж  ...   625773,3051     268188,5593
136  01.01.2016  Отдел продвижения  ...   508671,6102     218002,1186
137  01.01.2016  Отдел продвижения  ...   1034427,966     443326,2712
138  01.01.2016  Отдел продвижения  ...   55792,37288     18597,45763
139  01.01.2016  Отдел продвижения  ...   8477,542373     941,9491525

[6 rows x 8 columns]</pre>
<h4 id="6c5f" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>.loc включает в себя последнее значение из обозначения среза</span></h4>
<p id="88ad" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Обратите внимание, что строка с пометкой 139 в примере без шага </span><span>была выведена. В других контейнерах данных, таких как списки Python, последнее значение исключается.</span></p>
<h4>Вывод среза с использованием .loc и шага из DataFrame</h4>
<p data-selectable-paragraph="">Выведем тот же самый результат, только будем выводить каждый второй элемент из среза:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[134:139:2])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">           Дата      Подразделение  ... Себестоимость Валовая прибыль
134  01.01.2016  Отдел продвижения  ...   560,5932203     62,28813559
136  01.01.2016  Отдел продвижения  ...   508671,6102     218002,1186
138  01.01.2016  Отдел продвижения  ...   55792,37288     18597,45763

[3 rows x 8 columns]</pre>
<h4>Выбор до указанной позиции .loc</h4>
<p><strong>Пример скрипта Python 3 для вывода 139 первых строк из Pandas DataFrame:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[:139])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">           Дата      Подразделение  ... Себестоимость Валовая прибыль
0    01.01.2016       Отдел продаж  ...   621983,8983     334914,4068
1    01.01.2016  Отдел продвижения  ...   1289364,407     552584,7458
2    01.01.2016  Отдел продвижения  ...    736779,661     315762,7119
3    01.01.2016  Отдел продвижения  ...   55859,11017     18619,70339
..          ...                ...  ...           ...             ...
136  01.01.2016  Отдел продвижения  ...   508671,6102     218002,1186
137  01.01.2016  Отдел продвижения  ...   1034427,966     443326,2712
138  01.01.2016  Отдел продвижения  ...   55792,37288     18597,45763
139  01.01.2016  Отдел продвижения  ...   8477,542373     941,9491525

[140 rows x 8 columns]</pre>
<p>Тот же самый пример, но выведем с шагом 25:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[:139:25])</pre>
<p><strong>Результат выполнения выборки данных из Pandas DataFrame:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">           Дата      Подразделение  ... Себестоимость Валовая прибыль
0    01.01.2016       Отдел продаж  ...   621983,8983     334914,4068
25   01.01.2016       Отдел продаж  ...   12813,55932     5491,525424
50   01.01.2016       Отдел продаж  ...   42978,81356     14326,27119
75   01.01.2016  Отдел продвижения  ...   6246,610169     694,0677966
100  01.01.2016  Отдел продвижения  ...   89694,91525     38440,67797
125  01.01.2016  Отдел продвижения  ...   879864,4068     377084,7458

[6 rows x 8 columns]</pre>
<h4>Выбор с указанной позиции до конца DataFrame через .loc</h4>
<p><strong>Полный код вывода данных из Pandas DataFrame:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[2660:])</pre>
<p><strong>Результат запроса к DataFrame:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">            Дата      Подразделение  ... Себестоимость Валовая прибыль
2660  01.12.2017       Отдел продаж  ...   762,7118644     84,74576271
2661  01.12.2017       Отдел продаж  ...   381,3559322     42,37288136
2662  01.12.2017       Отдел продаж  ...  -9915,254237    -5338,983051
2663  01.12.2017       Отдел продаж  ...   5314576,271     2861694,915
2664  01.12.2017       Отдел продаж  ...   154067,7966     17118,64407
2665  01.12.2017  Отдел продвижения  ...   15254,23729     1694,915254
2666  01.12.2017  Отдел продвижения  ...   9915,254237     5338,983051
2667  01.12.2017  Отдел продвижения  ...   1083686,441     361228,8136
2668  01.12.2017  Отдел продвижения  ...   3050,847458     338,9830508

[9 rows x 8 columns]</pre>
<p>Тот же пример, но с шагом 3 (<strong>вывод каждого третьего элемента из Pandas DataFrame с использованием .iloc[]</strong>):</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[2660::3])</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">            Дата      Подразделение  ... Себестоимость Валовая прибыль
2660  01.12.2017       Отдел продаж  ...   762,7118644     84,74576271
2663  01.12.2017       Отдел продаж  ...   5314576,271     2861694,915
2666  01.12.2017  Отдел продвижения  ...   9915,254237     5338,983051

[3 rows x 8 columns]</pre>
<h3 id="472b" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv">Выбор строк и столбцов одновременно с .loc</h3>
<p id="2a14" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>В отличие от просто оператора индексирования, можно выбирать строки и столбцы одновременно с </span><code class="gw gx gy gz ha b">.loc</code><span>. Вы делаете это, разделяя выбранные строки и столбцы </span><strong class="hd js"><span>запятой</span></strong><span>. Это будет выглядеть примерно так:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">df.loc [row_selection, column_selection]</pre>
<p><strong>Пример запроса на Python 3:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[[150,163],['Подразделение','Менеджер','Продажи']])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">         Подразделение Менеджер      Продажи
150       Отдел продаж   Петров   1067796,61
163  Отдел продвижения  Сидоров  13665,25424</pre>
<h3 id="b8d6" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Используйте любую комбинацию выбора для строки или столбца с .loc</span></h3>
<p id="952c" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Выбор строки или столбца может быть совершен любым из следующих способов:</span></p>
<ul class="">
<li id="7ed7" class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho is hv hw" data-selectable-paragraph=""><span>Один ярлык</span></li>
<li id="3f7f" class="hb hc cn ar hd b he ib hg ic hi id hk ie hm if ho is hv hw" data-selectable-paragraph=""><span>Список ярлыков</span></li>
<li id="8fef" class="hb hc cn ar hd b he ib hg ic hi id hk ie hm if ho is hv hw" data-selectable-paragraph=""><span>slice с метками</span></li>
</ul>
<p id="a767" class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho" data-selectable-paragraph=""><span>Мы можем использовать любой из этих трех вариантов для выбора строки или столбца с помощью </span><code class="gw gx gy gz ha b"></code><strong class="hd js">.loc</strong><span>. Давайте посмотрим несколько примеров.</span></p>
<p data-selectable-paragraph=""><strong>Пример 1 &#171;Выборка данных из Pandas DataFrame&#187;:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[150:163:3,['Подразделение','Менеджер','Продажи']])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">         Подразделение  Менеджер      Продажи
150       Отдел продаж    Петров   1067796,61
153  Отдел продвижения  Добряков  82944,91525
156  Отдел продвижения  Добряков  85023,30508
159       Отдел продаж    Петров  499385,5932
162  Отдел продвижения   Сидоров  130805,0847</pre>
<h3 id="281b" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выбор строк и столбцов через переменные</span></h3>
<p id="5371" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Гораздо проще назначить список строк и столбцов переменным перед использованием в </span><code class="gw gx gy gz ha b">.loc</code><span>. Это полезно, если вы выбираете много строк или столбцов:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

rows = [59, 134, 1045]
columns = ['Контрагент', 'Номенклатура', 'Продажи'] 
print(df.loc[rows, columns])</pre>
<p data-selectable-paragraph=""><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">        Контрагент Номенклатура      Продажи
59        ИП Лусон   Велосипеды  1139110,169
134        Союз АО       Прочее  622,8813559
1045  Эсвольтр ООО       Прочее  2915,254237</pre>
<p data-selectable-paragraph=""><strong>Пример параметризации с slice:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

iStart = 59
iEnd = 134
iStep = 7
columns = ['Контрагент', 'Номенклатура', 'Продажи'] 
print(df.loc[iStart:iEnd:iStep, columns])</pre>
<p data-selectable-paragraph=""><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

iStart = 59
iEnd = 134
iStep = 7
columns = ['Контрагент', 'Номенклатура', 'Продажи'] 
print(df.loc[iStart:iEnd:iStep, columns])</pre>
<h2 id="2864" class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho">Выборка данных из Pandas DataFrame с помощью индексатора .iloc[]</h2>
<p>.iloc индексатор очень похож на .loc, но использует только целое число позиций, по которым необходимо сделать выборку.</p>
<h3>Выбор одной строки при помощи .iloc</h3>
<p><span>Передав одно целое число в </span><code class="gw gx gy gz ha b">.iloc</code><span>, он выберет одну строку в качестве ряда:</span></p>
<p><strong>Код запроса:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.iloc[5])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">Дата                  01.01.2016
Подразделение       Отдел продаж
Контрагент         Билли Боб ООО
Менеджер                Илинская
Номенклатура               Доски
Продажи              1263241,525
Себестоимость        884269,0678
Валовая прибыль      378972,4576
Name: 5, dtype: object</pre>
<h3 id="3c23" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выбор нескольких строк с .iloc</span></h3>
<p id="bc35" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>Используйте список целых чисел, чтобы выбрать несколько строк:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.iloc[[5,45,876]])</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">           Дата      Подразделение  ... Себестоимость Валовая прибыль
5    01.01.2016       Отдел продаж  ...   884269,0678     378972,4576
45   01.01.2016       Отдел продаж  ...   162972,4576     69845,33898
876  01.08.2016  Отдел продвижения  ...   444322,0339     190423,7288

[3 rows x 8 columns]</pre>
<h3 id="c375" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv"><span>Выборка диапазона строк через указание среза в .iloc</span></h3>
<p id="e0e5" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph=""><span>В случае с .iloc нотация слайса работает так же, как и список, и исключает последний элемент.</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.iloc[5:9])</pre>
<p data-selectable-paragraph=""><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">         Дата      Подразделение  ... Себестоимость Валовая прибыль
5  01.01.2016       Отдел продаж  ...   884269,0678     378972,4576
6  01.01.2016       Отдел продаж  ...   16517,47881     5505,826271
7  01.01.2016       Отдел продаж  ...   1098,305085     122,0338983
8  01.01.2016  Отдел продвижения  ...   22957,62712     9838,983051

[4 rows x 8 columns]</pre>
<h1 id="8023" class="gi gj cn ar aq gk gl gm gn go gp gq gr gs gt gu gv" data-selectable-paragraph=""><span>Выбор строк и столбцов одновременно в .iloc</span></h1>
<p id="0485" class="hb hc cn ar hd b he hf hg hh hi hj hk hl hm hn ho" data-selectable-paragraph="">Рассмотрим несколько примеров, чтобы понять, чем отличается .iloc от .loc.</p>
<p id="e2d4" class="hb hc cn ar hd b he hp hg hq hi hr hk hs hm ht ho" data-selectable-paragraph=""><span>Выберем две строки и два столбца:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.iloc[[2,3], [0,3]])</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">         Дата Менеджер
2  01.01.2016  Сидоров
3  01.01.2016  Сидоров</pre>
<p>Осуществим выборку строк и столбцов с помощью среза:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.iloc[2:9, 0:3])</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">         Дата      Подразделение     Контрагент
2  01.01.2016  Отдел продвижения     Абакус ООО
3  01.01.2016  Отдел продвижения     Абакус ООО
4  01.01.2016       Отдел продаж  Билли Боб ООО
5  01.01.2016       Отдел продаж  Билли Боб ООО
6  01.01.2016       Отдел продаж  Билли Боб ООО
7  01.01.2016       Отдел продаж  Билли Боб ООО
8  01.01.2016  Отдел продвижения  Билли Боб ООО</pre>
<p><strong>Выберем 1 значение из столбца и указанной колонки:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd
import numpy as np

df = pd.read_csv('D:\#python#\example\SampleData_Pandas.csv', sep=';')

print(df.loc[3, 4])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">Палатки</pre>
<h2>Резюме по .loc и .iloc</h2>
<p><strong>Доступ к строкам и колонкам по индексу возможен несколькими способами:</strong></p>
<ul>
<li><strong>.loc</strong> &#8212; используется для доступа по строковой метке &#8212; т.е. фактически по значению индекса и по названию столбца</li>
<li><strong>.iloc</strong> &#8212; используется для доступа по числовому значению (начиная от 0) &#8212; т.е. по номеру строки и номеру столбца</li>
</ul>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python3_For_Data_Science.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python3_For_Data_Science.png" alt="" width="2339" height="1654" class="aligncenter size-full wp-image-303" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python3_For_Data_Science.png 2339w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python3_For_Data_Science-300x212.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python3_For_Data_Science-768x543.png 768w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python3_For_Data_Science-1024x724.png 1024w" sizes="(max-width: 2339px) 100vw, 2339px" /></a></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python_selections_and_indexing.png"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python_selections_and_indexing.png" alt="" width="1400" height="1000" class="aligncenter size-full wp-image-304" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python_selections_and_indexing.png 1400w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python_selections_and_indexing-300x214.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python_selections_and_indexing-768x549.png 768w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Pandas_DataFrame_Python_selections_and_indexing-1024x731.png 1024w" sizes="(max-width: 1400px) 100vw, 1400px" /></a></p>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/cheat_sheet_pandas_dataframe_object.jpg"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/cheat_sheet_pandas_dataframe_object.jpg" alt="" width="1120" height="1576" class="aligncenter size-full wp-image-305" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/cheat_sheet_pandas_dataframe_object.jpg 1120w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/cheat_sheet_pandas_dataframe_object-213x300.jpg 213w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/cheat_sheet_pandas_dataframe_object-768x1081.jpg 768w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/cheat_sheet_pandas_dataframe_object-728x1024.jpg 728w" sizes="(max-width: 1120px) 100vw, 1120px" /></a></p>
<h2 class="entry-title"><span>Как выбрать строки из Pandas DataFrame по условию</span></h2>
<p>Собираем тестовый набор данных для иллюстрации работы выборки по условию</p>
<table width="179">
<tbody>
<tr>
<td width="52"><strong>Color</strong></td>
<td width="79"><strong>Shape</strong></td>
<td width="48"><strong>Price</strong></td>
</tr>
<tr>
<td width="52">Green</td>
<td width="79">Rectangle</td>
<td width="48">10</td>
</tr>
<tr>
<td width="52">Green</td>
<td width="79">Rectangle</td>
<td width="48">15</td>
</tr>
<tr>
<td width="52">Green</td>
<td width="79">Square</td>
<td width="48">5</td>
</tr>
<tr>
<td width="52">Blue</td>
<td width="79">Rectangle</td>
<td width="48">5</td>
</tr>
<tr>
<td width="52">Blue</td>
<td width="79">Square</td>
<td width="48">10</td>
</tr>
<tr>
<td width="52">Red</td>
<td width="79">Square</td>
<td width="48">15</td>
</tr>
<tr>
<td width="52">Red</td>
<td width="79">Square</td>
<td width="48">15</td>
</tr>
<tr>
<td width="52">Red</td>
<td width="79">Rectangle</td>
<td width="48">5</td>
</tr>
</tbody>
</table>
<p><strong>Пишем скрипт:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd

Boxes = {'Color': ['Green','Green','Green','Blue','Blue','Red','Red','Red'],
         'Shape': ['Rectangle','Rectangle','Square','Rectangle','Square','Square','Square','Rectangle'],
         'Price': [10,15,5,5,10,15,15,5]
        }

df = pd.DataFrame(Boxes, columns= ['Color','Shape','Price'])
print (df)</pre>
<p>Результат выполнения:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15
2  Green     Square      5
3   Blue  Rectangle      5
4   Blue     Square     10
5    Red     Square     15
6    Red     Square     15
7    Red  Rectangle      5</pre>
<h3>Синтаксис выборки строк из Pandas DataFrame по условию</h3>
<p><span>Вы можете использовать следующую логику для выбора строк в Pandas DataFrame по условию:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df.loc[df.column name condition]</pre>
<p><span>Например, если вы хотите получить строки с </span><em><span>зеленым цветом</span></em><span> , вам нужно применить:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">df.loc[df.Color == 'Green']</pre>
<p><span>Где:</span></p>
<ul>
<li><span><strong>Color</strong> &#8212; это название столбца</span></li>
<li><span><strong>Green</strong> &#8212; это условие (значение колонки)</span></li>
</ul>
<p><span>А вот полный код Python для нашего примера:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd

Boxes = {'Color': ['Green','Green','Green','Blue','Blue','Red','Red','Red'],
         'Shape': ['Rectangle','Rectangle','Square','Rectangle','Square','Square','Square','Rectangle'],
         'Price': [10,15,5,5,10,15,15,5]
        }

df = pd.DataFrame(Boxes, columns= ['Color','Shape','Price'])
print (df.loc[df.Color == 'Green'])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15
2  Green     Square      5</pre>
<h3><span>Выберем строки, где цена равна или больше 10</span></h3>
<p><span>Чтобы получить все строки, где цена равна или больше 10, Вам нужно применить следующее условие:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df.loc[df.Price &gt;= 10]</pre>
<p><span>Полный код Python:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd

Boxes = {'Color': ['Green','Green','Green','Blue','Blue','Red','Red','Red'],
         'Shape': ['Rectangle','Rectangle','Square','Rectangle','Square','Square','Square','Rectangle'],
         'Price': [10,15,5,5,10,15,15,5]
        }

df = pd.DataFrame(Boxes, columns= ['Color','Shape','Price'])

print (df.loc[df.Price &gt;= 10])</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15
4   Blue     Square     10
5    Red     Square     15
6    Red     Square     15</pre>
<h3>Выберем строки, в которых цвет зеленый, а форма &#8212; прямоугольник</h3>
<p><span>Теперь цель состоит в том, чтобы выбрать строки на основе </span><em><span>двух</span></em><span> условий:</span></p>
<ul>
<li><span>Color зеленый; </span><em><span>а также</span></em></li>
<li><span>Shape = прямоугольник</span></li>
</ul>
<p><span>Мы будем использовать символ </span><span><strong>&amp;</strong></span><span> для применения нескольких условий. В нашем примере код будет выглядеть так:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">df.loc[(df.Color == 'Green') &amp; (df.Shape == 'Rectangle')]</pre>
<p><strong>Полный код примера Python для выборки Pandas DataFrame:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd

Boxes = {'Color': ['Green','Green','Green','Blue','Blue','Red','Red','Red'],
         'Shape': ['Rectangle','Rectangle','Square','Rectangle','Square','Square','Square','Rectangle'],
         'Price': [10,15,5,5,10,15,15,5]
        }

df = pd.DataFrame(Boxes, columns= ['Color','Shape','Price'])

print (df.loc[(df.Color == 'Green') &amp; (df.Shape == 'Rectangle')])
</pre>
<p><strong>Результат:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">   Color      Shape  Price
0  Green  Rectangle     10
1  Green  Rectangle     15</pre>
<h3>Выберем строки, где цвет зеленый ИЛИ форма прямоугольная</h3>
<p><span>Для достижения этой цели будем использовать</span><span> </span><span>символ | следующим образом:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df.loc[(df.Color == 'Green') | (df.Shape == 'Rectangle')]</pre>
<p><strong>Полный код Python 3:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">import pandas as pd

Boxes = {'Color': ['Green','Green','Green','Blue','Blue','Red','Red','Red'],
         'Shape': ['Rectangle','Rectangle','Square','Rectangle','Square','Square','Square','Rectangle'],
         'Price': [10,15,5,5,10,15,15,5]
        }

df = pd.DataFrame(Boxes, columns= ['Color','Shape','Price'])

print (df.loc[(df.Color == 'Green') | (df.Shape == 'Rectangle')])</pre>
<p>Результат:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">   Color      Shape  Price<br />0  Green  Rectangle     10<br />1  Green  Rectangle     15<br />2  Green     Square      5<br />3   Blue  Rectangle      5<br />7    Red  Rectangle      5</pre>
<h3>Выберем строки, где цена не равна 15</h3>
<p>Мы будем использовать комбинацию символов !=, чтобы выбрать строки, цена которых не равна 15:</p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df.loc[df.Price != 15]</pre>
<p><strong>Полный код Pandas DF на питоне:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">import pandas as pd

Boxes = {'Color': ['Green','Green','Green','Blue','Blue','Red','Red','Red'],
         'Shape': ['Rectangle','Rectangle','Square','Rectangle','Square','Square','Square','Rectangle'],
         'Price': [10,15,5,5,10,15,15,5]
        }

df = pd.DataFrame(Boxes, columns= ['Color','Shape','Price'])

print (df.loc[df.Price != 15])</pre>
<p><strong>Результат работы скрипта Python:</strong></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">   Color      Shape  Price
0  Green  Rectangle     10
2  Green     Square      5
3   Blue  Rectangle      5
4   Blue     Square     10
7    Red  Rectangle      5</pre>
<h1><strong>Data Wrangling with Pandas</strong></h1>
<ul>
<li><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet.pdf">Data Wrangling Pandas Cheat Sheet.pdf</a></li>
<li><a href="https://towardsdatascience.com/data-wrangling-with-pandas-5b0be151df4e" target="_blank" rel="noopener noreferrer">Data Wrangling With Pandas</a></li>
</ul>
<p><a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_1.png" target="_blank" rel="noopener noreferrer"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_1.png" alt="" width="3056" height="2362" class="aligncenter wp-image-311 size-full" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_1.png 3056w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_1-300x232.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_1-768x594.png 768w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_1-1024x791.png 1024w" sizes="(max-width: 3056px) 100vw, 3056px" /></a> <a href="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_2.png" target="_blank" rel="noopener noreferrer"><img decoding="async" src="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_2.png" alt="" width="3056" height="2362" class="aligncenter wp-image-312 size-full" srcset="https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_2.png 3056w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_2-300x232.png 300w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_2-768x594.png 768w, https://python.ivan-shamaev.ru/wp-content/uploads/2019/04/Data_Wrangling_Pandas_Cheat_Sheet_2-1024x791.png 1024w" sizes="(max-width: 3056px) 100vw, 3056px" /></a></p>
<h2><strong>Обработка данных с помощью Pandas (<span style="color: #ff6600;">Data Wrangling</span>)</strong></h2>
<p>Обработка данных является одной из важнейших задач в data science и анализе данных, которая включает такие операции, как:</p>
<ul>
<li><strong>Dealing with missing values (Работа с пропущенными значениями)</strong> &#8212; количественная оценка пропущенных значений для каждого столбца, заполнение и удаление пропущенных значений.</li>
<li><strong>Reshaping data (Изменение формы данных)</strong> &#8212; единая кодировка данных, сводные таблицы, объединения, группировка и агрегирование.</li>
<li><strong>Data Sorting (Сортировка данных)</strong>: упорядочивание значений в порядке возрастания или убывания.</li>
<li><strong>Data Filtration (Фильтрация данных)</strong>: создание подмножества данных согласно тем или иным условиям.</li>
<li><strong>Data deduplication (Дедупликация данных)</strong> &#8212; это технология поиска и устранения дубликатов в хранилищах данных. Применяется для снижения накладные расходов на хранение информации.</li>
<li><strong>Data Reduction (Понижение размерности/Сокращение данных)</strong>: Уменьшение объема данных, сокращение количества используемых признаков и разнообразия их значений. Применяется в случае, когда данные избыточны. Избыточность возникает тогда, когда задачу анализа можно решить с тем же уровнем эффективности и точности, но используя меньшую размерность данных. Это позволяет сократить время и вычислительные затраты на решение задачи, сделать данные и результаты их анализа более интерпретируемыми и понятными для пользователя.</li>
<li><strong>Data Access (Доступ к данным)</strong>: для чтения или записи файлов данных.</li>
<li><strong>Data Handling/Data Processing (Обработка данных) или Data Transformation (преобразование данных)</strong>: выполнение агрегации, статистических и подобных операций над конкретными значениями.</li>
<li><strong>Другое:</strong> Создание описательных столбцов, поэлементные условные операции.</li>
</ul>
<h3><strong>Concatenation DataFrame</strong></h3>
<p>todo</p>
<h3><strong>Joining DataFrame</strong></h3>
<p>todo</p>
<h3><strong>Merging DataFrame</strong></h3>
<p>todo</p>
<h3><strong>Pivot &amp; Melt (Unpivot) DataFrame</strong></h3>
<p>todo</p>
<h3><strong>GroupBy Операции</strong></h3>
<p>todo</p>
<h3><strong>Применение Lambda функции в DataFrame</strong></h3>
<p>todo</p>
<h1 class="eg b eh eo ef"><strong>10 трюков Python Pandas, которые сделают вашу работу более эффективной</strong></h1>
<p><span><strong>Pandas</strong> &#8212; это широко используемый пакет Python для структурированных данных.</span></p>
<h2 id="893e" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij"><strong>read_csv</strong></h2>
<p id="6600" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>Все знают эту команду. Но данные, которые вы пытаетесь прочитать, велики, попробуйте добавить этот аргумент: </span><strong class="hk ip"><span>nrows = 5,</span></strong><span> чтобы загружать только часть данных. Тогда вы можете избежать ошибки, выбрав неправильный разделитель (он не всегда может быть разделен запятой).</span></p>
<p id="6108" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>(Или вы можете использовать команду &#8216;head&#8217; в linux, чтобы проверить первые 5 строк (скажем) в любом текстовом файле: </span><strong class="hk ip"><span>head -n 5 data.txt</span></strong><span>)</span></p>
<p id="5e92" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Затем вы можете извлечь список столбцов, используя </span><code class="gt iq ir is it b">df.columns.tolist()</code><span>для извлечения всех столбцов, а затем добавить </span><strong class="hk ip"><span>аргумент usecols = [&#8216;c1&#8217;, &#8216;c2&#8217;,…],</span></strong><span> чтобы загрузить нужные вам столбцы. </span></p>
<p class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Кроме того, если вы знаете типы данных нескольких определенных столбцов, вы можете добавить аргумент </span><strong class="hk ip"><span>dtype = {&#8216;c1&#8217;: str, &#8216;c2&#8217;: int,…},</span></strong><span> чтобы он загружался быстрее. </span></p>
<p class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Еще одно преимущество этого аргумента в том, что если у вас есть столбец, который содержит как строки, так и числа, рекомендуется объявить его тип строковым, чтобы не возникало ошибок при попытке объединить таблицы, используя этот столбец в качестве ключа.</span></p>
<h2 id="51fd" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij"><strong>select_dtypes</strong></h2>
<p id="fe3b" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>Если предварительная обработка данных должна выполняться в <strong>Python</strong>, эта команда сэкономит вам время. После чтения в таблице типами данных по-умолчанию для каждого столбца могут быть bool, int64, float64, object, category, timedelta64 или datetime64. Вы можете сначала проверить распределение по</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df.dtypes.value_counts()</pre>
<p id="e108" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>чтобы узнать все возможные типы данных вашего DataFrame</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">df.select_dtypes(include=['float64', 'int64'])</pre>
<p id="10fb" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>выбрать sub-dataframe только с числовыми характеристиками.</span></p>
<h2 id="ee83" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij">copy()</h2>
<p id="df2a" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>Это важная команда, если вы еще не слышали о ней. Если вы выполните следующие команды:</span></p>
<pre class="gd ge gf gg gh iu iv cm">import pandas as pd<br />df1 = pd.DataFrame({ 'a':[0,0,0], 'b': [1,1,1]})<br />df2 = df1<br />df2['a'] = df2['a'] + 1<br />df1.head()</pre>
<p id="e7ea" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Вы обнаружите, что <strong>df1</strong> изменен. Это потому, что <strong>df2 = df1</strong> не делает копию <strong>df1</strong> и присваивает ее <strong>df2</strong>, но устанавливает указатель, указывающий на <strong>df1</strong>. Таким образом, любые изменения в <strong>df2</strong> приведут к изменениям в <strong>df1</strong>. Чтобы это исправить, вы можете сделать либо</span></p>
<pre class="gd ge gf gg gh iu iv cm">df2 = df1.copy()</pre>
<p id="eafe" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>или же</span></p>
<pre class="gd ge gf gg gh iu iv cm">from copy import deepcopy<br />df2 = deepcopy(df1)</pre>
<h2 id="be19" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij"><span>map()</span></h2>
<p id="0a1f" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>Это классная команда для простого преобразования данных. Сначала вы определяете словарь, в котором «ключами» являются старые значения, а «значениями» являются новые значения.</span></p>
<pre class="gd ge gf gg gh iu iv cm">level_map = {1: 'high', 2: 'medium', 3: 'low'}<br />df['c_level'] = df['c'].map(level_map)</pre>
<p id="1b9c" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span><strong>Некоторые примеры:</strong> </span></p>
<p class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>True, False до 1, 0 (для моделирования); определение уровней; определяемые пользователем лексические кодировки.</span></p>
<h2 id="0efe" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij">apply or not apply?</h2>
<p id="1a4c" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>Если мы хотим создать новый столбец с несколькими другими столбцами в качестве входных данных, функция apply иногда будет весьма полезна.</span></p>
<pre class="gd ge gf gg gh iu iv cm">def rule(x, y):<br />    if x == 'high' and y &gt; 10:<br />         return 1<br />    else:<br />         return 0<br />df = pd.DataFrame({ 'c1':[ 'high' ,'high', 'low', 'low'], 'c2': [0, 23, 17, 4]})<br />df['new'] = df.apply(lambda x: rule(x['c1'], x['c2']), axis =  1)<br />df.head()</pre>
<p id="1a16" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>В приведенных выше кодах мы определяем функцию с двумя входными переменными и используем функцию <strong>apply</strong>, чтобы применить ее к столбцам <strong>&#8216;c1&#8217;</strong> и <strong>&#8216;c2&#8217;</strong>.</span></p>
<p id="8ae2" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Но </span><strong class="hk ip"><span>проблема «apply» в том , что иногда он слишком медленный</span></strong><span> . Скажем, если вы хотите вычислить максимум из двух столбцов <strong>«c1»</strong> и <strong>«c2»</strong>, конечно, вы можете сделать</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df['maximum'] = df.apply(lambda x: max(x['c1'], x['c2']), axis = 1)</pre>
<p class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><code class="gt iq ir is it b"></code><span>но вы найдете это намного медленнее, чем эта команда:</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df['maximum'] = df[['c1','c2']].max(axis =1)</pre>
<p id="98d2" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><strong class="hk ip"><span>Вывод</span></strong><span>: не используйте apply, если вы можете выполнить ту же работу с другими встроенными функциями (они часто быстрее). Например, если вы хотите округлить колонку «с» целыми числами, делать </span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">round(df[‘c’], 0)</pre>
<p class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>или </span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="null">df[‘c’].round(0)</pre>
<p class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Вместо использования функции применяются: </span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df.apply(lambda x: round(x['c'], 0), axis = 1)</pre>
<h2 id="380f" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij">value counts</h2>
<p id="0012" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>Это команда для проверки распределения значений. Например, если вы хотите проверить возможные значения и частоту для каждого отдельного значения в столбце «c», вы можете сделать</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">df['c'].value_counts()</pre>
<p id="92e3" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Есть несколько полезных трюков / аргументов:</span><br /><span></span></p>
<ol>
<li><span><strong class="hk ip">normalize = True</strong></span><span>: если вы хотите проверить частоту вместо количества.</span><br /><span></span></li>
<li><span><strong class="hk ip">dropna = False</strong></span><span>: если вы также хотите включить пропущенные значения в статистику.</span><br /><span></span></li>
<li><code class="gt iq ir is it b">df['c'].value_counts().reset_index()</code><span>.: если вы хотите преобразовать таблицу статистики в кадр данных pandas и манипулировать ею</span><br /><span></span></li>
<li><code class="gt iq ir is it b">df['c'].value_counts().sort_index()</code><span>: показать статистику, отсортированную по разным значениям, в столбце «c» вместо счетчиков.</span></li>
</ol>
<h2 id="9d7c" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij"><span>number of missing values &#8212; количество пустых значений</span></h2>
<p id="74b7" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>При построении моделей может потребоваться исключить строку со слишком большим количеством пропущенных значений / строки со всеми пропущенными значениями. Вы можете использовать <strong>.isnull()</strong> и <strong>.sum()</strong> для подсчета количества пропущенных значений в указанных столбцах.</span></p>
<pre class="gd ge gf gg gh iu iv cm">import pandas as pd<br />import numpy as np<br />df = pd.DataFrame({ 'id': [1,2,3], 'c1':[0,0,np.nan], 'c2': [np.nan,1,1]})<br />df = df[['id', 'c1', 'c2']]<br />df['num_nulls'] = df[['c1', 'c2']].isnull().sum(axis=1)<br />df.head()</pre>
<h2 id="b2a7" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij"><span>выбрать строки с конкретными идентификаторами (select rows with specific IDs)</span></h2>
<p id="a7d2" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>В SQL мы можем сделать это, используя <strong>SELECT * FROM … WHERE ID in (‘A001’, ‘C022’, …)</strong>, чтобы получить записи с конкретными идентификаторами. Если вы хотите сделать то же самое с Pandas, вы можете сделать</span></p>
<pre class="gd ge gf gg gh iu iv cm">df_filter = df['ID'].isin(['A001','C022',...])<br />df[df_filter]</pre>
<h2 id="261c" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij"><span>Процентильные группы (Percentile groups)</span></h2>
<p id="c90c" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>У вас есть числовой столбец, и вы хотите классифицировать значения в этом столбце по группам, скажем, верхние 5% в группе 1, 5–20% в группе 2, 20–50% в группе 3, нижние 50% в группе 4 Конечно, вы можете сделать это с помощью pandas.cut, но я бы хотел предоставить здесь другую опцию:</span></p>
<pre class="gd ge gf gg gh iu iv cm">import numpy as np<br />cut_points = [np.percentile(df['c'], i) for i in [50, 80, 95]]<br />df['group'] = 1<br />for i in range(3):<br />    df['group'] = df['group'] + (df['c'] &lt; cut_points[i])<br /># or &lt;= cut_points[i]</pre>
<p id="d775" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>который быстро запускается (не применяется функция apply).</span></p>
<h2 id="5535" class="hw hx ef at as hy hz ia ib ic id ie if ig ih ii ij"><span>to_csv</span></h2>
<p id="9bd9" class="hi hj ef at hk b hl ik hn il hp im hr in ht io hv" data-selectable-paragraph=""><span>Опять же, это команда, которую все будут использовать. Я хотел бы указать на две уловки здесь. Первый</span></p>
<pre class="EnlighterJSRAW" data-enlighter-language="python">print(df[:5].to_csv())</pre>
<p id="0413" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Вы можете использовать эту команду, чтобы распечатать первые пять строк того, что будет записано в файл точно.</span></p>
<p id="e0c3" class="hi hj ef at hk b hl hm hn ho hp hq hr hs ht hu hv" data-selectable-paragraph=""><span>Еще один трюк &#8212; это смешанные целые числа и пропущенные значения. Если столбец содержит как пропущенные значения, так и целые числа, тип данных по-прежнему будет плавающим, а не целым. Когда вы экспортируете таблицу, вы можете добавить <strong class="hk ip">float_format=‘%.0f’</strong></span><strong class="hk ip"><span>,</span></strong><span> чтобы округлить все числа с плавающей точкой до целых чисел. Используйте этот трюк, если вам нужны только целочисленные выходные данные для всех столбцов &#8212; вы избавитесь от всех назойливых <strong>‘.0’s</strong>.</span></p><p><a class="a2a_button_telegram" href="https://www.addtoany.com/add_to/telegram?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="Telegram" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_whatsapp" href="https://www.addtoany.com/add_to/whatsapp?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="WhatsApp" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_facebook" href="https://www.addtoany.com/add_to/facebook?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="Facebook" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_linkedin" href="https://www.addtoany.com/add_to/linkedin?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="LinkedIn" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_vk" href="https://www.addtoany.com/add_to/vk?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="VK" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_twitter" href="https://www.addtoany.com/add_to/twitter?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="Twitter" rel="nofollow noopener" target="_blank"></a><a class="a2a_button_email" href="https://www.addtoany.com/add_to/email?linkurl=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&amp;linkname=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" title="Email" rel="nofollow noopener" target="_blank"></a><a class="a2a_dd addtoany_share_save addtoany_share" href="https://www.addtoany.com/share#url=https%3A%2F%2Fpython.ivan-shamaev.ru%2Fpandas-series-and-dataframe-objects-build-index%2F&#038;title=Python%203%20Pandas%3A%20%D0%9E%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D1%8B%20Series%20%D0%B8%20DataFrame.%20%D0%9F%D0%BE%D1%81%D1%82%D1%80%D0%BE%D0%B5%D0%BD%D0%B8%D0%B5%20Index" data-a2a-url="https://python.ivan-shamaev.ru/pandas-series-and-dataframe-objects-build-index/" data-a2a-title="Python 3 Pandas: Объекты Series и DataFrame. Построение Index"></a></p><p>Сообщение <a href="https://python.ivan-shamaev.ru/pandas-series-and-dataframe-objects-build-index/">Python 3 Pandas: Объекты Series и DataFrame. Построение Index</a> появились сначала на <a href="https://python.ivan-shamaev.ru">Python 3 | Data Science | Нейронные сети | AI - Искусственный Интеллект</a>.</p>
]]></content:encoded>
					
					<wfw:commentRss>https://python.ivan-shamaev.ru/pandas-series-and-dataframe-objects-build-index/feed/</wfw:commentRss>
			<slash:comments>3</slash:comments>
		
		
			</item>
	</channel>
</rss>
