Python: деректен өз есебіңізге дейін 31-сабақ (барлығы 56)
Лас дерек: жетіспейтін мәндер, қайталаулар және түрлер
Python курсының отызыншы сабағы. Дерек сынып келеді: сандар жол болып, қала үш түрлі жазылып, егіз жол мен бос ұяшық қоса келеді. `isna`, `errors="coerce"` бар `to_numeric`, `astype`, `drop_duplicates` — және сабақтың басты сұрағы: жетіспейтін мәнді тастау ма, толтыру ма, әрі оның құны қандай.
Не үшін керек
Осы кезге дейінгі сабақтардағы кестелер таза болды, өйткені оларды біз жаздық. Нағыздары басқаша келеді: сома — ішінде бос орны бар мәтін, қала үш рет әртүрлі жазылған, бір жол экспорт кезінде екі еселенген, ал ұяшықта «дерек жоқ» деп тұр.
Тазалау — бір реттік ұсақ-түйек емес, бағдарламаның бір бөлігі, әрі оның ережесі бар: әр әрекет із қалдырады. Қанша жол болды, қанша болды, нақты не өзгерді. Онымен не істелгенін ешкім айта алмайтын кесте лас кестеден де жаман.
Бірден тұтас
uborka.py файлы. Сегіз жол, оларда әдетте сынатынның бәрі сынған.
"""30-сабақ: сынып келгенді жөндеу.
Сегіз жол, оларда әдетте сынатынның бәрі сынған: жетіспейтін мәндер, қайталау,
жол болып келген сандар, үш түрлі жазылған қала. Бір-бірлеп жөндеп, не
өзгергенін санаймыз.
"""
import pandas as pd
rows = [
("Қостанай", "тамақ", "4 200", "2026-01-03"),
("қостанай ", "жанармай", "18 500", "2026-01-05"),
("Рудный", "тамақ", "2 600", "2026-01-07"),
("Рудный", "тамақ", "2 600", "2026-01-07"),
("ҚОСТАНАЙ", "байланыс", "дерек жоқ", "2026-01-09"),
("Рудный", "жалдау", "62 000", "2026-01-11"),
("Қостанай", "жалдау", "95 000", None),
("Астана", "тамақ", "7 300", "2026-01-15"),
]
df = pd.DataFrame(rows, columns=["city", "kind", "amount", "day"])
print(df)
print("түрлері:", dict(df.dtypes.astype(str)))
print()
print("== не сынған: жөндер алдында қараймыз")
print("бағандардағы жетіспейтін мән:", df.isna().sum().to_dict())
print("толық қайталау:", int(df.duplicated().sum()))
print("қала болатын:", sorted(df["city"].unique()))
print()
print("== сандар: мәтін санға, қоқыс жетіспейтін мәнге")
df["amount"] = pd.to_numeric(df["amount"].str.replace(" ", "", regex=False), errors="coerce")
print("түрі енді:", df["amount"].dtype, "| жетіспейтін мән:", int(df["amount"].isna().sum()))
print()
print("== күндер: сол әдіс, тек күндер үшін errors='coerce'")
df["day"] = pd.to_datetime(df["day"], errors="coerce")
print("түрі енді:", df["day"].dtype, "| жетіспейтін мән:", int(df["day"].isna().sum()))
print()
print("== қалалар: үш жазылым — бір қала")
df["city"] = df["city"].str.strip().str.capitalize()
print("қала болды:", sorted(df["city"].unique()))
print()
print("== қайталау: алдымен санаймыз, сосын аламыз")
before = len(df)
df = df.drop_duplicates()
print(f"жол: {before} → {len(df)}")
print()
print("== жетіспейтін мән: тастау да, толтыру да — шешім, әдет емес")
print("сомасы жоқ жол:", int(df["amount"].isna().sum()))
paid = df.dropna(subset=["amount"])
print("санайтынымыз:", len(paid), "жол | сома:", int(paid["amount"].sum()))
print("ал нөлмен толтырсақ:", int(df["amount"].fillna(0).sum()), "— сома сол, бірақ орташа өтірік айтады")
print("бары бойынша орташа:", round(paid["amount"].mean(), 1),
"| нөлмен:", round(df["amount"].fillna(0).mean(), 1))
print()
print("== жолдың орнына санат: сол кесте, жады аз")
print("жолмен:", int(df["city"].memory_usage(deep=True)),
"| санатпен:", int(df["city"].astype("category").memory_usage(deep=True)))
Шығысы:
city kind amount day
0 Қостанай тамақ 4 200 2026-01-03
1 қостанай жанармай 18 500 2026-01-05
2 Рудный тамақ 2 600 2026-01-07
3 Рудный тамақ 2 600 2026-01-07
4 ҚОСТАНАЙ байланыс дерек жоқ 2026-01-09
5 Рудный жалдау 62 000 2026-01-11
6 Қостанай жалдау 95 000 NaN
7 Астана тамақ 7 300 2026-01-15
түрлері: {'city': 'str', 'kind': 'str', 'amount': 'str', 'day': 'str'}
== не сынған: жөндер алдында қараймыз
бағандардағы жетіспейтін мән: {'city': 0, 'kind': 0, 'amount': 0, 'day': 1}
толық қайталау: 1
қала болатын: ['Астана', 'Рудный', 'ҚОСТАНАЙ', 'Қостанай', 'қостанай ']
== сандар: мәтін санға, қоқыс жетіспейтін мәнге
түрі енді: float64 | жетіспейтін мән: 1
== күндер: сол әдіс, тек күндер үшін errors='coerce'
түрі енді: datetime64[us] | жетіспейтін мән: 1
== қалалар: үш жазылым — бір қала
қала болды: ['Астана', 'Рудный', 'Қостанай']
== қайталау: алдымен санаймыз, сосын аламыз
жол: 8 → 7
== жетіспейтін мән: тастау да, толтыру да — шешім, әдет емес
сомасы жоқ жол: 1
санайтынымыз: 6 жол | сома: 189600
ал нөлмен толтырсақ: 189600 — сома сол, бірақ орташа өтірік айтады
бары бойынша орташа: 31600.0 | нөлмен: 27085.7
== жолдың орнына санат: сол кесте, жады аз
жолмен: 725 | санатпен: 344
Талдау
Алдымен қарау, сосын жөндеу
Басқа жерден келген кез келген кестемен жұмыс басталатын үш жол:
df.isna().sum() әр бағанда қанша жетіспейтін мән бар
df.duplicated().sum() қанша егіз жол бар
df["city"].unique() шын мәнінде қанша түрлі мән бар
Әдетте көзді ашатыны — үшіншісі: үшеудің орнына бес «қала», өйткені бір жерде бос орын, бір жерде бас әріп. value_counts() соны сандарымен көрсетеді — сонда қай жазылым сирек, яғни қайсысы қате екені бірден көрінеді.
Мысалда үш жазылымды str.strip().str.capitalize() бір түрге келтіреді, әрі сабаққа осы жетеді. Жұмыста олай істеу қауіпті: capitalize қалған әріптердің бәрін кіші етеді, демек қысқарған атауларды (ЖШС), қос есімдерді және дефиспен жазылатын атауларды бұзады. Жазылым үшеуден асқан бойда сәйкестік кестесін жасайды — «қалай келді → қалай дұрыс» деген сөздік — әрі оны replace арқылы қолданады; сөздікте жоғының бәрі көрініп тұрады да, журналға түседі.
Сандар: astype емес, to_numeric
«дерек жоқ» кездесетін бағанда astype(float) тұтас құлайды: бір нашар ұяшық — бірде-бір сан жоқ. pd.to_numeric(..., errors="coerce") аударатынын аударады, аудара алмайтынын NaN-ға айналдырады. Бұл — адал қадам: түсініксіз мән нөлге емес, түсініксіз екені белгілі мәнге айналады.
Сан ішіндегі бос орындар аударудан бұрын алынады. Дәл осы жерде бөлек бағдарламаға тұратын тұзақ бар: бос орын бос орынға тең емес. Excel сан ішіне ажырамайтын бос орын, кейде жіңішке ажырамайтын бос орын қояды; экранда олар кәдімгісінен аумайды, ал replace(" ", "") оларға тимейді.
import pandas as pd
# Бос орындар әдейі кодпен жазылған: файлда олар кәдімгідей көрінеді.
# \u00a0 — Excel-ден келетін ажырамайтын бос орын, \u202f — жіңішке ажырамайтыны
raw = pd.Series(["1\u00a0200,50", "18\u202f500 ₸", "12%", "н/д"])
only_space = raw.str.replace(" ", "", regex=False)
print("тек кәдімгі бос орынды алдық:", pd.to_numeric(only_space, errors="coerce").tolist())
clean = (raw.str.replace("\u00a0", "", regex=False)
.str.replace("\u202f", "", regex=False)
.str.replace(" ", "", regex=False)
.str.replace("₸", "", regex=False)
.str.replace("%", "", regex=False)
.str.replace(",", ".", regex=False))
print("артықтың бәрін алдық: ", pd.to_numeric(clean, errors="coerce").tolist())
Шығысы:
тек кәдімгі бос орынды алдық: [nan, nan, nan, nan]
артықтың бәрін алдық: [1200.5, 18500.0, 12.0, nan]
Бірінші жол — төрт жетіспейтін мән: бұл сандарда кәдімгі бос орын мүлде болмаған. Сондықтан валютаны, пайызды және бос орынның әр түрін бөлек алады, ал ондық үтірді нүктеге ауыстырады — олар көбейгенде мұны тұрақты өрнекпен бір рет те жасауға болады.
Пайызбен бөлек сұрақ бар, әрі оны санаудан бұрын шешу керек: 12% — бұл 12 саны ма, әлде 0.12 үлесі ме? Жауап баған әрі қарай не үшін керегіне байланысты, әрі оны бір айдан кейін есіне түсіргеннен гөрі кодта қасына жазып қойған дұрыс.
Күндер сол әдіспен жөнделеді: pd.to_datetime(..., errors="coerce").
Түрлер: astype және жетіспейтін мәні бар бүтін сан
astype — дерек реттелген соң түрін ауыстыру үшін: astype("category"), astype("str"), astype("Int64").
Бәрі басатын тұзақ: жетіспейтін мәні бар бағанда astype(int) құлайды, өйткені кәдімгі бүтін сан бос бола алмайды:
IntCastingNaNError: Cannot convert non-finite values (NA or inf) to integer
Шығар жол — бас әріппен жазылатын Int64: бұл <NA> бола алатын бүтін сан. Кәдімгі int64 — жоқ.
Қайталаулар: толығы және кілт бойынша
df.duplicated() бұрын кездескен жолмен тұтас сәйкес келетін жолдарды табады. drop_duplicates() оларды алып тастайды.
Бірақ көбіне басқасы бүлдіреді: кілт бойынша қайталау — жолдар бір бағанда өзгеше, ал кілттері біреу. Сонда subset пен keep нені қайталау деп санауды және қай жолды қалдыруды шешеді:
df.drop_duplicates(subset=["city", "day"], keep="last")
keep="last" — кейінгі жазба ертерегінің түзетуі деп саналса. Бұл техникалық ұсақ-түйек емес, дерек мағынасы туралы шешім: first пен last-тың бірін таңдау арқылы екі жазбаның қайсысы шыншыл деген сұраққа жауап бересіз.
Мұны байқамаса, немен бітетінін жиырма тоғызыншы сабақ көрсетті: анықтама кілтіндегі қайталау біріктіру кезінде жолдарды көбейтеді.
Жетіспейтін мәндер: тастау ма, толтыру ма
Осы жерде техника бітіп, адалдық басталады.
dropna() жетіспейтін мәні бар жолдарды тастайды — тұтас немесе subset бойынша. fillna(мән) толтырады. Екеуі де — әдет емес, шешім.
Мысалдағы сандарға қараңыз. Сома өзгерген жоқ: fillna(0) нөл қосты, ал нөл сомада ештеңе білдірмейді. Ал орташа 31 600-ден 27 086-ға түсті — өйткені бос түбіртек болмаған нөл теңгелік түбіртекке айналды. Бір ғана амал бір сан үшін зиянсыз, екіншісі үшін өтірік.
Толтыруға болатын кез:
- әдепкі мән белгілі әрі ол нағыз: саны көрсетілмесе — демек, біреу;
- уақыт бойынша қатар, онда пәндік сала соңғы жарияланған мән келесі жаңартуға дейін күшінде деп айтады (
ffill): демалыс күнгі бағам — жұманың бағамы, оны сенбіде өлшегендіктен емес, ереже солай болғандықтан. Бұл — жорамал, әрі оны жазып қою керек: кодта да, есептің қасында да. Толтырылған мәндер бөлек бағанмен белгіленсе — жақсы: сонда қайсысы өлшем, қайсысы көшірме екені көрініп тұрады; - жетіспейтін мән — сөзбен айтуға келетін «белгісіз», әрі сіз санды емес, белгіні қоясыз:
"белгісіз","көрсетілмеген". Белгі — ойдан шығару емес, ол шындықты айтады.
Болмайтын кез:
- «есептеле берсін» деп сандық жетіспейтін мәнді орташамен, нөлмен немесе көршісімен толтыру. Бұл — ойдан шығарылған дерек, әрі кейін оны нағызынан ажырату мүмкін емес.
Жазып қоюға тұрарлық ереже: жетіспейтін мән — кедергі емес, факт. Олар қанша, қай жолдарда және олармен не істедіңіз — бұл жауаптың алдындағы қоқыс емес, жауаптың бір бөлігі.
Қосымша: жолдың орнына санат
Мәні аз, ал жолы көп баған үшін astype("category"): бес қала бір рет сақталады, бағанда олардың нөмірлері қалады. Мысалда 725 байт 344-ке айналады, ал миллион жолда жиырма төртінші сабақ 155 МБ-қа қарсы 9 МБ көрсетті.
Сабақ картасы
Өз сөзіңізбен айтыңыз
Қарамай, дауыстап немесе қағазға жауап беріңіз. Жауаптар — сабақтың соңында.
- Басқа жүйеден келген файлдың бағаны үшін
to_numeric(errors="coerce")astype(float)-тан несімен жақсы? fillna(0)соманы неге өзгерткен жоқ, ал орташаны неге өзгертті?- Жетіспейтін мәнді толтыру қашан адал, ал қашан дерек ойлап табу болады?
Жаттығу
Тапсырмаға дейінгі үш қысқа қадам: болжау, толықтыру, түзету. Жауаптар — сабақтың соңында, бірақ алдымен өзіңіз жауап беріңіз.
1. Болжаңыз. Бұл бағдарлама не басып шығарады?
import pandas as pd
amounts = pd.Series(["1200", "дерек жоқ", "4990"])
numbers = pd.to_numeric(amounts, errors="coerce")
print(numbers.tolist())
print("сома:", numbers.sum(), "| орташа:", numbers.mean(), "| count:", int(numbers.count()))
2. Бос орынды толтырыңыз. ... орнына «дерек жоқ» жетіспейтін мәнге айналатындай әрі бағдарлама құламайтындай етіңіз.
# бір нашар мән бүкіл бағанды бұзбауға тиіс
import pandas as pd
amounts = pd.Series(["1200", "дерек жоқ", "4990"])
numbers = pd.to_numeric(amounts, ...)
print(numbers.isna().sum(), "| түрі:", numbers.dtype)
3. Түзетіңіз. Бағдарлама IntCastingNaNError қатесімен құлайды. Жыл бүтін күйінде қалуға тиіс, ал жетіспейтін мән — жетіспейтін мән күйінде.
# кәдімгі бүтін сан бос бола алмайды
import pandas as pd
years = pd.Series([2024.0, 2025.0, None])
print(years.astype(int).tolist())
Тапсырма
Міндетті. Сегіз жолдық экспорт берілген: қала үш түрлі жазылған, сомаларда бос орын бар, сандардың орнына «дерек жоқ» пен «—» тұр, бір жол егіз. Оны ретке келтіріп, тазалау журналын басып шығарыңыз: қанша жол келді, тазалауға дейін қанша қала болды және тазалаудан кейін қанша қалды, қанша мән санға айналмады, қанша қайталау алынды және есепке қанша жол жетті. Содан кейін қалалар бойынша түбіртек санын, соманы және орташаны есептеңіз — тек сомасы белгілі жолдар бойынша.
Күтілетін шығыс:
тазалау журналы:
жол келді: 8
қала келді: 5
қала болды: 3 — ['Астана', 'Рудный', 'Қостанай']
санға айналмағаны: 2
алынған қайталау: 1
есепке кететін жол: 5 барлығынан 7
қалалар бойынша:
түбіртек барлығы орташа
city
Қостанай 3 117700.0 39233.0
Рудный 2 64600.0 32300.0
сомалар сәйкес: True
Дайын болғаны: шығыс жол-жолымен сәйкес келеді; сандар бір-бірлеп ауыстырумен емес, to_numeric(errors="coerce") арқылы алынған; қалалар бірегейлерін санағанға дейін бір түрге келтірілген; сомасы жоқ жолдар нөлмен толтырылмай, есептен шығарылған; журналда Астананың есепке жетпегені көрінеді — оның жалғыз түбіртегі сомасыз қалды.
Өз деректеріңізде. Сізге жіберілген кез келген файлды алып, оған тазалау журналын жазыңыз: «қарау» үш жолы бұрын және сонша кейін. Тазалаудан кейін жол саны бірер пайыздан артық азайса — тоқтап, нақты нені лақтырғаныңызды қараңыз.
Қалауыңыз бойынша.
- Өз қайталауларыңызда
keep="first"пенkeep="last"-ты салыстырып, қай жазба шыншыл екенін шешіңіз. - Өз мәтіндік бағаныңызда
astype("category")дейін және кейінmemory_usage(deep=True)өлшеңіз. - Күндер бойынша қатарда
ffill()қолданып көріп, мұның қай жағдайда адал екенін өзіңізге түсіндіріңіз.
Жобада бұл қайда тұрады
Он бірінші қадам: дереккөз бен есептің арасында тазалау пайда болады. sholu/tazalau.py екі нәрсе қайтарады — санауға жарамды кестені және не істегенінің журналын.
Ондағы ережелер — дәл сабақтағы: кілтсіз жол лақтырылады (бұл дерек ішіндегі жетіспеушілік емес, жолдың өзінің жоқтығы), қайталанған «ел мен жыл» жұбы да, сан емес нәрсе нөл емес, жетіспейтін мән болады, ал ел коды category-ге ауысады.
Есеп мұның ешқайсысын енді шешпейді — ол тек санайды. Оның өзінде бір шешім қалды, әрі ол сан емес, сөз туралы: анықтамада жоқ ел бос ұяшықтың орнына белгісіз белгісін алады. Жиырма тоғызыншы сабақтың қарызы осылай жабылады: есептегі бос ұяшық — ешкім жауап бермейтін сұрақ, ал белгі адал жауап береді.
Қарыздар. Тазалау журналы экранға басылады да, сонымен бірге жоғалады. Оның орны есептің қасында — өткен жіберіліммен салыстыруға болатын файлда; оған да серверге жеткен жерде жетеміз.
Жауаптар
Жауаптарды көрсету
Сұрақтарға
- Өйткені
astype(float)алғашқы түсініксіз мәннің өзінде құлап, ештеңе аудармайды, алto_numeric(errors="coerce")аудара алатынының бәрін аударып, түсініксізінNaNетеді — яғни «түсініксіз екені белгілі» етеді. Онымен әрі қарай жұмыс істеуге болады: санауға, көрсетуге, шешім қабылдауға. - Өйткені нөл сомаға ештеңе қоспайды, ал орташада тағы бір қосылғыш қосады. Бос түбіртек ешқашан болмаған нөл теңгелік түбіртекке айналды, әрі орташа 31 600-ден 27 086-ға түсті.
- Адал — нағыз әдепкі мән қойылғанда, пәндік сала ережесінің өзі бұрынғы мән келесі жаңартуға дейін күшінде дегенде және санның орнына «белгісіз» деген белгі қойылғанда. Алғашқы екеуінде жорамал жазылып қойылады, ал толтырылған мәндерді белгілеген жөн. Ойлап табу — формула есептелсін деп жетіспейтін мәнді орташамен не нөлмен толтырғанда: ондай деректі кейін нағызынан ажырата алмайсыз.
Жаттығуға
errors="coerce"«дерек жоқ» дегендіNaN-ға айналдырады, әрі бүкіл баған бөлшек санға айналады.sum()пенmean()жетіспейтін мәнді санамайды, алcount()олардың қанша мән бойынша есептелгенін көрсетеді.
[1200.0, nan, 4990.0]
сома: 6190.0 | орташа: 3095.0 | count: 2
errors="coerce". Онсызto_numericалғашқы аударылмайтын мәннің өзінде құлайды.
import pandas as pd
amounts = pd.Series(["1200", "дерек жоқ", "4990"])
numbers = pd.to_numeric(amounts, errors="coerce")
print(numbers.isna().sum(), "| түрі:", numbers.dtype)
1 | түрі: float64
astype("Int64")— бос бола алатын, бас әріппен жазылатын бүтін сан. Кәдімгіintбос бола алмайды, сондықтан құлайды.
import pandas as pd
years = pd.Series([2024.0, 2025.0, None])
print(years.astype("Int64").tolist())
[2024, 2025, <NA>]
Тапсырмаға
Қалалар бірегейлерін санағанға дейін бір түрге келтіріледі: әйтпесе есеп үш Қостанай алады әрі үшеуі де толық емес сомамен болады.
Сомасы жоқ жолдар нөлмен толтырылмай, шығарылған, әрі Астананың есепке кірмегені содан: оның жалғыз түбіртегі сансыз қалды. Бұл — дұрыс нәтиже, бірақ ол көрініп тұруға міндетті — журнал сол үшін басылады. Қаласы үнсіз жоғалған есеп ол қала мүлде болмаған есептен еш айырмасы жоқ.
Дереккөздер
- Жетіспейтін деректермен жұмыс —
isna,dropna,fillnaжәнеNaN-ның есептеудегі мінезі. - Түрлер және түрлендіру —
astype,to_numericжәне бос бола алатын бүтін сандар. - Санаттық түр — сөзден тұратын бағанды нөмірмен сақтау қашан тиімді.
Пікірлер (0)
Пікір қалдыру үшін кіріңіз →
Әзірге пікір жоқ. Бірінші болыңыз.