File size: 1,926 Bytes
eed2dec
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
f817cf6
 
 
 
 
 
eed2dec
 
 
 
 
f817cf6
eed2dec
 
 
 
 
 
 
f817cf6
 
 
 
 
 
 
eed2dec
 
 
 
 
 
 
 
f817cf6
eed2dec
 
 
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
"""
Auto Visualization -- chon loai bieu do (metric / bar / line / table) dua tren
hinh dang ket qua truy van. Heuristic don gian, khong can train rieng:

  - 1 dong x 1 cot, gia tri so      -> "metric" (so lon, vd COUNT(*))
  - cot dau la nhan (text), co cot so, ten cot goi y thoi gian -> "line"
  - cot dau la nhan (text), co cot so, it dong (<=30)          -> "bar"
  - con lai (nhieu cot, nhieu dong, hoac toan text)            -> "table"
"""

import pandas as pd

_TIME_HINTS = ("year", "date", "time", "month", "day")


def make_chart_data(df: pd.DataFrame):
    """Tra ve (chart_type, chart_df). chart_type in {'metric', 'bar', 'line', 'table'}.
    chart_df da duoc set_index() phu hop de truyen truc tiep vao st.bar_chart/
    st.line_chart (voi 'table'/'metric' thi chart_df = df goc, khong dung den).

    Model SQL hay sinh aggregate truoc label (vd SELECT COUNT(*), city FROM ...
    GROUP BY city), nen label_col duoc tim trong ALL columns, khong chi cot dau.
    api.py se reorder cot truoc khi serialize neu label_col khong o vi tri 0.
    """
    if df.empty:
        return "table", df

    n_rows, n_cols = df.shape
    numeric_cols = df.select_dtypes(include="number").columns.tolist()
    text_cols = df.select_dtypes(exclude="number").columns.tolist()

    if n_rows == 1 and n_cols == 1 and numeric_cols:
        return "metric", df

    if n_cols < 2 or not numeric_cols:
        return "table", df

    # Can it nhat 1 cot text de lam label thanh truc X cua chart
    if not text_cols:
        return "table", df

    label_col = text_cols[0]
    value_cols = [c for c in df.columns if c in numeric_cols]

    if not value_cols or n_rows < 2:
        return "table", df

    chart_df = df.set_index(label_col)[value_cols]

    if any(hint in str(label_col).lower() for hint in _TIME_HINTS):
        return "line", chart_df

    if n_rows <= 30:
        return "bar", chart_df

    return "table", df