Python: деректен өз есебіңізге дейін 32-сабақ (барлығы 56)
Кестедегі уақыт: ресемплинг, жылжымалы орташа және адалдық
Python курсының отыз бірінші сабағы. Күн индексі тізім істей алмайтынды істейді: `asfreq` жоқ күндерді көрсетеді, `resample` күндерді аптаға жинайды, `rolling` тегістейді. Әрі тегістеудің өлшенген құны: ауқым екі есе кемиді, ал нағыз шыңның күні қатардан жоғалып кетеді.
Не үшін керек
Уақыт бойынша қатарлар кез келген жұмыста дерлік кездеседі: күндік бағам, сағаттық сатылым, минуттық есептегіш көрсеткіші. Олармен үш нәрсе істейді — ірілендіреді, тегістейді және өткен кезеңмен салыстырады, — әрі үшеуі де pandas-та дайын тұр.
Төртінші нәрсе де бар, ол бірде-бір кітапханада жоқ: өтірік айтпау. Тегістелген қатар нағызынан сенімдірек көрінеді, әрі оны нағызының орнына көрсету дәл сондықтан оңай. Сабақтың соңында бұл теңгемен өлшенген.
Бірден тұтас
vremya.py файлы. Бағамның қырық күнтізбелік күні, оның отызы жұмыс күні, әрі бір күні жаңалық болған.
"""31-сабақ: кестедегі уақыт.
Доллар бағамының қырық күні: жұмыс күндері бар, демалыс жоқ. Осымен ресемплинг
не істейді, жылжымалы орташа не істейді және екеуі қай жерден бастап өтірік
айта бастайды.
"""
import pandas as pd
# Қатар санауышпен құрылған: бәрінде бірдей. Онда демалыс күндері жоқ — нағыз
# биржа үзіндісіндегідей.
days, rates = [], []
start = pd.Timestamp("2026-01-05")
for i in range(40):
day = start + pd.Timedelta(days=i)
if day.weekday() >= 5:
continue
value = 512.0 + i * 0.35 + ((i * 7) % 11 - 5) * 0.6
if i == 21:
value += 14.0 # жаңалық күні: қатардың ортасындағы бір секіріс
days.append(day)
rates.append(value)
rate = pd.Series(rates, index=pd.DatetimeIndex(days, name="day"), name="rate").round(2)
print(rate.head(3))
print("нүкте:", len(rate), "|", rate.index.min().date(), "—", rate.index.max().date())
print()
print("== күн индексі тізім істей алмайтынды істейді")
print("қаңтар:", len(rate.loc["2026-01"]), "нүкте | бір күн:", rate.loc["2026-01-19"])
print("апта күндері:", sorted(set(rate.index.day_name())))
print()
print("== asfreq('D') тесіктерді көрсетеді")
daily = rate.asfreq("D")
print("нүкте болды:", len(daily), "| оның бос:", int(daily.isna().sum()))
print(daily.loc["2026-01-09":"2026-01-12"])
print()
print("== resample: күннің орнына апта")
weekly = rate.resample("W").agg(["mean", "min", "max", "count"]).round(2)
print(weekly.head(3))
print()
print("== rolling: бес күндік жылжымалы орташа")
smooth = rate.rolling(5).mean().round(2)
print("алғашқы төртеуі бос:", int(smooth.head(4).isna().sum()))
print(smooth.head(6))
print()
print("== тегістеу немен төлейді")
print("нағыз ауқым:", round(rate.max() - rate.min(), 2))
print("тегістелгеннің ауқымы:", round(smooth.max() - smooth.min(), 2))
print("максимум күні: нағызы", rate.idxmax().date(), "| тегістелгені", smooth.idxmax().date())
print("26 қаңтардағы секіріс: қатарда", rate.loc["2026-01-26"], "| тегістелгенде", smooth.loc["2026-01-26"])
print()
print("== алдыңғы күнмен салыстырғанда")
print((rate.diff().round(2)).head(3))
print("өскен күн:", int((rate.diff() > 0).sum()), "| түскен:", int((rate.diff() < 0).sum()))
Шығысы:
day
2026-01-05 509.00
2026-01-06 513.55
2026-01-07 511.50
Name: rate, dtype: float64
нүкте: 30 | 2026-01-05 — 2026-02-13
== күн индексі тізім істей алмайтынды істейді
қаңтар: 20 нүкте | бір күн: 519.9
апта күндері: ['Friday', 'Monday', 'Thursday', 'Tuesday', 'Wednesday']
== asfreq('D') тесіктерді көрсетеді
нүкте болды: 40 | оның бос: 10
day
2026-01-09 514.00
2026-01-10 NaN
2026-01-11 NaN
2026-01-12 514.45
Freq: D, Name: rate, dtype: float64
== resample: күннің орнына апта
mean min max count
day
2026-01-11 512.82 509.0 516.05 5
2026-01-18 514.31 512.4 516.95 5
2026-01-25 518.44 515.8 520.35 5
== rolling: бес күндік жылжымалы орташа
алғашқы төртеуі бос: 4
day
2026-01-05 NaN
2026-01-06 NaN
2026-01-07 NaN
2026-01-08 NaN
2026-01-09 512.82
2026-01-12 513.91
Name: rate, dtype: float64
== тегістеу немен төлейді
нағыз ауқым: 23.75
тегістелгеннің ауқымы: 12.73
максимум күні: нағызы 2026-01-26 | тегістелгені 2026-02-13
26 қаңтардағы секіріс: қатарда 532.75 | тегістелгенде 521.01
== алдыңғы күнмен салыстырғанда
day
2026-01-05 NaN
2026-01-06 4.55
2026-01-07 -2.05
Name: rate, dtype: float64
өскен күн: 14 | түскен: 15
Талдау
Күн индексі — жол болып тұрған белгілер емес
pd.DatetimeIndex — жиырма бесінші сабақтағы сол индекс, бірақ ол белгілердің уақыт екенін түсінеді. Қалғанының бәрі содан:
rate.loc["2026-01"]— бүкіл қаңтар, индексте ондай белгі болмаса да: pandas мұны кесінді деп оқиды;rate.index.day_name(),.month,.quarter— әр белгінің өз бөліктері бар;- қатардан жиілігін сұрауға, оны бір аптаға жылжытуға, тоқсандап жаюға болады.
"2026-01-05" жолдарымен мұның ешқайсысы істемейді: resample үшін олар жай ғана мәтін, әрі ол TypeError деп жауап береді. Басқа жүйеден келген файлмен бірінші істейтін нәрсе — күн бағаны үшін pd.to_datetime (жиырма алтыншы сабақ, parse_dates параметрі), содан кейін ғана set_index.
asfreq: жоқ күндер
Қатарда отыз нүкте бар, ал күнтізбелік күн қырық. Он күн — демалыс, ол күндері бақылау жоқ, әрі тізімде бұл ешқалай көрінбейді: тізім жұма мен дүйсенбінің арасында үзіліс бар екенін білмейді.
rate.asfreq("D") қатарды күнтізбе торына қайта құрады: бақылауы жоқ күндер пайда болады, әрі оларда NaN тұрады. Уақыт бойынша кез келген қатармен бірінші істейтін нәрсе осы — тесіктерді толтыру үшін емес, олардың бар екенін білу үшін. Әрі қарай шешеді: демалыс — қалыпты нәрсе, ал апта ортасында жоғалған сейсенбі — дереккөзден сұрауға себеп.
resample: күннің орнына апта
resample("W") қатарды апталарға кеседі де, әрқайсысында сұралғанды санайды. Бұл — жиырма сегізінші сабақтағы groupby, тек кілт — күнтізбелік кесінді, әрі оны өзіңіз құрудың қажеті жоқ.
Жиіліктер қысқа жазылады: D — күн, W — апта, ME — ай соңы, QE — тоқсан, YE — жыл, h — сағат. Аптаның әдепкі белгісі — оның соңғы күні (шығыстағы 2026-01-11 — бұл 5-тен 11 қаңтарға дейінгі апта). Мұны әр жолы тексерген жөн: соңғы күнмен белгіленген апталық есепті «11 қаңтардағы жағдай» деп оқып жіберу оңай, ал ол «11 қаңтарға дейінгі апта үшін» дегенді білдіреді.
Жиынтықтағы count — әшекей емес. Ол аптаға қанша нүкте түскенін көрсетеді: біреуінде бес, екіншісінде екеу болса, ол апталардың орташалары салыстыруға келмейді.
rolling: жылжымалы орташа
rate.rolling(5).mean() — соңғы бес нүкте бойынша орташа, қатармен қадамдап жүреді. Алғашқы төрт мән бос, әрі бұл дұрыс: бес нүкте әлі жиналмаған, ал үшеуімен санап, оны бес күндік орташа деп атау — өтірік. Бос басы кедергі келтірсе, min_periods=3 бар, бірақ сонда алғашқы мәндер басқа нүкте санымен есептелген болады, әрі мұны есте ұстау керек.
Әдепкі терезе артқа қарайды: 9 қаңтардағы мән — 5–9 қаңтардағы орташа. Сондықтан тегістелген қатар нағызынан қалып отырады. center=True терезені симметриялы қояды, сонда қатар қалып қоймайды, бірақ басы мен соңындағы бос мәндер екі есе көбейеді.
Тегістеу немен төлейді
Сабақ содан жазылған. Қатарда жаңалық болған бір күн бар — 26 қаңтар, бағам 14 теңгеге секірген. Онымен не болды:
| нағыз қатар | тегістелген | |
|---|---|---|
| ауқым | 23.75 | 12.73 |
| шың күні | 26 қаңтар | 13 ақпан |
| 26 қаңтардағы мән | 532.75 | 521.01 |
Тегістеу өзінен сұралғанды дәл істеді: шектен шыққанды алып тастады. Бірақ мұндағы шектен шыққан — шу емес, оқиға. Тегістелген графикте 26 қаңтар ешқалай ерекшеленбейді, ауқым нағызынан екі есе аз, ал шың екі жарым апта алға кетті — қатардың орташа алғанда жай ғана жоғары жеріне.
Бұдан сол күйінде қабылдауға тұрарлық үш ереже шығады:
- Тегістелген қатар — қорытынды, дерек емес. Оның қасында әрқашан нағызы тұруға тиіс: ең болмаса сол графиктегі бозғылт сызық.
- Ауқым, максимум және минимум тегістелген емес, нағыз қатар бойынша есептеледі. Әйтпесе есепте бағам 526-дан аспаған болып шығады, ал ол 533 болған.
- Тегістеудің параметрі — терезе ені — бар, әрі оны нәтижеге қарағанға дейін таңдайды. Әйтпесе терезе қисықтың керекті пішініне қарай іріктеледі, ал бұл — талдау емес.
Өткен кезеңмен салыстыру
diff() — алдыңғы нүктемен айырма, pct_change() — сол үлеспен, shift(1) — бір қадамға жылжытылған сол қатардың өзі. Үшеуі де көршілерді қатар қалай жатса, сол ретпен санайды, сондықтан олардың алдында қатар индекс бойынша сұрыпталады; сұрыпталмаған қатар сенімді көрінетін, бірақ ештеңе білдірмейтін сандар береді.
Бірнеше қатары бар кесте үшін — жобадағыдай, онда ел үшеу — diff топтың ішінде алынады: table.groupby("country")["value"].diff(). Топтаусыз әр келесі елдің бірінші жолы алдыңғы елдің соңғы жылын шегеріп алады.
Сабақ картасы
Өз сөзіңізбен айтыңыз
Қарамай, дауыстап немесе қағазға жауап беріңіз. Жауаптар — сабақтың соңында.
- Жетіспейтін мәндерді толтырмайтын болсаңыз,
asfreq("D")не үшін жасалады? - Бес нүкте бойынша жылжымалы орташаның алғашқы төрт мәні неге бос?
- Тек тегістелген қатар көрсетілген есеп нені жоғалтады?
Жаттығу
Тапсырмаға дейінгі үш қысқа қадам: болжау, толықтыру, түзету. Жауаптар — сабақтың соңында, бірақ алдымен өзіңіз жауап беріңіз.
1. Болжаңыз. Бұл бағдарлама не басып шығарады?
import pandas as pd
days = pd.to_datetime(["2026-01-05", "2026-01-06", "2026-01-07", "2026-01-12", "2026-01-13"])
rate = pd.Series([512.0, 514.0, 513.0, 520.0, 522.0], index=days)
print(rate.resample("W").mean().round(2))
print("апта:", len(rate.resample("W").mean()))
2. Бос орынды толтырыңыз. ... орнына терезе енін қойыңыз, сонда басындағы бос мән дәл екеу болсын.
# терезеде қанша нүкте болса, басында сонша минус бір бос мән болады
import pandas as pd
days = pd.date_range("2026-01-05", periods=6, freq="D")
rate = pd.Series([512.0, 514.0, 513.0, 520.0, 522.0, 519.0], index=days)
smooth = rate.rolling(...).mean().round(2)
print(smooth.tolist())
print("басындағы бос:", int(smooth.isna().sum()))
3. Түзетіңіз. Бағдарлама құлайды: Only valid with DatetimeIndex, TimedeltaIndex or PeriodIndex. Индексте күндер бар, бірақ олар — жол.
# индекс күн болып көрінеді, ал pandas мәтін көріп тұр
import pandas as pd
rate = pd.Series([512.0, 514.0, 520.0], index=["2026-01-05", "2026-01-06", "2026-01-12"])
print(rate.resample("W").mean().round(2).tolist())
Тапсырма
Міндетті. Сабақтағы сол қатарды алыңыз — қырық күнтізбелік күн, отыз жұмыс күні, 26 қаңтардағы секіріс. Апталық есеп (count, mean, min, max) және бес күндік жылжымалы орташа құрыңыз. Мыналарды басып шығарыңыз: қанша күнтізбелік күн бақылаусыз қалды; апталық кестені; нағыз және тегістелген қатардың ауқымын; екеуіндегі шыңның күні мен шамасын; бір күндегі ең үлкен секірісті және оның тегістелген қатарда неге айналғанын.
Күтілетін шығыс:
қатардағы күн: 30 | күнтізбелік күн: 40 | бақылаусыз: 10
апталар бойынша:
count mean min max
day
2026-01-11 5 512.82 509.00 516.05
2026-01-18 5 514.31 512.40 516.95
2026-01-25 5 518.44 515.80 520.35
2026-02-01 5 522.73 516.70 532.75
2026-02-08 5 522.74 520.10 524.65
2026-02-15 5 525.55 523.05 528.05
бес күндік жылжымалы орташа:
басындағы бос: 4
қатардың ауқымы: 23.75 | тегістелгеннің ауқымы: 12.73
қатардың шыңы: 2026-01-26 532.75 | тегістелгеннің шыңы: 2026-02-13 525.55
бір күндегі ең үлкен секіріс: 2026-01-26 + 14.45
тегістелген қатарда бұл күн: 521.01 — нағызынан кем: 11.74
Дайын болғаны: шығыс жол-жолымен сәйкес келеді; жетіспейтін күндер ұзындықтарды шегерумен емес, asfreq арқылы табылған; апталар жолдағы апта нөмірі бойынша топтаумен емес, resample-мен алынған; нағыз қатардың ауқымы мен шыңы нағыз қатар бойынша есептелген; секіріс күніндегі айырма көзбен емес, есеппен шыққан.
Өз деректеріңізде. Уақыт бойынша өз қатарыңызды алыңыз — күндік шығыс, қадам саны, салмақ, кез келгені. asfreq жасап, онда шын мәнінде қанша күн жетіспейтінін қараңыз. Содан кейін екі түрлі тереземен жылжымалы орташа құрып, есеп үшін қайсысын таңдайтыныңызды және неге таңдайтыныңызды өзіңізге адал айтыңыз.
Қалауыңыз бойынша.
rolling(5).mean()менrolling(5, center=True).mean()салыстырыңыз: қайсысында қатар қалып отырады, қайсысында екі жағынан қиылады.resample("ME")жасап, pandas айды қандай белгімен атайтынын қараңыз.pct_change()есептеп, пайызбен ең көп өскен күнді табыңыз — ол теңгемен ең көп өскен күнмен сәйкес келе ме.
Жобада бұл қайда тұрады
Он екінші қадам, әрі онда қалағаннан азырақ — адал себеппен.
Жиынтықтағы жыл сан болудан қалып, күнге айналады: pd.to_datetime(year, format="%Y"). Сан кездейсоқтықпен сұрыпталып, шегеріледі, күн — мағынасы бойынша, әрі жиынтық айлық қатарды оқитын күні осы жолдан жоғарыдағы ештеңені өзгертудің қажеті болмайды.
Есеп жылдық қатар шын мәнінде жауап бере алатын сұрақты алады: соңғы жыл өткен жылдан қаншалық өзгеше. Бұл — топтау ішіндегі diff(): бір жол әрі сұрыпталған жылдар бойынша цикл соншалық жақсы көретін бірлікке жылжу жоқ.
Ал resample пен rolling жобаға кірген жоқ, әрі бұл қадамда жазулы: бес жылдық нүкте — тегістейтін қатар емес. Бес нүктелі жылжымалы орташа артында ештеңесі жоқ сурет болар еді. Олар жиынтық жылына бір саннан тығызырақ нәрсе оқи бастағанда келеді.
Әлі қарастырылмағаны. Жиынтықтың индексі енді күн, бірақ қатардың жиілігі жарияланбаған: ол жылдық па, айлық па — бағдарлама білмейді, келгеніне қарап біледі. Дереккөз біреу болғанда бұл қалыпты.
Жауаптар
Жауаптарды көрсету
Сұрақтарға
- Жоқ нәрсені көру үшін. Тізімде жетіспейтін күн ешқалай білінбейді — қатар жай ғана күнтізбеден қысқа.
asfreq("D")ол күндердіNaN-мен орнына қояды, әрі одан кейін шешеді: демалыс — күтілетін нәрсе, ал жоғалған сейсенбі — дереккөзден не болғанын сұрауға себеп. - Өйткені бес нүкте әлі жиналмаған. Үшеуімен санап, оны бес нүктелік орташа деп атау — өтірік; мұндағы
NaN«жауап әзірге жоқ» дегенді білдіреді, әрі бұл адал жауап. - Ол оқиғаларды жоғалтады. Тегістеу шектен шыққанды алып тастайды, ал шектен шыққан — көбіне болған нәрсенің ең маңыздысы: жаңалық күні, ақау, науқан. Мысалда ауқым 23.75-тен 12.73-ке түседі, ал шың күні екі жарым апта жылжиды. Сондықтан тегістелген қатар нағызының орнына емес, қасында көрсетіледі.
Жаттығуға
resample("W")күнтізбелік апталар бойынша санайды әрі әрқайсысын соңғы күнімен — жексенбімен — белгілейді. Екі апта: 5–11 қаңтар және 12–18 қаңтар.
2026-01-11 513.0
2026-01-18 521.0
Freq: W-SUN, dtype: float64
апта: 2
rolling(3). Басындағы бос мәндер әрқашан терезедегі нүктеден бірге кем: үш нүктелі терезе екі бос мән береді.
import pandas as pd
days = pd.date_range("2026-01-05", periods=6, freq="D")
rate = pd.Series([512.0, 514.0, 513.0, 520.0, 522.0, 519.0], index=days)
smooth = rate.rolling(3).mean().round(2)
print(smooth.tolist())
print("басындағы бос:", int(smooth.isna().sum()))
[nan, nan, 513.0, 515.67, 518.33, 520.33]
басындағы бос: 2
rate.index = pd.to_datetime(rate.index). Күнге ұқсайтын жолдар pandas үшін күнге айналдырылмайынша жол болып қала береді;resampleтек уақыт индексімен істейді.
import pandas as pd
rate = pd.Series([512.0, 514.0, 520.0], index=["2026-01-05", "2026-01-06", "2026-01-12"])
rate.index = pd.to_datetime(rate.index)
print(rate.resample("W").mean().round(2).tolist())
[513.0, 520.0]
Тапсырмаға
Жетіспейтін күндер 40 − 30 шегерумен емес, asfreq("D") арқылы саналады: күнтізбенің ұзындығы бізге оны өзіміз құрғандықтан ғана белгілі, ал нағыз қатарда оны бір жерден алуға тура келер еді.
Нағыз қатардың ауқымы мен шыңы тегістеуге дейін және нағыз қатар бойынша есептеледі. Тапсырмада тексерілетін бастысы — осы: есепте тегістелген қатардың max пен min-і пайда болған бойда, есеп болмаған нәрсені айта бастайды.
Дереккөздер
- pandas-тағы уақытпен жұмыс — күн индексі, жиіліктер,
resampleжәне жылжулар. - Жылжымалы терезелер —
rolling,expanding,min_periodsжәне терезені ортаға қою. - Жиілік белгілері —
D,W,ME,QE,YEжәне қалғандары.
Пікірлер (0)
Пікір қалдыру үшін кіріңіз →
Әзірге пікір жоқ. Бірінші болыңыз.