Гузариш ба мундариҷа
Мавзӯи 7 аз 7

Қиматҳои гумшуда ва санаҳо

Барои чӣ қиматҳои гумшуда ва вақтро меомӯзем

Ҳангоми ченкунӣ датчик метавонад қимат нафиристад, дар пурсишнома кас метавонад саволеро беҷавоб гузорад ва дар дафтари ҳодисаҳо санаҳо аксар вақт матни одӣ мебошанд. Пеш аз ҳисоб бояд фаҳмид, ки маҳз чӣ номаълум аст ва кадом амалҳои вақт лозиманд. Вагарна ҳарорати номаълум ба сифр табдил меёбад ё декабри солҳои гуногун ба як сатри ҳисобот меафтад.

Қимати гумшуда набудани қиматро мефаҳмонад, на худкор сифр ё сатри холиро. Сана қимати дорои маънои тақвимӣ аст, ки онро муқоиса ва ба қисмҳо ҷудо кардан мумкин аст. Ҷойҳои холиро меёбем, тарзи коркардашонро бошуурона интихоб мекунем ва санаҳои матниро ба қиматҳои муносиб барои таҳлил табдил медиҳем.

1. Қиматҳои номавҷуд чӣ гуна ифода мешаванд

Ҳангоми хондани CSV pandas бо нобаёнӣ майдонҳои холиро ҳамчун қиматҳои гумшуда мешиносад. Дар сутуни одии ададӣ онҳо аксар вақт бо NaN (Not a Number) ифода мешаванд. Аз сабаби он ададҳои бутун метавонанд ҳамчун float64 нигоҳ дошта шаванд: массиви одии бутуни NumPy ҳолати алоҳидаи «адад нест» надорад. Ин маънои тағйир ё дақиқтар шудани ченкуниро надорад.

Дар pandas шаклҳои дигари ҷойи холӣ ҳам ҳастанд: pd.NA барои навъҳои дастгирикунанда ва NaT барои санаҳо. Барои ёфтани ҳамаи онҳо бо роҳи ягона isna() ва санҷиши баръакси notna()-ро истифода баред.

import io
import pandas as pd

data = io.StringIO("device,reading,room\nA,10,X\nB,,Y\nC,20,\n")
df = pd.read_csv(data)
print(df["reading"])
print(df.isna().sum().to_dict())
print(df["reading"].notna().tolist())

Натиҷа:

0    10.0
1     NaN
2    20.0
Name: reading, dtype: float64
{'device': 0, 'reading': 1, 'room': 1}
[True, False, True]

2. Агрегатҳо чӣ кор мекунанд

Миёна бо нобаёнӣ аз рӯйи қиматҳои маълум ҳисоб мешавад. count() шумораи онҳо ва len шумораи умумии унсурҳоро медиҳад. Аз ин рӯ санҷиши шумораи мушоҳидаҳо мисли худи миёна муҳим аст. skipna=False мавҷудияти ҷойи холиро ба назар мегирад: агар ҳадди ақал як қимат номаълум бошад, миёна NaN мешавад.

Хусусияти ҷамъ: агар ягон қимати маълум набошад, sum() бо нобаёнӣ 0.0 медиҳад. Агар ин ҷавоб набудани ченкуниро пинҳон кунад, sum(min_count=1) гиред: камаш як қимати маълум талаб мешавад.

s = pd.Series([10, None, 20])
print(s.mean(), s.count(), len(s))
print(s.mean(skipna=False))
unknown = pd.Series([None, None], dtype="float64")
print(unknown.sum(), unknown.sum(min_count=1))

Натиҷа:

15.0 2 3
nan
0.0 nan

3. Хориҷ кардан ё пур кардан

dropna() дар ҷадвал сатрҳои дорои ҳар гуна ҷойи холиро хориҷ мекунад. subset санҷишро ба майдонҳои лозим маҳдуд мекунад: агар ҳуҷра барои ҳисоб муҳим набошад, номаълум будани он набояд ченкунии дурустро хориҷ кунад. Метод натиҷа медиҳад; бе бахшидан ҷадвали аслӣ тағйир намеёбад.

fillna(value) ҷойҳои холиро бо қимати додашуда пур мекунад. Чунин ивазкунӣ қарор дар бораи маънои додаҳост. Маблағи номаълум ҳатман сифр нест: пардохт шояд шуда бошад, вале андозааш номаълум аст. Пур кардан бо миёна ҳам тақсимотро тағйир медиҳад ва мушоҳидаҳои ҳақиқиро барқарор намекунад. Аввал қоида ва баъд методро интихоб кунед.

print(df.dropna()["device"].tolist())
print(df.dropna(subset=["reading"])["device"].tolist())
print(df["reading"].fillna(df["reading"].mean()).tolist())
print(df["reading"].isna().sum())

Натиҷа:

['A']
['A', 'C']
[10.0, 15.0, 20.0]
1

4. Қимати маълуми ҳамсоя

Дар қатори мураттаб ffill() охирин қимати маълумро ба пеш ва bfill() қимати маълуми баъдиро ба қафо мебарад. «Пешина» тартиби сатрҳоро мефаҳмонад, на худкор санаи пештарро. Қатори вақтӣ аввал аз рӯйи вақт мураттаб карда шавад. Ҷойҳои холии аввал баъди ffill мемонанд, зеро пеш аз онҳо ҳанӯз қимати маълум нест.

limit дарозии занҷири пуршавандаро маҳдуд мекунад. Ин вақте муфид аст, ки гузаронидани қимат танҳо ба як ҷойи холӣ иҷозат бошад, на ба танаффуси дароз. Дар пешгӯӣ пур кардан бо қимати оянда эҳтиёт мехоҳад: дар лаҳзаи пешгӯӣ он шояд ҳанӯз вуҷуд надошт.

temps = pd.Series([None, 11, None, None, 17, None])
print(temps.ffill().tolist())
print(temps.bfill().tolist())
print(temps.ffill(limit=1).tolist())

Натиҷа:

[nan, 11.0, 11.0, 11.0, 17.0, 17.0]
[11.0, 11.0, 17.0, 17.0, 17.0, nan]
[nan, 11.0, 11.0, nan, 17.0, 17.0]

5. Матн ба сана табдил меёбад

pd.to_datetime сатрҳоро ба қиматҳои тақвимӣ табдил медиҳад. format-и ошкор тартиби сол, моҳ ва рӯзро муайян мекунад. Барои додаҳои вайрон errors="coerce" санаи нодурустро ба NaT табдил медиҳад; баъд шумораи хатоҳоро бо isna санҷед, на ин ки додаҳоро хомӯшона ислоҳшуда ҳисоб кунед.

Дар Series-и санаҳо .dt ба қисмҳо дастрасӣ медиҳад: сол, моҳ, рӯз ва рӯзи ҳафта. dayofweek рӯзҳоро аз 0 барои душанбе то 6 барои якшанбе рақамгузорӣ мекунад. Дар сутуни одии сатрӣ .dt кор намекунад: аввал табдил лозим аст.

raw = pd.Series(["2026-01-05", "2026-02-31", "2027-01-10"])
dates = pd.to_datetime(raw, format="%Y-%m-%d", errors="coerce")
print(dates.isna().tolist())
known = dates.dropna()
print(known.dt.year.tolist())
print(known.dt.month.tolist())
print(known.dt.dayofweek.tolist())

Натиҷа:

[False, True, False]
[2026, 2027]
[1, 1]
[0, 6]

6. Муқоиса, фарқ ва формат

Санаҳоро бо ҳад муқоиса, мураттаб ва аз ҳам тарҳ кардан мумкин аст. Фарқ давомнокӣ медиҳад ва .days-и он шумораи рӯзҳои пурраро нишон медиҳад. .dt.strftime сатрҳои формати лозимро медиҳад. Ин шакли намоиш аст; агар ҳисобҳои тақвимӣ идома ёбанд, сутуни аслии санаҳоро нигоҳ доред.

print((known.max() - known.min()).days)
print(known[known >= "2027-01-01"].dt.strftime("%d.%m.%Y").tolist())
print(known.sort_values().dt.strftime("%Y-%m-%d").tolist())

Натиҷа:

370
['10.01.2027']
['2026-01-05', '2027-01-10']

7. Давра — як моҳи пурра ҳамчун қимат

Рақами моҳ аз .dt.month солро нигоҳ намедорад. Давра (Period) бо басомади M моҳи муайяни соли муайянро мефаҳмонад, масалан 2027-01. .dt.to_period("M") санаҳоро ба чунин қиматҳо мегузаронад. Аз рӯйи онҳо мисли ҳар калиди дигар гурӯҳбандӣ кардан мумкин аст. Барои мисол шумораи ҳодисаҳои техникиро мешуморем, на маблағи пулро.

events = pd.to_datetime(pd.Series(["2026-01-05", "2026-01-20", "2027-01-10"]))
months = events.dt.to_period("M")
print(months.astype(str).tolist())
counts = pd.DataFrame({"month": months}).groupby("month").size()
print([(str(month), int(count)) for month, count in counts.items()])

Натиҷа:

['2026-01', '2026-01', '2027-01']
[('2026-01', 2), ('2027-01', 1)]

8. Ҳамаи тамғаҳо, аз ҷумла номавҷудҳо

pd.period_range(first, last, freq="M") тақвими пайдарпайи моҳҳоро бо ҳар ду ҳад месозад. Худи groupby моҳҳои номавҷудро илова намекунад. Барои мувофиқ кардани натиҷа ба маҷмӯи лозими тамғаҳо reindex ҳаст: он таркиб ва тартиби индексро иваз мекунад. fill_value тамғаҳои навро пур мекунад, аммо ҷойҳои холии қаблан мавҷудро иваз намекунад. Дар поён воситаҳо алоҳида нишон дода шудаанд, то сохтани тақвим аз мувофиқкунӣ фарқ кунад.

calendar = pd.period_range("2026-11", "2027-02", freq="M")
print(calendar.astype(str).tolist())
levels = pd.Series([2, None], index=["A", "C"])
print(levels.reindex(["A", "B", "C"], fill_value=0).tolist())

Натиҷа:

['2026-11', '2026-12', '2027-01', '2027-02']
[2.0, 0.0, nan]

Дар дохил чӣ рӯй медиҳад

Вектори isna() ҳолати ҳар ячейкаро қайд мекунад; ҷамъи қиматҳои булӣ нишонаҳои True-ро мешуморад. Бисёр агрегатҳо танҳо унсурҳои маълумро мегиранд, бинобар ин махраҷи миёна бо шумораи мушоҳидаҳо тағйир меёбад. ffill аз рӯйи тартиб гузашта, охирин қимати маълумро дар хотир нигоҳ медорад; bfill аз қафо мегузарад.

Табдил ба сана ба матн маънои тақвимӣ медиҳад. Давра фосилаи басомади интихобшударо муайян мекунад, на танҳо тамғаи зеботарро. Ҳангоми reindex pandas барои ҳар тамғаи нав қимати пешинаро меҷӯяд ва набудани мувофиқатро алоҳида коркард мекунад.

Хатоҳои маъмул ва ислоҳи онҳо

  1. NaN-ро бо баробарӣ ҷустан. s == float("nan") ҷойҳои холиро намеёбад. s.isna() гиред; барои қиматҳои маълум s.notna() лозим аст.
  2. Пеш аз миёна ҳама чизро бо сифр пур кардан. s.fillna(0).mean() ченкунии номаълумро сифри ҳақиқӣ ҳисобида, ҷавобро дигар мекунад. Барои танҳо ченкуниҳои маълум s.mean() гиред ва s.count()-ро санҷед.
  3. .dt-ро барои сатрҳо даъват кардан. raw.dt.month хатои AttributeError медиҳад. Аввал бо pd.to_datetime(raw, ...) санаҳо гиред.
  4. Моҳҳои якхелаи солҳои гуногунро якҷо кардан. Гурӯҳбандӣ бо .dt.month январи 2026 ва январи 2027-ро омехта мекунад. Барои ҳисоботи тақвимӣ .dt.to_period("M") лозим аст.
  5. Пеш аз мураттабсозӣ қаторро пур кардан. ffill тартиби сатрҳоро риоя мекунад. Аз рӯйи вақт мураттаб кунед ва бе гурӯҳбандӣ қиматҳоро байни датчикҳои гуногун нагузаронед.

Ёддошт

  • Ёфтани ҷойҳои холӣ: isna(), notna(); шуморидан: isna().sum().
  • Мушоҳидаҳои маълум: count(); ҳамаи унсурҳо: len().
  • Хориҷ кардан: dropna(subset=[...]); пур кардан: fillna(value).
  • Ҳамсояҳо: ffill(), bfill(); маҳдудияти занҷир: limit.
  • Табдили сана: pd.to_datetime(..., format=..., errors="coerce").
  • Қисмҳо ва намоиш: .dt.year, .dt.month, .dt.dayofweek, .dt.strftime(...).
  • Моҳ бо сол: .dt.to_period("M"); тақвими пурра: pd.period_range.
  • Маҷмӯи лозими тамғаҳо: reindex(labels, fill_value=...).