You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Data-Science-For-Beginners/translations/bg/2-Working-With-Data/08-data-preparation/README.md

346 lines
28 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

<!--
CO_OP_TRANSLATOR_METADATA:
{
"original_hash": "3ade580a06b5f04d57cc83a768a8fb77",
"translation_date": "2025-08-26T14:40:18+00:00",
"source_file": "2-Working-With-Data/08-data-preparation/README.md",
"language_code": "bg"
}
-->
# Работа с данни: Подготовка на данни
|![ Скетч от [(@sketchthedocs)](https://sketchthedocs.dev) ](../../sketchnotes/08-DataPreparation.png)|
|:---:|
|Подготовка на данни - _Скетч от [@nitya](https://twitter.com/nitya)_ |
## [Тест преди лекцията](https://purple-hill-04aebfb03.1.azurestaticapps.net/quiz/14)
В зависимост от източника си, суровите данни може да съдържат несъответствия, които създават предизвикателства при анализа и моделирането. С други думи, тези данни могат да бъдат категоризирани като „замърсени“ и ще трябва да бъдат почистени. Тази лекция се фокусира върху техники за почистване и трансформиране на данни, за да се справим с предизвикателствата, свързани с липсващи, неточни или непълни данни. Темите, разгледани в тази лекция, ще използват Python и библиотеката Pandas и ще бъдат [демонстрирани в тетрадката](notebook.ipynb) в тази директория.
## Значението на почистването на данни
- **Лесна употреба и повторна употреба**: Когато данните са правилно организирани и нормализирани, те са по-лесни за търсене, използване и споделяне с други.
- **Последователност**: Науката за данни често изисква работа с повече от един набор от данни, където набори от данни от различни източници трябва да бъдат обединени. Увереността, че всеки отделен набор от данни има обща стандартизация, гарантира, че данните остават полезни, когато всички те се обединят в един набор от данни.
- **Точност на модела**: Почистените данни подобряват точността на моделите, които разчитат на тях.
## Често срещани цели и стратегии за почистване
- **Изследване на набор от данни**: Изследването на данни, което е разгледано в [по-късна лекция](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/4-Data-Science-Lifecycle/15-analyzing), може да ви помогне да откриете данни, които трябва да бъдат почистени. Визуалното наблюдение на стойностите в набор от данни може да създаде очаквания за това как изглежда останалата част от него или да даде представа за проблемите, които могат да бъдат решени. Изследването може да включва основни заявки, визуализации и вземане на проби.
- **Форматиране**: В зависимост от източника, данните може да имат несъответствия в начина, по който са представени. Това може да създаде проблеми при търсенето и представянето на стойностите, където те се виждат в набора от данни, но не са правилно представени във визуализации или резултати от заявки. Често срещаните проблеми с форматирането включват премахване на празни пространства, дати и типове данни. Решаването на проблеми с форматирането обикновено зависи от хората, които използват данните. Например стандартите за представяне на дати и числа могат да се различават в различните държави.
- **Дублиране**: Данни с повече от едно повторение могат да доведат до неточни резултати и обикновено трябва да бъдат премахнати. Това може да бъде често срещано явление при обединяване на два или повече набора от данни. Въпреки това, има случаи, когато дублирането в обединени набори от данни съдържа части, които могат да предоставят допълнителна информация и може да се наложи да бъдат запазени.
- **Липсващи данни**: Липсващите данни могат да доведат до неточности, както и до слаби или пристрастни резултати. Понякога те могат да бъдат решени чрез „презареждане“ на данните, попълване на липсващите стойности с изчисления и код като Python или просто премахване на стойността и съответните данни. Има много причини, поради които данните може да липсват, и действията, които се предприемат за решаване на тези липсващи стойности, могат да зависят от това как и защо са изчезнали.
## Изследване на информацията в DataFrame
> **Цел на обучението:** До края на този раздел трябва да сте уверени в намирането на обща информация за данните, съхранявани в pandas DataFrames.
След като заредите данните си в pandas, те най-вероятно ще бъдат в DataFrame (вижте предишния [урок](https://github.com/microsoft/Data-Science-For-Beginners/tree/main/2-Working-With-Data/07-python#dataframe) за подробен преглед). Но ако наборът от данни в DataFrame има 60,000 реда и 400 колони, откъде да започнете, за да разберете с какво работите? За щастие, [pandas](https://pandas.pydata.org/) предоставя удобни инструменти за бързо разглеждане на общата информация за DataFrame, както и за първите и последните няколко реда.
За да изследваме тази функционалност, ще импортираме библиотеката Python scikit-learn и ще използваме емблематичен набор от данни: **Iris dataset**.
```python
import pandas as pd
from sklearn.datasets import load_iris
iris = load_iris()
iris_df = pd.DataFrame(data=iris['data'], columns=iris['feature_names'])
```
| |sepal length (cm)|sepal width (cm)|petal length (cm)|petal width (cm)|
|----------------------------------------|-----------------|----------------|-----------------|----------------|
|0 |5.1 |3.5 |1.4 |0.2 |
|1 |4.9 |3.0 |1.4 |0.2 |
|2 |4.7 |3.2 |1.3 |0.2 |
|3 |4.6 |3.1 |1.5 |0.2 |
|4 |5.0 |3.6 |1.4 |0.2 |
- **DataFrame.info**: За начало, методът `info()` се използва за отпечатване на обобщение на съдържанието в `DataFrame`. Нека разгледаме този набор от данни, за да видим какво имаме:
```python
iris_df.info()
```
```
RangeIndex: 150 entries, 0 to 149
Data columns (total 4 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 sepal length (cm) 150 non-null float64
1 sepal width (cm) 150 non-null float64
2 petal length (cm) 150 non-null float64
3 petal width (cm) 150 non-null float64
dtypes: float64(4)
memory usage: 4.8 KB
```
От това знаем, че наборът от данни *Iris* има 150 записа в четири колони без липсващи записи. Всички данни са съхранени като 64-битови числа с плаваща запетая.
- **DataFrame.head()**: След това, за да проверим действителното съдържание на `DataFrame`, използваме метода `head()`. Нека видим как изглеждат първите няколко реда на нашия `iris_df`:
```python
iris_df.head()
```
```
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
0 5.1 3.5 1.4 0.2
1 4.9 3.0 1.4 0.2
2 4.7 3.2 1.3 0.2
3 4.6 3.1 1.5 0.2
4 5.0 3.6 1.4 0.2
```
- **DataFrame.tail()**: Обратно, за да проверим последните няколко реда на `DataFrame`, използваме метода `tail()`:
```python
iris_df.tail()
```
```
sepal length (cm) sepal width (cm) petal length (cm) petal width (cm)
145 6.7 3.0 5.2 2.3
146 6.3 2.5 5.0 1.9
147 6.5 3.0 5.2 2.0
148 6.2 3.4 5.4 2.3
149 5.9 3.0 5.1 1.8
```
> **Извод:** Дори само като разгледате метаданните за информацията в DataFrame или първите и последните няколко стойности в него, можете веднага да получите представа за размера, формата и съдържанието на данните, с които работите.
## Работа с липсващи данни
> **Цел на обучението:** До края на този раздел трябва да знаете как да заменяте или премахвате null стойности от DataFrames.
Повечето от времето наборите от данни, които искате (или трябва) да използвате, съдържат липсващи стойности. Начинът, по който се обработват липсващите данни, носи със себе си фини компромиси, които могат да повлияят на крайния ви анализ и реалните резултати.
Pandas обработва липсващите стойности по два начина. Първият, който сте виждали в предишни раздели, е `NaN`, или Not a Number. Това всъщност е специална стойност, която е част от спецификацията на IEEE за числа с плаваща запетая и се използва само за обозначаване на липсващи стойности с плаваща запетая.
За липсващи стойности, различни от числа с плаваща запетая, pandas използва обекта `None` на Python. Макар че може да изглежда объркващо, че ще срещнете два различни вида стойности, които казват по същество едно и също, има основателни програмни причини за този дизайн и, на практика, този подход позволява на pandas да предостави добро решение за огромното мнозинство от случаи. Независимо от това, както `None`, така и `NaN` имат ограничения, които трябва да имате предвид по отношение на начина, по който могат да бъдат използвани.
Научете повече за `NaN` и `None` от [тетрадката](https://github.com/microsoft/Data-Science-For-Beginners/blob/main/4-Data-Science-Lifecycle/15-analyzing/notebook.ipynb)!
- **Откриване на null стойности**: В `pandas`, методите `isnull()` и `notnull()` са основните ви методи за откриване на null данни. И двата връщат булеви маски върху вашите данни. Ще използваме `numpy` за стойности `NaN`:
```python
import numpy as np
example1 = pd.Series([0, np.nan, '', None])
example1.isnull()
```
```
0 False
1 True
2 False
3 True
dtype: bool
```
Внимателно разгледайте изхода. Нещо изненадва ли ви? Макар че `0` е аритметичен null, той все пак е напълно валидно цяло число и pandas го третира като такова. `''` е малко по-фино. Макар че го използвахме в Раздел 1, за да представим празна стойност на низ, той все пак е обект от тип низ и не е представяне на null според pandas.
Сега нека обърнем това и използваме тези методи по начин, по който ще ги използвате на практика. Можете да използвате булеви маски директно като индекс на ``Series`` или ``DataFrame``, което може да бъде полезно, когато се опитвате да работите с изолирани липсващи (или налични) стойности.
> **Извод:** И методите `isnull()`, и `notnull()` дават подобни резултати, когато ги използвате в `DataFrame`: те показват резултатите и индекса на тези резултати, което ще ви помогне значително, докато се борите с вашите данни.
- **Премахване на null стойности**: Освен идентифициране на липсващи стойности, pandas предоставя удобен начин за премахване на null стойности от `Series` и `DataFrame`. (Особено при големи набори от данни, често е по-препоръчително просто да премахнете липсващите [NA] стойности от анализа си, отколкото да се справяте с тях по други начини.) За да видим това в действие, нека се върнем към `example1`:
```python
example1 = example1.dropna()
example1
```
```
0 0
2
dtype: object
```
Обърнете внимание, че това трябва да изглежда като вашия изход от `example3[example3.notnull()]`. Разликата тук е, че вместо просто да индексира върху маскираните стойности, `dropna` е премахнал тези липсващи стойности от `Series` `example1`.
Тъй като `DataFrame` има две измерения, те предоставят повече опции за премахване на данни.
```python
example2 = pd.DataFrame([[1, np.nan, 7],
[2, 5, 8],
[np.nan, 6, 9]])
example2
```
| | 0 | 1 | 2 |
|------|---|---|---|
|0 |1.0|NaN|7 |
|1 |2.0|5.0|8 |
|2 |NaN|6.0|9 |
(Забелязахте ли, че pandas преобразува две от колоните в числа с плаваща запетая, за да се справи с `NaN`?)
Не можете да премахнете единична стойност от `DataFrame`, така че трябва да премахнете цели редове или колони. В зависимост от това, което правите, може да искате да направите едното или другото, и затова pandas ви дава опции за двете. Тъй като в науката за данни колоните обикновено представляват променливи, а редовете представляват наблюдения, по-вероятно е да премахнете редове от данни; настройката по подразбиране за `dropna()` е да премахне всички редове, които съдържат null стойности:
```python
example2.dropna()
```
```
0 1 2
1 2.0 5.0 8
```
Ако е необходимо, можете да премахнете NA стойности от колони. Използвайте `axis=1`, за да го направите:
```python
example2.dropna(axis='columns')
```
```
2
0 7
1 8
2 9
```
Забележете, че това може да премахне много данни, които може да искате да запазите, особено в по-малки набори от данни. Какво ако искате да премахнете само редове или колони, които съдържат няколко или дори всички null стойности? Можете да зададете тези настройки в `dropna` с параметрите `how` и `thresh`.
По подразбиране, `how='any'` (ако искате да проверите сами или да видите какви други параметри има методът, изпълнете `example4.dropna?` в кодова клетка). Можете алтернативно да зададете `how='all'`, за да премахнете само редове или колони, които съдържат всички null стойности. Нека разширим нашия пример `DataFrame`, за да видим това в действие.
```python
example2[3] = np.nan
example2
```
| |0 |1 |2 |3 |
|------|---|---|---|---|
|0 |1.0|NaN|7 |NaN|
|1 |2.0|5.0|8 |NaN|
|2 |NaN|6.0|9 |NaN|
Параметърът `thresh` ви дава по-фин контрол: задавате броя на *не-null* стойностите, които ред или колона трябва да има, за да бъде запазен:
```python
example2.dropna(axis='rows', thresh=3)
```
```
0 1 2 3
1 2.0 5.0 8 NaN
```
Тук първият и последният ред са премахнати, защото съдържат само две не-null стойности.
- **Попълване на null стойности**: В зависимост от вашия набор от данни, понякога може да има повече смисъл да попълните null стойности с валидни, вместо да ги премахнете. Можете да използвате `isnull`, за да направите това на място, но това може да бъде трудоемко, особено ако имате много стойности за попълване. Тъй като това е толкова често срещана задача в науката за данни, pandas предоставя `fillna`, който връща копие на `Series` или `DataFrame` с липсващите стойности, заменени с избрана от вас стойност. Нека създадем друг пример `Series`, за да видим как това работи на практика.
```python
example3 = pd.Series([1, np.nan, 2, None, 3], index=list('abcde'))
example3
```
```
a 1.0
b NaN
c 2.0
d NaN
e 3.0
dtype: float64
```
Можете да попълните всички null записи с една стойност, като например `0`:
```python
example3.fillna(0)
```
```
a 1.0
b 0.0
c 2.0
d 0.0
e 3.0
dtype: float64
```
Можете да **попълните напред** null стойности, като използвате последната валидна стойност, за да попълните null:
```python
example3.fillna(method='ffill')
```
```
a 1.0
b 1.0
c 2.0
d 2.0
e 3.0
dtype: float64
```
Можете също така да **попълните назад**, за да разпространите следващата валидна стойност назад, за да попълните null:
```python
example3.fillna(method='bfill')
```
```
a 1.0
b 2.0
c 2.0
d 3.0
e 3.0
dtype: float64
```
Както може да предположите, това работи същото с `DataFrame`, но можете също така да зададете `axis`, по който да попълните null стойности. Вземайки отново използвания `example2`:
```python
example2.fillna(method='ffill', axis=1)
```
```
0 1 2 3
0 1.0 1.0 7.0 7.0
1 2.0 5.0 8.0 8.0
2 NaN 6.0 9.0 9.0
```
Забележете, че когато предишна стойност не е налична за попълване напред, null стойността остава.
> **Основна идея:** Има множество начини за справяне с липсващи стойности в наборите ви от данни. Конкретната стратегия, която използвате (премахване, заместване или дори как точно ги замествате), трябва да бъде продиктувана от спецификата на данните. Ще развиете по-добро усещане за това как да се справяте с липсващи стойности, колкото повече работите и взаимодействате с набори от данни.
## Премахване на дублирани данни
> **Цел на обучението:** До края на този подраздел трябва да се чувствате уверени в идентифицирането и премахването на дублирани стойности от DataFrame.
Освен липсващи данни, често ще се сблъсквате с дублирани данни в реални набори от данни. За щастие, `pandas` предоставя лесен начин за откриване и премахване на дублирани записи.
- **Идентифициране на дубликати: `duplicated`**: Можете лесно да откриете дублирани стойности, използвайки метода `duplicated` в pandas, който връща булева маска, указваща дали даден запис в `DataFrame` е дубликат на по-ранен. Нека създадем още един примерен `DataFrame`, за да видим това в действие.
```python
example4 = pd.DataFrame({'letters': ['A','B'] * 2 + ['B'],
'numbers': [1, 2, 1, 3, 3]})
example4
```
| |letters|numbers|
|------|-------|-------|
|0 |A |1 |
|1 |B |2 |
|2 |A |1 |
|3 |B |3 |
|4 |B |3 |
```python
example4.duplicated()
```
```
0 False
1 False
2 True
3 False
4 True
dtype: bool
```
- **Премахване на дубликати: `drop_duplicates`:** просто връща копие на данните, за които всички стойности на `duplicated` са `False`:
```python
example4.drop_duplicates()
```
```
letters numbers
0 A 1
1 B 2
3 B 3
```
И `duplicated`, и `drop_duplicates` по подразбиране разглеждат всички колони, но можете да зададете да се изследва само подмножество от колони във вашия `DataFrame`:
```python
example4.drop_duplicates(['letters'])
```
```
letters numbers
0 A 1
1 B 2
```
> **Основна идея:** Премахването на дублирани данни е съществена част от почти всеки проект в областта на науката за данни. Дублираните данни могат да променят резултатите от вашите анализи и да ви дадат неточни резултати!
## 🚀 Предизвикателство
Всички обсъдени материали са предоставени като [Jupyter Notebook](https://github.com/microsoft/Data-Science-For-Beginners/blob/main/2-Working-With-Data/08-data-preparation/notebook.ipynb). Освен това, след всяка секция има упражнения опитайте ги!
## [Тест след лекцията](https://purple-hill-04aebfb03.1.azurestaticapps.net/quiz/15)
## Преглед и самостоятелно обучение
Има много начини за откриване и подход към подготовката на данните ви за анализ и моделиране, а почистването на данните е важна стъпка, която изисква "практически" опит. Опитайте тези предизвикателства от Kaggle, за да изследвате техники, които този урок не е обхванал.
- [Предизвикателство за почистване на данни: Парсиране на дати](https://www.kaggle.com/rtatman/data-cleaning-challenge-parsing-dates/)
- [Предизвикателство за почистване на данни: Скалиране и нормализиране на данни](https://www.kaggle.com/rtatman/data-cleaning-challenge-scale-and-normalize-data)
## Задача
[Оценка на данни от формуляр](assignment.md)
---
**Отказ от отговорност**:
Този документ е преведен с помощта на AI услуга за превод [Co-op Translator](https://github.com/Azure/co-op-translator). Въпреки че се стремим към точност, моля, имайте предвид, че автоматизираните преводи може да съдържат грешки или неточности. Оригиналният документ на неговия роден език трябва да се счита за авторитетен източник. За критична информация се препоръчва професионален човешки превод. Не носим отговорност за недоразумения или погрешни интерпретации, произтичащи от използването на този превод.