{"metadata":{"kernelspec":{"language":"python","display_name":"Python 3","name":"python3"},"language_info":{"name":"python","version":"3.10.14","mimetype":"text/x-python","codemirror_mode":{"name":"ipython","version":3},"pygments_lexer":"ipython3","nbconvert_exporter":"python","file_extension":".py"},"kaggle":{"accelerator":"none","dataSources":[{"sourceId":81933,"databundleVersionId":9643020,"sourceType":"competition"}],"dockerImageVersionId":30786,"isInternetEnabled":true,"language":"python","sourceType":"notebook","isGpuEnabled":false}},"nbformat_minor":4,"nbformat":4,"cells":[{"cell_type":"markdown","source":"# Mieu ta\n* Train: Chuyển Các cột season thành int, cập nhật các giá trị thiếu bằng KNN(3 neighhbor)\n* Actigraphy: chưa làm gì nhiều, nhưng tạm thời các field có ảnh hưởng nhiều đến total PCIAT với sii là enmo, đang tìm cách tính giá trị tương quan giữa các field của actigraphy và 2 lable này (có thể là tính mean của từng field của id và taoh thành bảng mới)","metadata":{}},{"cell_type":"code","source":"import numpy as np\nimport pandas as pd\nimport os\nimport re\nfrom sklearn.base import clone\nfrom sklearn.metrics import cohen_kappa_score\nfrom sklearn.model_selection import StratifiedKFold\nfrom scipy.optimize import minimize\nfrom sklearn.impute import KNNImputer\nfrom concurrent.futures import ThreadPoolExecutor\nfrom tqdm import tqdm\nimport polars as pl\nimport polars.selectors as cs\nimport matplotlib.pyplot as plt\nfrom matplotlib.ticker import MaxNLocator, FormatStrFormatter, PercentFormatter\nimport seaborn as sns\n","metadata":{"_uuid":"8f2839f25d086af736a60e9eeb907d3b93b6e0e5","_cell_guid":"b1076dfc-b9ad-4769-8c92-a6c4dae69d19","trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:43:58.874248Z","iopub.execute_input":"2024-12-01T14:43:58.874653Z","iopub.status.idle":"2024-12-01T14:44:02.182185Z","shell.execute_reply.started":"2024-12-01T14:43:58.874617Z","shell.execute_reply":"2024-12-01T14:44:02.181185Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Load dataset","metadata":{}},{"cell_type":"code","source":"train = pl.read_csv('/kaggle/input/child-mind-institute-problematic-internet-use/train.csv')\ntest = pl.read_csv('/kaggle/input/child-mind-institute-problematic-internet-use/test.csv')\ndata_dict = pl.read_csv('/kaggle/input/child-mind-institute-problematic-internet-use/data_dictionary.csv')\ntrain","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:44:02.184574Z","iopub.execute_input":"2024-12-01T14:44:02.185180Z","iopub.status.idle":"2024-12-01T14:44:02.386036Z","shell.execute_reply.started":"2024-12-01T14:44:02.185132Z","shell.execute_reply":"2024-12-01T14:44:02.384942Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"data_dict.head()","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:44:02.387234Z","iopub.execute_input":"2024-12-01T14:44:02.387585Z","iopub.status.idle":"2024-12-01T14:44:02.397215Z","shell.execute_reply.started":"2024-12-01T14:44:02.387553Z","shell.execute_reply":"2024-12-01T14:44:02.396125Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Statistical ","metadata":{}},{"cell_type":"code","source":"\ndef clean_check(df, column_name=None):\n    # Thông tin về DataFrame\n    print(\"\\n=== Thông tin chung về DataFrame ===\")\n    print(df.describe())\n\n    # Xem một vài dòng đầu tiên và cuối cùng\n    print(\"\\n=== 5 dòng đầu tiên ===\")\n    print(df.head())\n    print(\"\\n=== 5 dòng cuối cùng ===\")\n    print(df.tail())\n\n    # Số lượng giá trị thiếu ở mỗi cột\n    print(\"\\n=== Số lượng giá trị thiếu ở mỗi cột ===\")\n    print(df.null_count())\n\n    # Số lượng hàng trùng lặp\n    print(\"\\n=== Số lượng hàng trùng lặp ===\")\n    duplicated_count = df.filter(df.is_duplicated()).shape[0]\n    print(duplicated_count)\n\n    # Thống kê cho cột cụ thể hoặc tất cả cột kiểu str\n    valid_seasons = [\"Spring\", \"Summer\", \"Fall\", \"Winter\"]\n    \n    columns_to_check = [column_name] if column_name else df.select(pl.col(pl.Utf8)).columns\n    columns_to_check = [col for col in columns_to_check if col != \"id\"]\n    \n    for col in columns_to_check:\n     # Lọc và hiển thị các giá trị không hợp lệ trong cột kiểu str\n        if df[col].dtype == pl.Utf8:\n            invalid_values = df.filter(~df[col].is_in(valid_seasons))[col].unique()\n            if not invalid_values.is_empty():\n                print(\"\\n=== Các giá trị không hợp lệ trong cột ===\")\n                print(invalid_values)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:44:02.399322Z","iopub.execute_input":"2024-12-01T14:44:02.399675Z","iopub.status.idle":"2024-12-01T14:44:02.414741Z","shell.execute_reply.started":"2024-12-01T14:44:02.399637Z","shell.execute_reply":"2024-12-01T14:44:02.413669Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"clean_check(train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:44:02.416096Z","iopub.execute_input":"2024-12-01T14:44:02.416390Z","iopub.status.idle":"2024-12-01T14:44:02.577091Z","shell.execute_reply.started":"2024-12-01T14:44:02.416361Z","shell.execute_reply":"2024-12-01T14:44:02.576032Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"clean_check(test)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:44:02.578135Z","iopub.execute_input":"2024-12-01T14:44:02.578444Z","iopub.status.idle":"2024-12-01T14:44:02.606352Z","shell.execute_reply.started":"2024-12-01T14:44:02.578383Z","shell.execute_reply":"2024-12-01T14:44:02.605237Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"train_columns = set(train.columns)\ntest_columns = set(test.columns)\n\n# Tìm các cột có trong train nhưng không có trong test\ncolumns_in_train_not_in_test = train_columns - test_columns\n\n# Lọc data_dict để lấy các hàng có 'field' nằm trong danh sách thiếu\nmissing_fields_info = data_dict.filter(pl.col(\"Field\").is_in(columns_in_train_not_in_test))\n\nprint(sorted(columns_in_train_not_in_test))\n# In ra các hàng này\nprint(missing_fields_info)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:44:02.607814Z","iopub.execute_input":"2024-12-01T14:44:02.608172Z","iopub.status.idle":"2024-12-01T14:44:02.616811Z","shell.execute_reply.started":"2024-12-01T14:44:02.608139Z","shell.execute_reply":"2024-12-01T14:44:02.615572Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import polars as pl\nimport matplotlib.pyplot as plt\n\ndef calculate_missing_stats(data, sort_by_nan=True):\n    columns = data.columns \n\n    missing_percentages = {}  # Dictionary lưu tỷ lệ NaN\n\n    for col in columns:\n        missing_count = data[col].is_null().sum()\n        missing_percentages[col] = missing_count\n\n    # Sắp xếp các cột theo tỷ lệ NaN nếu sort_by_nan được bật\n    if sort_by_nan:\n        sorted_missing = {col: missing_percentages[col] for col in sorted(missing_percentages, key=missing_percentages.get, reverse=True)}\n\n        # Vẽ biểu đồ tỷ lệ NaN (xoay ngang)\n        plt.figure(figsize=(10, 14))\n        plt.barh(list(sorted_missing.keys()), list(sorted_missing.values()), color='skyblue')\n        plt.title('Số giá trị bị thiếu (NaN) của các cột')\n        plt.xlabel('Số lượng NaN')\n        plt.ylabel('Cột')\n        plt.xticks(rotation=0, ha='right', fontsize=10)\n        plt.show()\n\n    return missing_percentages\n\n# Sử dụng hàm (ví dụ): nếu muốn sắp xếp theo tỷ lệ NaN\ncalculate_missing_stats(train)\ncalculate_missing_stats(test)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:44:02.618169Z","iopub.execute_input":"2024-12-01T14:44:02.618534Z","iopub.status.idle":"2024-12-01T14:44:04.446994Z","shell.execute_reply.started":"2024-12-01T14:44:02.618500Z","shell.execute_reply":"2024-12-01T14:44:04.445939Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# Normalization","metadata":{}},{"cell_type":"code","source":"# Định nghĩa các cột mùa và ánh xạ\nseason_cols = [\n    'Basic_Demos-Enroll_Season', \n    'Demos-Enroll_Season',\n    'CGAS-Season', \n    'Physical-Season', \n    'FGC-Season', \n    'BIA-Season', \n    'PCIAT-Season', \n    'SDS-Season', \n    'PreInt_EduHx-Season',\n    'Fitness_Endurance-Season',\n    'PAQ_A-Season',\n    'PAQ_C-Season'\n]\n\nseason_mapping = {\n    'Spring': 0,\n    'Summer': 1,\n    'Fall': 2,\n    'Winter': 3\n}\n\n# Thay thế các giá trị trong các cột mùa và chuyển kiểu dữ liệu sang int\nfor col in season_cols:\n    if col in train.columns:\n        train = train.with_columns(\n            pl.col(col)\n            .replace(season_mapping)  # Thay thế giá trị theo ánh xạ\n            .cast(pl.Int32)  # Chuyển kiểu dữ liệu sang int\n            .alias(col)  # Giữ lại tên cột\n        )\n\n# In kết quả để kiểm tra\nprint(train)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:44:04.448399Z","iopub.execute_input":"2024-12-01T14:44:04.448855Z","iopub.status.idle":"2024-12-01T14:44:04.494907Z","shell.execute_reply.started":"2024-12-01T14:44:04.448808Z","shell.execute_reply":"2024-12-01T14:44:04.493613Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# threshold = 0.5 * len(train)\n\n# # Kiểm tra số lượng giá trị thiếu cho mỗi cột\n# null_counts = train.null_count()\n\n# # Lọc các cột có số lượng giá trị thiếu nhỏ hơn threshold\n# columns_with = [col for col, count in zip(null_counts.columns, null_counts.to_numpy()[0]) if count < threshold]\n\n# # Lọc lại DataFrame chỉ với các cột có ít hơn 50% giá trị thiếu\n# train = train.select(columns_with)\ntrain_no_id = train.drop(\"id\")\ncolumns_without_id = train_no_id.columns\n\n# Chuyển DataFrame Polars sang Pandas\ntrain_pandas = train_no_id.to_pandas()\n\n# Khởi tạo KNNImputer từ scikit-learn với k=3 (3 láng giềng gần nhất)\nimputer = KNNImputer(n_neighbors=3)\n\n# Áp dụng KNNImputer để thay thế giá trị thiếu\ntrain_imputed = imputer.fit_transform(train_pandas)\n\n# Chuyển lại DataFrame Pandas về Polars mà không cần chỉ định columns\ntrain_imputed_polars = pl.DataFrame(train_imputed, schema=columns_without_id)\n\n# In kết quả để kiểm tra\nprint(train_imputed_polars)\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:45:37.524266Z","iopub.execute_input":"2024-12-01T14:45:37.525086Z","iopub.status.idle":"2024-12-01T14:45:45.994872Z","shell.execute_reply.started":"2024-12-01T14:45:37.525043Z","shell.execute_reply":"2024-12-01T14:45:45.993704Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"# ACTIGRAPHY","metadata":{}},{"cell_type":"code","source":"actigraphy = pl.read_parquet('/kaggle/input/child-mind-institute-problematic-internet-use/series_train.parquet/id=0417c91e/part-0.parquet')\nactigraphy","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:48:56.744645Z","iopub.execute_input":"2024-12-01T14:48:56.745613Z","iopub.status.idle":"2024-12-01T14:48:56.839007Z","shell.execute_reply.started":"2024-12-01T14:48:56.745552Z","shell.execute_reply":"2024-12-01T14:48:56.837991Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"* step: Bước thời gian (timestep) là một giá trị nguyên cho mỗi quan sát trong chuỗi dữ liệu.\n* X, Y, Z: Đo gia tốc, tính bằng g, mà đồng hồ đeo tay cảm nhận được theo mỗi trục chuẩn.\n* enmo: Như được tính toán và mô tả bởi gói wristpy, ENMO là Chuẩn Euclid Trừ Một của tất cả các tín hiệu cảm biến gia tốc (dọc theo mỗi trục x, y và z, đo bằng lực g) với các giá trị âm được làm tròn về không. Các giá trị bằng không chỉ ra các khoảng thời gian không có chuyển động. Mặc dù không có tiêu chuẩn đo gia tốc trong không gian này, nhưng đây là một trong những đặc trưng thường được tính toán.\n* anglez: Như được tính toán và mô tả bởi gói wristpy, Angle-Z là một chỉ số được lấy từ các thành phần gia tốc riêng lẻ và đề cập đến góc của cánh tay so với mặt phẳng ngang.\n* non_wear_flag: Cờ (0: đồng hồ đang được đeo, 1: đồng hồ không được đeo) giúp xác định các khoảng thời gian khi đồng hồ bị tháo ra, dựa trên định nghĩa GGIR, sử dụng độ lệch chuẩn và phạm vi của dữ liệu gia tốc.\n* Light: Đo mức độ ánh sáng môi trường tính bằng lux. Xem thêm chi tiết tại đây.\n* battery_voltage: Đo điện áp của pin tính bằng mV.\n* time_of_day: Thời gian trong ngày đại diện cho bắt đầu của cửa sổ 5s mà dữ liệu đã được lấy mẫu, với định dạng %H:%M:%S.%9f.\n* weekday: Ngày trong tuần, được mã hóa dưới dạng một số nguyên với 1 là Thứ Hai và 7 là Chủ Nhật.\n* quarter: Quý trong năm, một số nguyên từ 1 đến 4.\n* relative_date_PCIAT: Số ngày (số nguyên) kể từ khi bài kiểm tra PCIAT được thực hiện (các ngày âm chỉ ra rằng dữ liệu actigraphy đã được thu thập trước khi bài kiểm tra được thực hiện).\r\n","metadata":{}},{"cell_type":"code","source":"def analyze_actigraphy(id, only_one_week=False, small=False):\n    actigraphy = pl.read_parquet(f'/kaggle/input/child-mind-institute-problematic-internet-use/series_train.parquet/id={id}/part-0.parquet')\n    day = actigraphy.get_column('relative_date_PCIAT') + actigraphy.get_column('time_of_day') / 86400e9\n    sample = train.filter(pl.col('id') == id)\n    age = sample.get_column('Basic_Demos-Age').item()\n    sex = ['boy', 'girl'][sample.get_column('Basic_Demos-Sex').item()]\n    actigraphy = (\n        actigraphy\n        .with_columns(\n            (day.diff() * 86400).alias('diff_seconds'),\n            (np.sqrt(np.square(pl.col('X')) + np.square(pl.col('Y')) + np.square(pl.col('Z'))).alias('norm'))\n        )\n    )\n\n    if only_one_week:\n        start = np.ceil(day.min())\n        mask = (start <= day.to_numpy()) & (day.to_numpy() <= start + 7*3)\n        mask &= ~ actigraphy.get_column('non-wear_flag').cast(bool).to_numpy()\n    else:\n        mask = np.full(len(day), True)\n        \n    if small:\n        timelines = [\n            ('enmo', 'forestgreen'),\n            ('light', 'orange'),\n        ]\n    else:\n        timelines = [\n            ('X', 'm'),\n            ('Y', 'm'),\n            ('Z', 'm'),\n#             ('norm', 'c'),\n            ('enmo', 'forestgreen'),\n            ('anglez', 'lightblue'),\n            ('light', 'orange'),\n            ('non-wear_flag', 'chocolate')\n    #         ('diff_seconds', 'k'),\n        ]\n        \n    _, axs = plt.subplots(len(timelines), 1, sharex=True, figsize=(12, len(timelines) * 1.1 + 0.5))\n    for ax, (feature, color) in zip(axs, timelines):\n        ax.set_facecolor('#eeeeee')\n        ax.scatter(day.to_numpy()[mask],\n                   actigraphy.get_column(feature).to_numpy()[mask],\n                   color=color, label=feature, s=1)\n        ax.legend(loc='upper left', facecolor='#eeeeee')\n        if feature == 'diff_seconds':\n            ax.set_ylim(-0.5, 20.5)\n    axs[-1].set_xlabel('day')\n    axs[-1].xaxis.set_major_locator(MaxNLocator(integer=True))\n    plt.tight_layout()\n    axs[0].set_title(f'id={id}, {sex}, age={age}')\n    plt.show()\n\nanalyze_actigraphy('0417c91e', only_one_week=False)","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T14:52:18.041459Z","iopub.execute_input":"2024-12-01T14:52:18.042494Z","iopub.status.idle":"2024-12-01T14:52:20.489647Z","shell.execute_reply.started":"2024-12-01T14:52:18.042444Z","shell.execute_reply":"2024-12-01T14:52:20.488604Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"# Hàm tính toán giá trị trung bình của các trường trong mỗi file parquet\ndef calculate_mean_for_parquet(id):\n    # Đọc parquet từ đường dẫn\n    parquet_path = f'/kaggle/input/child-mind-institute-problematic-internet-use/series_train.parquet/id={id}/part-0.parquet'\n    \n    # Kiểm tra nếu file parquet tồn tại\n    if os.path.exists(parquet_path):\n        actigraphy = pl.read_parquet(parquet_path)\n\n        # Tính ngày từ relative_date_PCIAT và time_of_day\n        day = actigraphy.get_column('relative_date_PCIAT') + actigraphy.get_column('time_of_day') / 86400e9\n        \n        # Tính giá trị trung bình cho các cột yêu cầu\n        means = actigraphy.select([\n            pl.col('step').median().alias('mean_step'),\n            pl.col('X').median().alias('mean_X'),\n            pl.col('Y').median().alias('mean_Y'),\n            pl.col('Z').median().alias('mean_Z'),\n            pl.col('enmo').median().alias('mean_enmo'),\n            pl.col('anglez').median().alias('mean_anglez'),\n            pl.col('non-wear_flag').median().alias('mean_non_wear_flag'),\n            pl.col('light').median().alias('mean_light'),\n            pl.col('battery_voltage').median().alias('mean_battery_voltage'),\n            pl.col('time_of_day').median().alias('mean_time_of_day'),\n            pl.col('weekday').median().alias('mean_weekday'),\n            pl.col('quarter').median().alias('mean_quarter'),\n            pl.col('relative_date_PCIAT').median().alias('mean_relative_date_PCIAT')\n        ])\n\n        # Thêm cột 'id' vào kết quả để dễ dàng nhận diện\n        means = means.with_columns(pl.lit(id).alias('id'))\n        \n        return means\n# Lấy danh sách các id từ cột 'id' trong DataFrame train\nids = train.select('id').to_pandas()['id'].tolist()\n\n# Tính toán giá trị trung bình cho mỗi id và gộp kết quả vào một DataFrame\nall_means = []\n\nfor id in ids:\n    result = calculate_mean_for_parquet(id)\n    if result is not None:\n        all_means.append(result)\n\n# Gộp các kết quả lại thành một DataFrame duy nhất\nif all_means:\n    all_means_df = pl.concat(all_means)\n    print(all_means_df)\nelse:\n    print(\"Không có dữ liệu hợp lệ để gộp.\")","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T15:17:30.533814Z","iopub.execute_input":"2024-12-01T15:17:30.534696Z","iopub.status.idle":"2024-12-01T15:18:05.142119Z","shell.execute_reply.started":"2024-12-01T15:17:30.534650Z","shell.execute_reply":"2024-12-01T15:18:05.140963Z"}},"outputs":[],"execution_count":null},{"cell_type":"code","source":"import polars as pl\nimport pandas as pd\nimport seaborn as sns\nimport matplotlib.pyplot as plt\n\ndef add_sii_and_PCIAT(all_means_df, train):\n    # Kiểm tra nếu cả hai DataFrame đều có dữ liệu\n    if all_means_df.is_empty() or train.is_empty():\n        print(\"Một trong hai DataFrame (all_means_df hoặc train) là rỗng.\")\n        return None\n\n    # Lọc các hàng trong 'train' có 'id' giống với 'id' trong all_means_df\n    all_means_df = all_means_df.join(train.select(['id', 'sii', 'PCIAT-PCIAT_Total']), on='id', how='left')\n\n    # Kiểm tra xem các cột 'sii' và 'PCIAT-PCIAT_Total' đã được thêm vào chưa\n    if 'sii' not in all_means_df.columns or 'PCIAT-PCIAT_Total' not in all_means_df.columns:\n        print(\"Không thể thêm cột 'sii' và 'PCIAT-PCIAT_Total' vào DataFrame.\")\n        return None\n\n    return all_means_df\n\ndef check_correlation(all_means_df):\n    # Kiểm tra kiểu dữ liệu của các cột\n    print(\"Kiểu dữ liệu của các cột:\")\n    print(all_means_df.dtypes)\n\n    # Loại bỏ các cột không phải số (ví dụ: 'id')\n    numeric_columns = [\n        col for col in all_means_df.columns if all_means_df[col].dtype in [\n            pl.Float32, pl.Float64, pl.Int32, pl.Int64\n        ]\n    ]\n    all_means_df_numeric = all_means_df.select(numeric_columns)\n\n    # Kiểm tra nếu có ít nhất một cột số\n    if all_means_df_numeric.is_empty():\n        print(\"Không có cột số để tính toán độ tương quan.\")\n        return None\n\n    # Chuyển all_means_df sang Pandas để tính toán tương quan\n    all_means_pandas = all_means_df_numeric.to_pandas()\n\n    # Tính toán ma trận tương quan cho tất cả các cột trong all_means_df\n    corr_matrix = all_means_pandas.corr()\n\n    # In ra ma trận tương quan\n    print(corr_matrix)\n\n    return corr_matrix\n\ndef plot_heatmap(corr_matrix):\n    # Kiểm tra nếu ma trận tương quan không rỗng\n    if corr_matrix is not None and not corr_matrix.empty:\n        # Vẽ heatmap với seaborn\n        plt.figure(figsize=(10, 8))  # Điều chỉnh kích thước đồ thị\n        sns.heatmap(corr_matrix, annot=True, cmap='coolwarm', fmt='.2f', vmin=-1, vmax=1)\n        plt.title('Ma trận tương quan')\n        plt.show()\n    else:\n        print(\"Ma trận tương quan rỗng, không thể vẽ heatmap.\")\n\n# Giả sử all_means_df đã có dữ liệu\nif all_means:\n    all_means_df = pl.concat(all_means)\n    \n    # Kiểm tra nếu all_means_df có dữ liệu hợp lệ\n    if all_means_df.is_empty():\n        print(\"all_means_df là rỗng sau khi gộp.\")\n    else:\n        # Lấy DataFrame 'train' (giả sử là một DataFrame đã được tải)\n        # Lọc và gộp cột 'sii' và 'PCIAT-PCIAT_Total' vào all_means_df\n        all_means_with_sii_PCIAT = add_sii_and_PCIAT(all_means_df, train)\n        \n        # Kiểm tra nếu all_means_with_sii_PCIAT không rỗng\n        if not all_means_with_sii_PCIAT.is_empty():\n            corr_matrix = check_correlation(all_means_with_sii_PCIAT)  # Lấy ma trận tương quan\n            plot_heatmap(corr_matrix)  # Vẽ heatmap\n        else:\n            print(\"Không có dữ liệu hợp lệ sau khi gộp.\")\nelse:\n    print(\"Không có dữ liệu hợp lệ để kiểm tra độ tương quan.\")\n","metadata":{"trusted":true,"execution":{"iopub.status.busy":"2024-12-01T15:18:05.144631Z","iopub.execute_input":"2024-12-01T15:18:05.145114Z","iopub.status.idle":"2024-12-01T15:18:06.022212Z","shell.execute_reply.started":"2024-12-01T15:18:05.145060Z","shell.execute_reply":"2024-12-01T15:18:06.021020Z"}},"outputs":[],"execution_count":null},{"cell_type":"markdown","source":"Hmm, trông nó không liên quan lắm :vv Có thể là không phải tính mean","metadata":{}}]}