File size: 4,164 Bytes
bcb314a
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# src/features_q4.py
import re
import pandas as pd

# мини-словарики (можно расширять)
PLACE_WORDS   = r"(кухн|парк|сквер|берег|река|дом|улиц|квартир|комнат|набережн)"
SEASON_WORDS  = r"(лето|зим|весн|осен|снег|жарко|холодно|листопад|сосулк)"
PEOPLE_WORDS  = r"(мама|папа|дедушк|бабушк|женщин|мужчин|ребен|дет|сем|дочка|сын|парень|девушк)"
ACTION_WORDS  = r"(игра|моет|готов|накрыва|бежит|катает|кормит|сидит|спит|несет|перепрыг|гуляет)"
DETAIL_WORDS  = r"(одет|рост|волос|глаз|характер|возраст|пальто|рубашк|кроссовк|плать|кофт|ботинк)"
PIC_INTRO     = r"(на картинке|на рисунке|я вижу|изображен)"

CHILDREN_Q    = r"(сколько детей|детям|о них|как.*играете.*дет(ями|ьми))"
FREE_TIME_Q   = r"(свободн(ое|ым)\s+врем|как.*проводите.*время|выходн(ой|ые))"

def q4_slot_features(df: pd.DataFrame) -> pd.DataFrame:
    out = df.copy()
    if "question_number" not in out.columns:
        raise ValueError("В датафрейме нет колонки 'question_number'")
    for col in ["question_text", "answer_text"]:
        if col not in out.columns:
            out[col] = ""  # на всякий случай

    mask = out["question_number"] == 4
    q = out.loc[mask, "question_text"].fillna("").astype(str)
    a = out.loc[mask, "answer_text"].fillna("").astype(str)

    expects_children = q.str.contains(CHILDREN_Q, case=False, regex=True)
    expects_free     = q.str.contains(FREE_TIME_Q, case=False, regex=True)

    has_place_time = a.str.contains(PLACE_WORDS, case=False, regex=True) | a.str.contains(SEASON_WORDS, case=False, regex=True)
    has_people     = a.str.contains(PEOPLE_WORDS, case=False, regex=True)
    has_actions    = a.str_contains(ACTION_WORDS, case=False, regex=True) if hasattr(a, "str_contains") else a.str.contains(ACTION_WORDS, case=False, regex=True)
    has_detail     = a.str.contains(DETAIL_WORDS, case=False, regex=True)

    answered_children = a.str.contains(r"(у меня.*дет(и|ей)|в моей семье.*дет|сын|дочк|мы.*играем)", case=False, regex=True)
    answered_free     = a.str.contains(r"(свободн.*врем|обычно.*(в выходн|по выходн)|люблю|занимаюсь|хожу|смотрю|рисую|спорт|танц)", case=False, regex=True)

    non_cyr_ratio = a.apply(lambda t: (len(re.findall(r"[A-Za-z]", t)) / max(1, len(t))))
    picture_first = a.str.contains(PIC_INTRO, case=False, regex=True)
    dont_know     = a.str.contains(r"(не знаю|не понимаю|трудно сказать|не могу описать)", case=False, regex=True)

    slots = (has_place_time.astype(int) + has_people.astype(int) + has_actions.astype(int) + has_detail.astype(int))
    slots_covered = (slots / 4.0).clip(0, 1)

    personal_ok = (
        (expects_children & answered_children) |
        (expects_free & answered_free) |
        (~expects_children & ~expects_free)
    )

    # создаём колонки с нулями; для Q4 — заполняем значениями
    cols = {
        "q4_slots_covered": slots_covered,
        "q4_has_place_time": has_place_time.astype(int),
        "q4_has_people":     has_people.astype(int),
        "q4_has_actions":    has_actions.astype(int),
        "q4_has_detail":     has_detail.astype(int),
        "q4_expects_children": expects_children.astype(int),
        "q4_expects_free":     expects_free.astype(int),
        "q4_answered_personal": personal_ok.astype(int),
        "q4_non_cyr_ratio":   non_cyr_ratio,
        "q4_picture_first":   picture_first.astype(int),
        "q4_dont_know":       dont_know.astype(int),
    }
    for name, series in cols.items():
        out[name] = 0
        out.loc[mask, name] = series.values

    return out