From d3861e30a9b6e14716f69c11f080be36b1c75ff8 Mon Sep 17 00:00:00 2001 From: wuzekai <3025054974@qq.com> Date: Fri, 26 Sep 2025 16:56:19 +0800 Subject: [PATCH] Initial commit --- Dockerfile | 25 +- data/cancer.csv | 930 ++++++++++++++ data/cancer.xlsx | Bin 0 -> 28041 bytes radiant-master/DESCRIPTION | 3 +- radiant-master/inst/app/global.R | 1 - .../inst/translations/translation_zh.csv | 75 +- radiant.quickgen/DESCRIPTION | 18 + radiant.quickgen/NAMESPACE | 40 + radiant.quickgen/R/quickgen_ai.R | 101 +- radiant.quickgen/R/quickgen_basic.R | 66 +- radiant.quickgen/inst/app/init.R | 2 +- .../inst/app/tools/analysis/quickgen_ai_ui.R | 296 ++++- .../app/tools/analysis/quickgen_basic_ui .txt | 1115 ----------------- .../app/tools/analysis/quickgen_basic_ui.R | 276 ++-- .../inst/app/tools/help/quickgen_ai.md | 27 + set_path.R | 1 - 16 files changed, 1608 insertions(+), 1368 deletions(-) create mode 100644 data/cancer.csv create mode 100644 data/cancer.xlsx create mode 100644 radiant.quickgen/NAMESPACE delete mode 100644 radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui .txt diff --git a/Dockerfile b/Dockerfile index 148b87c..2e3fac8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -6,21 +6,26 @@ RUN apt-get update && apt-get install -y \ libpng-dev libtiff5-dev libjpeg-dev \ && rm -rf /var/lib/apt/lists/* - -RUN R -e "install.packages(c('shiny', 'shinydashboard', 'remotes'), repos='https://cran.rstudio.com/')" +RUN R -e "install.packages(c('shiny', 'shinydashboard', 'remotes','readxl'), repos='https://cran.rstudio.com/',dependencies=TRUE)" +RUN echo 'options(radiant.shinyFiles = FALSE)' >> /usr/local/lib/R/etc/Rprofile.site COPY . /srv/shiny-server/ COPY set_path.R /usr/local/lib/R/etc/Rprofile.site.d/00-radiant-path.R # 安装所有子模块 -RUN R -e "remotes::install_local('/srv/shiny-server/radiant.data', type='source', upgrade='never')" -RUN R -e "remotes::install_local('/srv/shiny-server/radiant.basics', type='source', upgrade='never')" -RUN R -e "remotes::install_local('/srv/shiny-server/radiant.model', type='source', upgrade='never')" -RUN R -e "remotes::install_local('/srv/shiny-server/radiant.multivariate', type='source', upgrade='never')" -RUN R -e "remotes::install_local('/srv/shiny-server/radiant.design', type='source', upgrade='never')" -RUN R -e "remotes::install_local('/srv/shiny-server/radiant.quickgen', type='source', upgrade='never')" +RUN R -e "remotes::install_local('/srv/shiny-server/radiant.data',dependencies=TRUE, type='source', upgrade='never')" +RUN R -e "remotes::install_local('/srv/shiny-server/radiant.basics',dependencies=TRUE, type='source', upgrade='never')" +RUN R -e "remotes::install_local('/srv/shiny-server/radiant.model',dependencies=TRUE, type='source', upgrade='never')" +RUN R -e "remotes::install_local('/srv/shiny-server/radiant.multivariate',dependencies=TRUE, type='source', upgrade='never')" +RUN R -e "remotes::install_local('/srv/shiny-server/radiant.design',dependencies=TRUE, type='source', upgrade='never')" +RUN R -e "remotes::install_local('/srv/shiny-server/radiant.quickgen',dependencies=TRUE, type='source', upgrade='never')" # 安装主 radiant 应用 -RUN R -e "remotes::install_local('/srv/shiny-server/radiant-master', type='source', upgrade='never')" +RUN R -e "remotes::install_local('/srv/shiny-server/radiant-master',dependencies=TRUE, type='source', upgrade='never')" WORKDIR /data -CMD ["R", "-e", "radiant::radiant(host='0.0.0.0', port=3838)"] \ No newline at end of file +CMD ["R", "-e", "radiant::radiant(host='0.0.0.0', port=3838)"] + +#docker images | grep radiant 查看镜像 +#sudo systemctl restart shinyproxy 重启proxy +#sudo vim /etc/shinyproxy/application.yml 修改配置文件 +#docker build -t radiant:latest . 构建镜像 \ No newline at end of file diff --git a/data/cancer.csv b/data/cancer.csv new file mode 100644 index 0000000..4effa94 --- /dev/null +++ b/data/cancer.csv @@ -0,0 +1,930 @@ +ID,Hospital,Treatment,Age,Sex,Blood test,Obstruct,Perfor,Adhere,Differ,Extent,Effect,Occurrence,OS_status,OS_time,Objective Response +1,hospital_5,Lev,43,Male,3829,NA,No,No,Moderate,Serosa,Bad,5,1,1521,Yes +2,hospital_3,Lev,63,Male,3825,No,No,No,Moderate,Serosa,Good,1,0,3087,No +3,hospital_5,Obs,71,Female,3809,No,No,Yes,Moderate,Muscle,Bad,7,1,963,Yes +4,hospital_4,Lev,66,Female,3808,Yes,No,No,Moderate,Serosa,Bad,6,1,293,Yes +5,hospital_5,Obs,69,Male,3738,No,No,No,Moderate,Serosa,Bad,22,1,659,Yes +6,hospital_4,Lev,57,Female,3714,No,No,No,Moderate,Serosa,Bad,9,1,1767,Yes +7,hospital_2,Lev,77,Male,3692,No,No,No,Moderate,Serosa,Bad,5,1,420,Yes +8,hospital_2,Obs,54,Male,3685,No,No,No,Moderate,Serosa,Good,1,0,3192,No +9,hospital_2,Lev,46,Male,3673,No,No,Yes,Moderate,Serosa,Good,2,0,3173,Yes +10,hospital_2,Lev,68,Female,3587,No,No,No,Moderate,Serosa,Bad,1,0,3308,Yes +11,hospital_1,Lev,47,Female,3585,No,No,Yes,Moderate,Serosa,Bad,1,0,2908,No +12,hospital_1,Lev,52,Male,3578,No,No,No,Poor,Serosa,Bad,2,0,3309,Yes +13,hospital_3,Obs,64,Male,3530,No,No,No,Moderate,Serosa,Good,1,1,2085,Yes +14,hospital_4,Lev,68,Male,3524,Yes,No,No,Moderate,Serosa,Good,3,1,2910,Yes +15,hospital_1,Obs,46,Male,3519,Yes,No,No,Moderate,Serosa,Good,4,0,2754,Yes +16,hospital_1,Obs,68,Male,3517,No,No,No,Moderate,Serosa,Good,1,0,3214,Yes +17,hospital_4,Lev,62,Male,3500,Yes,No,Yes,Moderate,Serosa,Bad,6,1,406,Yes +18,hospital_5,Lev,79,Male,3485,Yes,No,No,Moderate,Serosa,Bad,1,1,522,Yes +19,hospital_1,Lev,34,Female,3469,Yes,No,No,Moderate,Muscle,Bad,1,1,887,No +20,hospital_1,Lev,50,Female,3469,No,No,Yes,Moderate,Serosa,Good,1,0,3329,No +21,hospital_2,Obs,64,Male,3458,NA,No,No,Moderate,Serosa,Good,1,1,2789,Yes +22,hospital_4,Lev,56,Male,3451,Yes,No,No,Moderate,Serosa,Bad,4,1,739,Yes +23,hospital_3,Lev,61,Female,3450,No,No,No,Moderate,Serosa,Bad,4,1,709,No +24,hospital_1,Lev,50,Female,3441,No,No,No,Moderate,Muscle,Good,1,0,2969,Yes +25,hospital_1,Lev,70,Female,3427,No,No,No,Moderate,Serosa,Good,4,0,2889,Yes +26,hospital_5,Obs,73,Male,3425,No,No,No,Moderate,Serosa,Bad,1,1,1772,No +27,hospital_5,Obs,70,Female,3418,No,No,Yes,Moderate,Serosa,Bad,13,1,384,Yes +28,hospital_5,Lev,68,Female,3416,No,No,No,Moderate,Serosa,Bad,1,1,968,Yes +29,hospital_4,Obs,56,Female,3415,Yes,No,No,Poor,Serosa,Bad,6,1,218,Yes +30,hospital_5,Lev,80,Male,3413,No,No,No,Poor,Serosa,Bad,1,1,133,No +31,hospital_2,Lev,64,Female,3410,No,No,No,Moderate,Submucosa,Good,1,0,3238,Yes +32,hospital_3,Lev,33,Female,3408,Yes,No,No,Moderate,Serosa,Good,3,0,3019,Yes +33,hospital_2,Obs,49,Female,3405,No,No,No,Moderate,Serosa,Bad,2,1,1745,No +34,hospital_5,Obs,47,Male,3401,No,No,No,Moderate,Serosa,Good,3,1,2527,Yes +35,hospital_4,Lev,56,Female,3399,No,No,No,Moderate,Serosa,Bad,1,1,1387,Yes +36,hospital_4,Lev,72,Female,3399,No,No,Yes,Poor,Serosa,Good,1,0,3024,Yes +37,hospital_5,Obs,79,Male,3389,No,No,No,Moderate,Serosa,Bad,19,1,570,Yes +38,hospital_2,Obs,64,Female,3383,No,No,No,Poor,Serosa,Good,1,0,2815,Yes +39,hospital_1,Lev,61,Male,3371,No,No,No,Poor,Serosa,Good,2,0,2901,Yes +40,hospital_2,Lev,58,Male,3369,No,No,No,Moderate,Serosa,Bad,7,1,553,No +41,hospital_3,Lev,75,Male,3362,No,No,No,Moderate,Serosa,Bad,2,1,905,Yes +42,hospital_3,Obs,39,Female,3349,Yes,No,No,Well,Serosa,Good,1,0,3030,Yes +43,hospital_3,Obs,71,Male,3342,Yes,No,No,Moderate,Muscle,Bad,3,1,685,Yes +44,hospital_2,Lev,58,Female,3340,Yes,No,No,Moderate,Serosa,Good,2,0,2740,Yes +45,hospital_3,Lev,40,Male,3335,No,No,No,Well,Serosa,Good,1,0,2899,No +46,hospital_1,Obs,63,Female,3328,No,Yes,No,Moderate,Serosa,Good,2,0,2598,No +47,hospital_1,Lev,59,Female,3326,No,No,No,Poor,Submucosa,Good,1,0,2840,Yes +48,hospital_1,Lev,59,Female,3321,Yes,No,No,Well,Serosa,Good,2,0,2802,Yes +49,hospital_4,Lev,59,Male,3320,No,No,No,Moderate,Serosa,Good,6,0,2781,Yes +50,hospital_3,Lev,60,Male,3315,No,No,No,Poor,Serosa,Bad,5,1,833,Yes +51,hospital_4,Obs,68,Female,3315,No,No,No,Moderate,Serosa,Bad,2,1,1290,No +52,hospital_3,Lev,70,Female,3302,No,No,No,Moderate,Serosa,Bad,3,1,1620,Yes +53,hospital_1,Obs,76,Male,3300,No,No,No,Moderate,Serosa,Good,2,0,2765,Yes +54,hospital_4,Lev,45,Female,3294,No,No,No,Moderate,Serosa,Bad,3,0,2708,Yes +55,hospital_3,Lev,61,Male,3289,No,No,No,Moderate,Muscle,Bad,2,0,2737,Yes +56,hospital_4,Obs,76,Male,3289,No,No,No,Well,Serosa,Bad,3,1,1178,No +57,hospital_3,Lev,53,Male,3281,No,No,No,Moderate,Serosa,Good,2,0,2765,Yes +58,hospital_1,Lev,63,Female,3279,No,No,No,Moderate,Serosa,Good,5,0,2883,Yes +59,hospital_2,Obs,65,Female,3275,No,No,No,Poor,Serosa,Good,6,0,2679,Yes +60,hospital_3,Obs,57,Female,3272,Yes,No,No,Poor,Serosa,Good,4,0,2925,No +61,hospital_4,Lev,80,Male,3265,No,Yes,No,Moderate,Serosa,Bad,4,1,472,Yes +62,hospital_1,Lev,58,Male,3265,No,No,No,Well,Muscle,Good,1,0,2772,Yes +63,hospital_5,Obs,53,Female,3265,No,No,No,Poor,Serosa,Bad,15,1,474,No +64,hospital_3,Lev,53,Female,3264,Yes,No,No,NA,Serosa,Good,1,0,2739,Yes +65,hospital_4,Obs,71,Female,3261,No,No,No,Well,Serosa,Bad,1,1,365,Yes +66,hospital_1,Lev,66,Female,3261,No,No,No,Moderate,Serosa,Good,2,0,2653,Yes +67,hospital_4,Lev,49,Male,3260,No,No,No,Poor,Serosa,Good,6,0,2726,No +68,hospital_5,Obs,60,Male,3254,No,No,No,Moderate,Serosa,Bad,10,1,774,Yes +69,hospital_3,Obs,70,Female,3254,No,No,No,Moderate,Submucosa,Good,3,0,3078,Yes +70,hospital_4,Obs,40,Female,3247,No,No,No,Moderate,Serosa,Good,2,1,2133,No +71,hospital_2,Lev,55,Female,3247,No,No,No,Moderate,Serosa,Good,1,1,2127,No +72,hospital_4,Lev,56,Female,3243,No,No,No,Moderate,Serosa,Bad,15,1,400,Yes +73,hospital_5,Lev,54,Male,3240,No,No,No,Moderate,Serosa,Good,9,0,3185,Yes +74,hospital_5,Obs,49,Female,3239,Yes,No,No,Poor,Serosa,Bad,5,1,1237,Yes +75,hospital_5,Lev,71,Female,3237,No,No,No,Moderate,Serosa,Bad,7,1,1219,No +76,hospital_4,Obs,67,Female,3232,No,No,No,Moderate,Serosa,Good,4,0,3017,Yes +77,hospital_2,Lev,68,Female,3231,No,No,No,Moderate,Serosa,Bad,5,1,806,Yes +78,hospital_1,Lev,63,Male,3230,No,No,No,Moderate,Serosa,Good,2,0,2985,Yes +79,hospital_2,Lev,50,Male,3230,Yes,No,Yes,Moderate,Serosa,Good,1,0,2969,Yes +80,hospital_5,Lev,45,Female,3226,No,No,No,Moderate,Muscle,Good,7,1,1995,Yes +81,hospital_3,Lev,66,Male,3226,No,No,No,Moderate,Muscle,Good,1,0,2958,Yes +82,hospital_4,Obs,46,Female,3225,No,No,No,Poor,Serosa,Bad,1,1,1133,No +83,hospital_5,Lev,70,Male,3224,No,No,No,NA,Muscle,Bad,3,1,1548,Yes +84,hospital_1,Lev,63,Male,3223,Yes,No,No,Moderate,Muscle,Good,2,0,3085,Yes +85,hospital_4,Lev,45,Male,3223,No,No,No,Poor,Serosa,Bad,8,1,736,No +86,hospital_1,Lev,49,Female,3220,No,No,No,Moderate,Serosa,Good,1,0,2789,Yes +87,hospital_2,Lev,62,Female,3218,No,No,No,Moderate,Muscle,Good,2,0,3325,Yes +88,hospital_4,Obs,59,Male,3216,No,No,No,Moderate,Serosa,Bad,4,1,381,No +89,hospital_1,Lev,80,Female,3213,NA,No,No,Well,Serosa,Good,4,0,2724,Yes +90,hospital_3,Lev,73,Male,3211,Yes,No,No,NA,Serosa,Bad,4,1,997,Yes +91,hospital_5,Obs,46,Male,3209,No,No,No,Moderate,Serosa,Bad,11,1,413,Yes +92,hospital_2,Lev,64,Male,3208,No,No,No,Moderate,Serosa,Bad,4,1,708,Yes +93,hospital_3,Lev,45,Male,3206,No,No,No,Moderate,Serosa,Good,9,0,2765,No +94,hospital_3,Lev,26,Female,3203,No,No,Yes,Moderate,Adjacent structures,Bad,NA,0,2869,No +95,hospital_1,Lev,66,Male,3199,NA,No,No,Moderate,Serosa,Bad,1,0,2918,Yes +96,hospital_3,Lev,67,Male,3197,No,No,Yes,Moderate,Adjacent structures,Bad,2,1,2458,Yes +97,hospital_5,Obs,65,Female,3195,No,No,No,Moderate,Adjacent structures,Bad,20,1,459,Yes +98,hospital_2,Lev,74,Male,3191,No,No,Yes,Moderate,Serosa,Good,1,1,2318,Yes +99,hospital_2,Lev,71,Male,3190,No,No,Yes,Moderate,Adjacent structures,Bad,NA,1,569,Yes +100,hospital_5,Obs,58,Female,3188,No,No,Yes,Moderate,Muscle,Good,8,1,2077,Yes +101,hospital_5,Obs,59,Male,3183,No,No,No,Moderate,Serosa,Bad,6,1,1216,Yes +102,hospital_5,Lev,61,Male,3182,NA,No,No,Poor,Serosa,Bad,5,1,171,Yes +103,hospital_4,Lev,49,Male,3179,No,No,No,Moderate,Serosa,Bad,2,1,712,Yes +104,hospital_5,Lev,50,Female,3179,No,No,No,Moderate,Serosa,Bad,6,1,614,No +105,hospital_1,Obs,75,Female,3178,No,No,No,Moderate,Serosa,Good,1,0,2849,No +106,hospital_3,Obs,68,Male,3176,No,No,No,Poor,Serosa,Bad,3,1,1530,Yes +107,hospital_4,Lev,60,Female,3174,No,No,Yes,Moderate,Serosa,Bad,10,1,402,Yes +108,hospital_5,Lev,65,Female,3172,No,No,Yes,Moderate,Serosa,Bad,2,1,1511,Yes +109,hospital_4,Lev,74,Female,3168,No,No,No,Moderate,Serosa,Good,5,0,2828,No +110,hospital_2,Lev,52,Female,3163,No,No,No,Poor,Serosa,Bad,3,1,23,Yes +111,hospital_1,Lev,64,Male,3156,No,No,Yes,Moderate,Serosa,Good,6,0,2941,Yes +112,hospital_3,Lev,47,Male,3156,No,No,Yes,Moderate,Serosa,Bad,1,1,755,Yes +113,hospital_1,Obs,45,Female,3153,No,No,No,Moderate,Submucosa,Good,1,0,2815,Yes +114,hospital_5,Obs,61,Male,3151,Yes,No,Yes,Poor,Serosa,Bad,5,1,761,Yes +115,hospital_2,Lev,53,Male,3148,No,No,No,Poor,Serosa,Good,2,1,1839,No +116,hospital_4,Obs,60,Male,3131,Yes,No,No,Moderate,Serosa,Good,5,1,2351,Yes +117,hospital_1,Lev,60,Female,3130,No,No,No,Moderate,Serosa,Good,1,0,2760,Yes +118,hospital_1,Lev,51,Female,3128,No,No,No,Moderate,Serosa,Good,5,0,2951,No +119,hospital_1,Lev,60,Female,3128,No,No,Yes,Moderate,Serosa,Good,1,0,2820,No +120,hospital_5,Obs,64,Female,3121,No,No,No,Moderate,Serosa,Bad,1,1,1327,Yes +121,hospital_2,Lev,52,Female,3118,No,No,No,Moderate,Serosa,Good,1,0,2678,Yes +122,hospital_3,Lev,65,Female,3118,No,No,No,Poor,Serosa,Bad,2,1,226,No +123,hospital_3,Lev,70,Female,3113,No,No,No,Moderate,Serosa,Good,1,0,2913,Yes +124,hospital_2,Obs,55,Male,3100,No,No,No,Moderate,Serosa,Good,2,0,2862,Yes +125,hospital_5,Lev,71,Male,3098,No,No,No,Poor,Serosa,Bad,5,1,454,Yes +126,hospital_3,Obs,30,Male,3093,No,No,No,Moderate,Muscle,Good,1,0,2743,Yes +127,hospital_2,Obs,40,Female,3092,No,No,No,Moderate,Serosa,Bad,3,1,1679,No +128,hospital_5,Obs,31,Male,3092,Yes,No,No,Poor,Serosa,Bad,11,1,924,No +129,hospital_3,Obs,53,Male,3090,No,No,No,Moderate,Muscle,Bad,1,1,721,No +130,hospital_4,Obs,67,Male,3088,No,No,No,Moderate,Serosa,Bad,1,1,709,No +131,hospital_3,Lev,58,Female,3080,No,No,No,Moderate,Serosa,Bad,1,1,961,No +132,hospital_4,Lev,79,Female,3077,Yes,No,No,Poor,Serosa,Bad,2,1,326,Yes +133,hospital_4,Lev,55,Female,3077,No,No,No,Poor,Muscle,Good,1,0,2703,Yes +134,hospital_3,Obs,63,Female,3074,No,No,Yes,Moderate,Serosa,Bad,2,1,289,Yes +135,hospital_3,Lev,55,Male,3072,Yes,No,No,Moderate,Serosa,Good,2,0,2905,No +136,hospital_5,Lev,42,Male,3068,Yes,No,No,Moderate,Serosa,Bad,5,1,206,No +137,hospital_2,Obs,56,Male,3065,No,No,No,Moderate,Serosa,Good,1,0,2618,Yes +138,hospital_3,Lev,64,Female,3062,No,No,No,Moderate,Serosa,Bad,8,1,283,No +139,hospital_2,Lev,55,Male,3058,Yes,No,No,Moderate,Serosa,Good,2,1,2718,Yes +140,hospital_1,Obs,25,Female,3058,Yes,No,No,Moderate,Serosa,Good,7,0,2826,Yes +141,hospital_4,Lev,59,Male,3055,No,No,No,Moderate,Serosa,Good,1,0,2916,Yes +142,hospital_5,Lev,28,Male,3052,No,No,No,Poor,Serosa,Bad,9,1,499,No +143,hospital_2,Lev,49,Female,3051,No,No,No,Well,Serosa,Good,NA,0,2950,Yes +144,hospital_4,Obs,52,Female,3048,No,No,No,Moderate,Submucosa,Good,1,0,2899,Yes +145,hospital_2,Obs,64,Female,3047,No,No,No,Poor,Serosa,Bad,5,1,673,Yes +146,hospital_1,Obs,33,Female,3045,Yes,No,Yes,Well,Serosa,Good,1,0,3000,No +147,hospital_4,Obs,76,Male,3044,No,No,No,Moderate,Serosa,Good,1,1,2284,No +148,hospital_5,Lev,38,Male,3042,No,No,No,Well,Serosa,Bad,2,1,362,Yes +149,hospital_2,Lev,53,Female,3041,Yes,Yes,No,Moderate,Serosa,Good,1,1,2152,Yes +150,hospital_1,Obs,72,Female,3040,Yes,No,No,Moderate,Serosa,Good,2,0,2562,Yes +151,hospital_1,Lev,46,Male,3038,No,No,No,Moderate,Serosa,Good,1,0,2730,Yes +152,hospital_5,Lev,69,Female,3032,No,No,No,Moderate,Serosa,Bad,13,1,802,Yes +153,hospital_5,Obs,43,Male,3030,Yes,No,No,Poor,Serosa,Bad,0,1,1166,Yes +154,hospital_4,Lev,72,Male,3030,Yes,No,Yes,Moderate,Serosa,Bad,2,1,1193,No +155,hospital_4,Lev,73,Male,3028,Yes,No,No,Moderate,Serosa,Bad,2,1,45,Yes +156,hospital_1,Obs,68,Male,3027,No,No,No,Moderate,Serosa,Good,3,0,2577,Yes +157,hospital_5,Obs,52,Female,3027,No,Yes,No,Well,Serosa,Bad,6,1,1136,No +158,hospital_2,Lev,73,Female,3027,Yes,No,No,Moderate,Serosa,Good,2,0,2497,Yes +159,hospital_3,Lev,66,Male,3025,Yes,No,No,Moderate,Serosa,Good,1,0,2648,Yes +160,hospital_1,Obs,75,Female,3020,No,No,No,Poor,Serosa,Good,2,0,2458,No +161,hospital_5,Lev,43,Male,3020,Yes,No,No,NA,Serosa,Bad,6,1,1135,Yes +162,hospital_5,Lev,57,Female,3017,No,No,No,Moderate,Serosa,Bad,1,1,580,Yes +163,hospital_4,Obs,74,Male,3017,Yes,No,No,Moderate,Serosa,Bad,6,1,485,Yes +164,hospital_1,Lev,67,Female,3017,No,No,No,Moderate,Serosa,Good,1,0,2656,Yes +165,hospital_4,Lev,66,Female,3013,No,No,Yes,Moderate,Serosa,Bad,2,1,806,Yes +166,hospital_4,Obs,57,Male,3013,Yes,No,No,Moderate,Serosa,Good,3,0,2435,Yes +167,hospital_2,Lev,81,Female,3009,No,No,No,Moderate,Serosa,Bad,3,1,1439,Yes +168,hospital_3,Obs,50,Male,3007,No,No,No,Poor,Serosa,Bad,4,1,717,Yes +169,hospital_4,Lev,62,Male,3006,Yes,Yes,No,Moderate,Serosa,Good,2,0,2568,Yes +170,hospital_1,Lev,48,Female,3006,No,No,No,Well,Serosa,Good,4,0,2631,Yes +171,hospital_3,Lev,45,Male,3005,No,No,No,Moderate,Muscle,NA,2,0,1474,No +172,hospital_4,Lev,46,Male,3003,No,No,Yes,Moderate,Serosa,Good,2,1,2593,Yes +173,hospital_3,Lev,72,Female,3001,No,No,No,Moderate,Serosa,Bad,2,1,1550,Yes +174,hospital_2,Obs,55,Female,2997,No,No,No,Moderate,Serosa,Bad,4,1,670,Yes +175,hospital_4,Lev,67,Male,2997,Yes,No,No,Moderate,Serosa,Bad,1,1,430,Yes +176,hospital_3,Lev,41,Female,2996,No,No,No,Moderate,Serosa,Good,2,0,2821,Yes +177,hospital_4,Lev,56,Male,2995,No,No,No,Moderate,Submucosa,Good,2,0,2672,Yes +178,hospital_2,Lev,50,Male,2990,No,No,No,Moderate,Submucosa,Good,4,0,2699,No +179,hospital_1,Lev,65,Female,2988,No,No,No,Well,Muscle,Good,1,0,2927,Yes +180,hospital_2,Lev,74,Male,2988,No,No,Yes,Moderate,Serosa,Bad,1,1,993,No +181,hospital_4,Obs,74,Female,2987,No,No,No,Moderate,Serosa,Good,2,0,2580,No +182,hospital_4,Obs,58,Female,2987,No,No,No,Moderate,Serosa,Good,4,0,2621,Yes +183,hospital_1,Lev,56,Female,2986,No,No,No,Poor,Serosa,Good,4,0,2779,Yes +184,hospital_2,Obs,75,Female,2985,No,No,No,Moderate,Muscle,Good,1,0,2794,No +185,hospital_1,Lev,67,Male,2984,No,No,No,Moderate,Serosa,Good,4,0,2656,Yes +186,hospital_2,Lev,58,Female,2982,No,No,No,Well,Serosa,Good,6,0,2513,No +187,hospital_1,Lev,58,Female,2981,No,No,No,Moderate,Serosa,Good,2,0,2488,No +188,hospital_5,Lev,41,Male,2974,No,No,No,Poor,Serosa,Bad,33,1,1112,Yes +189,hospital_1,Lev,72,Male,2972,No,No,No,Moderate,Serosa,Good,NA,0,2618,No +190,hospital_4,Lev,48,Male,2972,No,No,Yes,NA,Serosa,Bad,2,1,795,Yes +191,hospital_5,Lev,69,Female,2972,No,No,No,Moderate,Serosa,Bad,1,1,363,Yes +192,hospital_5,Obs,57,Male,2967,Yes,No,Yes,Moderate,Serosa,Bad,1,1,949,No +193,hospital_1,Lev,45,Female,2961,Yes,No,Yes,Moderate,Serosa,Bad,1,1,127,Yes +194,hospital_2,Lev,76,Female,2960,No,No,No,Moderate,Serosa,Good,4,0,2871,No +195,hospital_3,Obs,59,Male,2958,No,No,Yes,Moderate,Serosa,Good,2,0,2558,No +196,hospital_2,Obs,66,Female,2958,No,No,No,Moderate,Serosa,Good,1,1,2083,No +197,hospital_2,Obs,65,Female,2956,No,No,No,Poor,Muscle,Good,1,0,2747,Yes +198,hospital_4,Lev,69,Male,2950,No,No,No,Well,Serosa,Bad,1,1,1105,Yes +199,hospital_4,Lev,32,Female,2949,No,No,No,Poor,Serosa,Bad,NA,1,490,No +200,hospital_2,Obs,56,Female,2949,No,No,No,NA,Muscle,Good,1,0,2507,Yes +201,hospital_2,Lev,71,Male,2947,No,No,No,Well,Serosa,Bad,1,1,961,Yes +202,hospital_5,Lev,75,Male,2945,No,No,No,NA,Serosa,Good,8,1,1879,Yes +203,hospital_1,Lev,58,Male,2944,No,No,No,Poor,Serosa,Good,7,0,2592,Yes +204,hospital_4,Obs,40,Female,2942,No,No,No,Moderate,Serosa,Good,4,1,2552,Yes +205,hospital_4,Lev,39,Female,2941,No,No,No,Well,Submucosa,Good,2,0,2474,No +206,hospital_1,Lev,42,Female,2939,No,No,No,Moderate,Serosa,Good,4,0,2349,No +207,hospital_3,Lev,53,Female,2935,No,No,No,Well,Submucosa,Good,4,0,2835,Yes +208,hospital_2,Obs,43,Male,2929,No,No,No,Moderate,Serosa,Good,2,0,2761,Yes +209,hospital_3,Obs,51,Female,2923,No,No,No,Moderate,Serosa,Bad,4,1,411,Yes +210,hospital_1,Lev,77,Male,2923,No,No,No,Well,Serosa,Good,2,0,2720,Yes +211,hospital_2,Lev,67,Male,2922,Yes,No,No,Moderate,Serosa,Good,1,0,2495,Yes +212,hospital_3,Obs,41,Male,2916,No,No,No,Moderate,Serosa,Bad,7,1,462,No +213,hospital_1,Lev,63,Male,2914,Yes,Yes,Yes,Poor,Adjacent structures,Good,2,0,2497,Yes +214,hospital_1,Lev,63,Male,2913,No,No,Yes,Moderate,Muscle,Good,3,0,2343,Yes +215,hospital_4,Lev,63,Female,2910,No,No,No,Moderate,Serosa,Good,6,0,2630,Yes +216,hospital_4,Lev,58,Female,2908,Yes,No,No,Moderate,Serosa,Good,8,0,2461,Yes +217,hospital_3,Lev,67,Female,2896,No,No,No,Moderate,Adjacent structures,Good,4,0,2747,No +218,hospital_5,Lev,55,Male,2894,Yes,No,No,Moderate,Serosa,Good,7,1,2482,Yes +219,hospital_2,Lev,63,Male,2893,Yes,No,No,Poor,Serosa,Bad,5,1,580,Yes +220,hospital_4,Lev,77,Male,2893,No,No,Yes,Moderate,Serosa,Bad,1,1,1215,Yes +221,hospital_2,Lev,43,Male,2891,Yes,Yes,Yes,Poor,Serosa,Good,4,0,2525,Yes +222,hospital_1,Lev,78,Female,2891,No,No,No,Moderate,Muscle,Good,2,0,2842,Yes +223,hospital_5,Obs,51,Female,2887,No,No,Yes,Moderate,Serosa,Bad,5,1,1272,Yes +224,hospital_2,Obs,67,Male,2886,Yes,No,No,Moderate,Serosa,Bad,1,1,438,No +225,hospital_2,Lev,66,Male,2886,No,No,No,Moderate,Serosa,Good,1,0,2423,Yes +226,hospital_4,Obs,64,Female,2885,No,No,Yes,Moderate,Adjacent structures,Bad,1,1,599,Yes +227,hospital_2,Obs,75,Female,2884,Yes,No,Yes,Moderate,Serosa,Good,1,0,2706,Yes +228,hospital_5,Lev,53,Male,2881,No,No,No,Moderate,Serosa,Good,1,1,2683,Yes +229,hospital_3,Lev,48,Male,2880,Yes,Yes,No,Moderate,Serosa,Good,2,0,2723,Yes +230,hospital_3,Obs,59,Female,2878,No,No,Yes,Moderate,Adjacent structures,Bad,1,1,1230,No +231,hospital_3,Obs,60,Female,2875,No,No,No,Moderate,Serosa,Good,1,0,2731,Yes +232,hospital_2,Obs,42,Male,2865,No,No,No,Moderate,Serosa,Good,2,0,2313,Yes +233,hospital_3,Lev,60,Male,2864,No,No,No,Moderate,Muscle,Good,1,0,2484,No +234,hospital_1,Lev,58,Male,2862,NA,No,No,Well,Serosa,Good,1,0,2754,Yes +235,hospital_3,Lev,59,Male,2860,NA,No,No,Moderate,Muscle,Good,2,1,2725,Yes +236,hospital_5,Obs,70,Female,2856,No,No,No,Moderate,Serosa,Bad,2,1,1295,Yes +237,hospital_1,Lev,75,Female,2855,No,No,No,Moderate,Serosa,Good,3,0,2506,Yes +238,hospital_3,Lev,73,Female,2853,No,No,No,Moderate,Serosa,Good,3,0,2713,Yes +239,hospital_4,Obs,76,Male,2852,No,No,No,Moderate,Serosa,Good,1,0,2695,Yes +240,hospital_5,Lev,68,Female,2852,No,No,No,Moderate,Serosa,Bad,3,1,1276,Yes +241,hospital_3,Lev,61,Male,2851,No,No,No,Moderate,Adjacent structures,Good,2,0,2600,No +242,hospital_2,Lev,76,Male,2850,NA,No,No,Moderate,Muscle,Good,1,0,2352,No +243,hospital_1,Lev,56,Female,2850,No,Yes,Yes,Moderate,Serosa,Good,3,0,2775,Yes +244,hospital_2,Lev,55,Female,2849,Yes,No,No,NA,Serosa,Good,2,0,2442,Yes +245,hospital_3,Obs,60,Female,2847,Yes,No,Yes,Poor,Serosa,Bad,4,1,437,No +246,hospital_3,Lev,72,Male,2845,No,No,No,Moderate,Serosa,Bad,9,1,1709,Yes +247,hospital_3,Lev,74,Female,2843,Yes,No,No,Moderate,Serosa,Bad,11,1,1607,Yes +248,hospital_3,Lev,62,Female,2839,No,No,No,Moderate,Serosa,Bad,3,1,1637,No +249,hospital_4,Lev,76,Female,2832,No,No,No,Well,Serosa,Bad,1,1,1117,Yes +250,hospital_2,Lev,72,Male,2832,No,No,No,Moderate,Serosa,Good,2,0,2732,Yes +251,hospital_4,Lev,57,Male,2831,No,No,No,Poor,Serosa,Bad,2,1,222,Yes +252,hospital_3,Obs,39,Female,2831,No,No,No,Moderate,Adjacent structures,Good,1,0,2688,No +253,hospital_3,Lev,61,Male,2831,No,No,No,Moderate,Serosa,Good,1,0,2520,Yes +254,hospital_5,Obs,62,Female,2830,No,No,No,Poor,Serosa,Bad,5,1,595,Yes +255,hospital_4,Lev,70,Male,2826,No,No,No,Moderate,Serosa,Bad,2,1,343,No +256,hospital_4,Obs,70,Female,2825,No,No,No,Moderate,Serosa,Bad,5,1,874,Yes +257,hospital_5,Lev,57,Female,2824,Yes,No,No,Moderate,Serosa,Bad,8,1,232,Yes +258,hospital_3,Lev,65,Male,2823,No,No,No,Moderate,Muscle,Good,3,0,2558,Yes +259,hospital_3,Lev,65,Female,2821,No,No,No,Moderate,Serosa,Good,1,0,2711,Yes +260,hospital_5,Obs,71,Female,2818,No,No,No,Moderate,Serosa,Bad,15,1,113,Yes +261,hospital_5,Lev,70,Female,2816,Yes,No,No,Moderate,Serosa,Bad,3,1,643,Yes +262,hospital_2,Obs,36,Female,2813,No,No,No,Moderate,Serosa,Good,1,0,2413,No +263,hospital_1,Lev,48,Male,2813,No,No,No,Moderate,Submucosa,Good,2,0,2509,Yes +264,hospital_1,Lev,53,Male,2812,No,No,No,Well,Serosa,Good,1,0,2356,Yes +265,hospital_5,Lev,54,Male,2810,No,No,No,Moderate,Serosa,Bad,3,1,1279,Yes +266,hospital_3,Lev,58,Male,2809,No,No,No,Well,Serosa,Bad,3,1,938,Yes +267,hospital_3,Obs,67,Male,2804,No,No,No,Moderate,Serosa,Good,3,0,2761,No +268,hospital_3,Lev,59,Male,2803,Yes,No,No,Moderate,Serosa,Good,2,0,2386,No +269,hospital_2,Obs,67,Female,2800,No,No,Yes,Moderate,Serosa,Bad,4,1,433,Yes +270,hospital_2,Lev,60,Female,2799,Yes,No,No,Poor,Serosa,Good,1,0,2445,Yes +271,hospital_1,Lev,70,Female,2799,No,No,No,Moderate,Muscle,Good,1,0,2280,Yes +272,hospital_3,Obs,76,Male,3194,No,No,No,Well,Serosa,Bad,3,1,311,Yes +273,hospital_4,Lev,60,Male,3192,Yes,No,No,Well,Serosa,Bad,1,1,977,No +274,hospital_5,Obs,67,Female,3190,Yes,No,No,Well,Serosa,Bad,12,1,833,Yes +275,hospital_4,Lev,53,Male,3189,No,No,No,Moderate,Serosa,Bad,3,1,582,Yes +276,hospital_4,Lev,76,Female,3187,No,No,No,Well,Serosa,Good,1,0,2541,Yes +277,hospital_4,Obs,74,Male,3184,No,No,No,Moderate,Serosa,Bad,2,1,238,Yes +278,hospital_2,Obs,56,Female,3184,Yes,No,No,Moderate,Adjacent structures,Good,6,1,2257,No +279,hospital_4,Lev,65,Female,3180,No,No,No,Moderate,Muscle,Good,1,0,2501,Yes +280,hospital_2,Lev,63,Male,3179,No,No,No,Moderate,Serosa,Bad,2,1,1798,Yes +281,hospital_2,Obs,56,Male,3178,No,No,No,Moderate,Serosa,Bad,2,1,883,Yes +282,hospital_3,Lev,70,Female,3178,No,No,Yes,Poor,Serosa,Good,4,0,2548,No +283,hospital_3,Lev,48,Female,3177,No,No,No,Moderate,Serosa,Good,9,0,2527,Yes +284,hospital_2,Lev,45,Male,3174,Yes,No,No,Moderate,Serosa,Good,2,0,2263,Yes +285,hospital_4,Lev,68,Female,3170,No,No,No,Moderate,Serosa,Bad,8,1,706,No +286,hospital_1,Lev,57,Female,3169,No,No,No,Moderate,Muscle,Good,1,0,2588,Yes +287,hospital_5,Lev,70,Male,3167,No,No,No,Moderate,Muscle,Good,1,1,2542,Yes +288,hospital_1,Lev,39,Male,3165,No,No,No,Moderate,Serosa,NA,1,0,1279,Yes +289,hospital_1,Obs,46,Male,3164,No,No,Yes,Poor,Adjacent structures,Bad,1,1,1304,No +290,hospital_2,Obs,77,Female,3163,Yes,No,No,Moderate,Serosa,Good,4,0,2324,Yes +291,hospital_1,Lev,59,Male,3163,NA,No,No,Well,Serosa,Good,1,0,2488,Yes +292,hospital_4,Lev,58,Female,3161,No,No,No,Moderate,Serosa,Good,1,0,2628,No +293,hospital_2,Obs,56,Male,3157,No,No,No,Moderate,Serosa,Good,8,0,2800,No +294,hospital_1,Lev,68,Male,3157,No,No,No,NA,Serosa,Good,2,0,2456,Yes +295,hospital_2,Obs,57,Female,3155,No,Yes,Yes,Moderate,Serosa,Good,1,0,2503,Yes +296,hospital_4,Lev,44,Female,3154,No,No,No,Moderate,Serosa,Bad,3,1,1446,Yes +297,hospital_5,Lev,56,Male,3152,No,No,Yes,Moderate,Serosa,Bad,3,1,641,No +298,hospital_5,Obs,67,Male,3150,No,No,No,Moderate,Serosa,Bad,4,1,1788,Yes +299,hospital_3,Lev,62,Male,3150,No,No,No,Moderate,Muscle,Good,6,0,2304,Yes +300,hospital_3,Lev,68,Female,3145,No,No,No,Moderate,Serosa,Bad,7,1,944,Yes +301,hospital_3,Lev,61,Male,3144,No,No,No,Moderate,Muscle,Good,2,0,2679,Yes +302,hospital_3,Lev,44,Female,3142,Yes,No,No,Moderate,Serosa,Bad,5,1,559,Yes +303,hospital_2,Lev,52,Female,3140,No,No,No,Moderate,Serosa,Good,7,0,2663,Yes +304,hospital_3,Lev,51,Male,3137,Yes,No,No,Poor,Serosa,Bad,1,1,647,No +305,hospital_1,Obs,59,Female,3135,No,No,No,Moderate,Serosa,Good,9,0,2697,Yes +306,hospital_3,Lev,61,Male,3134,No,No,No,Poor,Serosa,Good,1,0,2538,Yes +307,hospital_2,Obs,57,Female,3132,No,No,No,Poor,Serosa,Good,2,0,2219,No +308,hospital_3,Lev,65,Male,3131,No,No,No,Moderate,Serosa,Good,1,0,2487,Yes +309,hospital_4,Lev,73,Female,3131,Yes,No,No,Moderate,Serosa,Good,1,0,2709,Yes +310,hospital_5,Obs,69,Female,3129,No,No,No,Poor,Serosa,Bad,6,1,840,No +311,hospital_1,Lev,63,Male,3129,No,No,No,Moderate,Serosa,Good,1,0,2267,Yes +312,hospital_3,Lev,75,Male,3127,No,No,No,Moderate,Muscle,Good,2,0,2444,Yes +313,hospital_2,Lev,64,Female,3127,No,No,No,Well,Serosa,Good,5,0,2393,Yes +314,hospital_1,Obs,56,Female,3122,No,No,No,Well,Submucosa,Good,1,0,2237,Yes +315,hospital_2,Lev,69,Male,3121,No,No,No,Moderate,Serosa,Good,2,0,2915,No +316,hospital_2,Lev,64,Female,3119,No,No,No,Moderate,Serosa,Good,2,0,2467,No +317,hospital_2,Lev,74,Female,3119,Yes,No,No,Moderate,Serosa,Bad,2,1,1092,Yes +318,hospital_3,Lev,72,Male,3113,No,No,No,Moderate,Muscle,Good,4,0,2726,Yes +319,hospital_4,Lev,58,Male,3113,Yes,No,No,Moderate,Serosa,Good,9,0,2764,Yes +320,hospital_3,Lev,74,Female,3112,No,No,Yes,Poor,Adjacent structures,Good,15,0,2592,Yes +321,hospital_1,Obs,61,Female,3112,No,No,No,Well,Muscle,Good,2,0,2730,Yes +322,hospital_1,Obs,74,Female,3110,NA,No,No,Moderate,Muscle,Good,1,1,2287,Yes +323,hospital_3,Lev,64,Male,3110,No,No,No,Moderate,Serosa,Good,5,0,2117,Yes +324,hospital_5,Lev,71,Female,3109,No,No,No,Moderate,Serosa,Bad,20,1,1668,Yes +325,hospital_1,Obs,66,Female,3107,No,No,Yes,NA,Adjacent structures,Bad,1,1,528,Yes +326,hospital_1,Obs,53,Female,3104,Yes,No,No,Well,Serosa,Good,2,0,2651,No +327,hospital_1,Lev,76,Female,3104,Yes,No,No,Moderate,Serosa,Good,1,0,2676,No +328,hospital_5,Lev,75,Female,3103,Yes,No,Yes,Moderate,Muscle,Good,3,1,1885,Yes +329,hospital_4,Lev,64,Male,3102,No,No,No,NA,Serosa,Good,3,0,2350,Yes +330,hospital_5,Lev,65,Male,3100,No,No,No,Moderate,Serosa,Bad,8,1,475,Yes +331,hospital_3,Obs,57,Female,3100,No,No,No,Moderate,Serosa,Bad,5,1,1246,No +332,hospital_3,Lev,65,Male,3098,No,No,Yes,Poor,Serosa,Good,1,0,2204,Yes +333,hospital_1,Obs,53,Male,3098,No,No,No,Moderate,Adjacent structures,Good,2,0,2716,Yes +334,hospital_2,Lev,74,Male,3097,No,No,No,Moderate,Serosa,Bad,4,1,797,Yes +335,hospital_2,Lev,74,Male,3095,No,No,No,Moderate,Serosa,Good,1,0,2527,Yes +336,hospital_4,Lev,74,Female,3094,No,No,Yes,Poor,Serosa,Good,1,1,2021,Yes +337,hospital_3,Lev,48,Female,3092,No,No,No,Moderate,Serosa,Bad,6,1,498,No +338,hospital_3,Lev,58,Male,3091,No,No,No,Poor,Serosa,Bad,NA,1,885,Yes +339,hospital_4,Lev,74,Female,3091,No,No,No,Moderate,Serosa,Bad,3,1,802,Yes +340,hospital_1,Lev,71,Female,3091,No,No,No,Moderate,Serosa,Good,1,0,2674,No +341,hospital_2,Obs,54,Female,3091,No,No,No,Moderate,Serosa,Bad,2,1,743,No +342,hospital_4,Lev,80,Male,3090,No,No,No,Moderate,Muscle,Good,4,0,2517,Yes +343,hospital_5,Lev,70,Male,3090,No,No,Yes,Moderate,Serosa,Bad,8,1,349,Yes +344,hospital_3,Lev,70,Male,3089,Yes,No,No,Moderate,Serosa,Good,1,0,2723,No +345,hospital_2,Obs,70,Male,3089,NA,No,No,Poor,Serosa,Bad,1,1,775,Yes +346,hospital_2,Obs,71,Male,3088,No,No,No,Moderate,Serosa,Good,4,0,2326,Yes +347,hospital_4,Obs,59,Male,3087,No,No,No,Moderate,Serosa,Bad,2,1,1134,Yes +348,hospital_3,Lev,47,Male,3087,No,No,No,NA,Serosa,Bad,2,1,602,Yes +349,hospital_1,Lev,63,Male,3086,No,No,No,Poor,Serosa,Good,2,0,2547,No +350,hospital_3,Lev,69,Female,3085,No,No,No,Moderate,Serosa,Bad,7,1,940,No +351,hospital_1,Lev,73,Female,3084,No,No,No,Moderate,Serosa,Good,1,0,2496,No +352,hospital_1,Obs,67,Male,3083,No,No,No,Moderate,Serosa,Good,1,0,2628,No +353,hospital_1,Lev,55,Female,3083,No,No,No,Moderate,Serosa,Good,1,0,2353,No +354,hospital_2,Obs,45,Male,3081,No,No,No,Moderate,Serosa,Good,2,0,2184,Yes +355,hospital_3,Lev,78,Female,3080,Yes,No,No,Moderate,Serosa,Good,3,0,2219,Yes +356,hospital_2,Lev,80,Male,3079,No,No,No,Moderate,Serosa,Bad,3,1,191,Yes +357,hospital_3,Obs,55,Male,3076,No,No,No,Moderate,Serosa,Bad,8,1,421,No +358,hospital_2,Lev,64,Female,3076,Yes,No,No,Moderate,Serosa,Good,NA,0,2362,No +359,hospital_5,Lev,60,Female,3074,No,Yes,No,Moderate,Serosa,Bad,10,1,952,Yes +360,hospital_5,Lev,74,Female,3074,No,No,No,Moderate,Serosa,Bad,5,1,911,No +361,hospital_5,Lev,61,Female,3073,No,No,No,Moderate,Serosa,Good,1,1,1851,Yes +362,hospital_1,Obs,64,Male,3071,No,No,No,Moderate,Muscle,Good,4,0,2423,Yes +363,hospital_4,Obs,48,Female,3071,No,No,Yes,Poor,Serosa,Bad,1,1,464,Yes +364,hospital_5,Lev,76,Male,3070,No,No,No,Moderate,Serosa,Bad,2,1,443,No +365,hospital_3,Lev,76,Female,3070,No,No,No,Poor,Serosa,Bad,NA,1,186,Yes +366,hospital_1,Lev,50,Female,3070,No,No,No,Moderate,Serosa,Good,4,0,2545,Yes +367,hospital_5,Lev,56,Male,3069,No,No,No,Moderate,Adjacent structures,Bad,3,1,356,Yes +368,hospital_4,Lev,42,Female,3067,No,No,No,Poor,Serosa,Bad,10,1,484,No +369,hospital_2,Lev,72,Female,3067,No,No,No,Moderate,Serosa,Bad,1,1,382,No +370,hospital_5,Obs,68,Female,3065,No,No,Yes,Moderate,Serosa,Bad,9,1,1021,Yes +371,hospital_2,Lev,49,Male,3064,No,No,No,Moderate,Muscle,Good,1,0,2472,Yes +372,hospital_5,Lev,64,Male,3064,No,No,No,Moderate,Serosa,Good,12,0,2352,Yes +373,hospital_2,Obs,70,Female,3062,NA,No,No,Well,Muscle,Good,1,0,2486,Yes +374,hospital_2,Lev,50,Male,3062,No,No,Yes,Moderate,Adjacent structures,Bad,2,1,324,Yes +375,hospital_1,Obs,74,Male,3061,No,No,Yes,Poor,Serosa,Good,3,0,2517,Yes +376,hospital_4,Lev,37,Female,3058,No,No,No,Moderate,Serosa,Good,1,0,2613,No +377,hospital_2,Lev,75,Female,3057,NA,No,No,Poor,Serosa,Good,1,0,2450,Yes +378,hospital_5,Obs,56,Female,3056,No,No,No,Poor,Serosa,Bad,2,1,770,Yes +379,hospital_2,Lev,74,Male,3054,No,No,No,Well,Serosa,Good,3,0,2490,No +380,hospital_5,Obs,63,Male,3053,No,No,No,Moderate,Serosa,Bad,2,1,1548,Yes +381,hospital_3,Lev,56,Male,3052,No,No,No,Moderate,Muscle,Good,2,0,2449,Yes +382,hospital_5,Lev,42,Male,3052,No,No,No,Moderate,Serosa,Good,13,0,2299,No +383,hospital_2,Lev,63,Male,3049,No,No,No,Moderate,Serosa,Bad,NA,1,1252,Yes +384,hospital_2,Lev,62,Female,3048,No,No,No,Moderate,Serosa,Bad,2,1,730,Yes +385,hospital_1,Lev,33,Female,3047,No,No,No,Moderate,Serosa,Good,2,0,2460,Yes +386,hospital_5,Obs,50,Female,3047,No,No,No,Moderate,Serosa,Bad,8,1,499,Yes +387,hospital_5,Lev,73,Male,3044,No,No,No,Poor,Serosa,Bad,6,1,129,Yes +388,hospital_5,Lev,61,Female,3042,No,No,No,Poor,Serosa,Bad,9,1,52,Yes +389,hospital_3,Obs,70,Male,3039,Yes,Yes,No,Moderate,Serosa,Good,1,1,2171,Yes +390,hospital_3,Lev,38,Female,3038,No,No,No,Moderate,Serosa,Bad,3,1,1178,Yes +391,hospital_4,Obs,64,Female,3038,Yes,No,No,Moderate,Serosa,Good,3,1,1915,Yes +392,hospital_1,Lev,39,Female,3038,No,No,No,Moderate,Serosa,Good,2,0,2572,Yes +393,hospital_1,Lev,47,Female,3036,No,No,No,Moderate,Serosa,Good,1,0,2590,No +394,hospital_4,Obs,76,Male,3033,No,No,Yes,Poor,Serosa,Bad,13,1,215,Yes +395,hospital_2,Obs,65,Male,3032,No,No,No,Moderate,Serosa,Good,2,0,2325,Yes +396,hospital_3,Lev,43,Female,3030,Yes,No,No,Moderate,Serosa,Bad,4,1,961,Yes +397,hospital_3,Lev,72,Male,3030,No,No,No,Moderate,Serosa,Good,1,0,2691,Yes +398,hospital_3,Obs,33,Male,3029,No,No,No,Moderate,Serosa,Good,2,0,2574,Yes +399,hospital_4,Lev,66,Male,3028,No,No,No,Moderate,Serosa,Good,7,0,2540,Yes +400,hospital_1,Lev,74,Female,3027,No,No,No,Moderate,Serosa,Good,2,0,2364,No +401,hospital_1,Lev,54,Male,3026,No,No,No,Moderate,Serosa,Good,1,0,2472,Yes +402,hospital_5,Obs,44,Male,3022,No,No,No,Moderate,Serosa,Bad,14,1,409,No +403,hospital_5,Obs,75,Male,3022,Yes,No,No,Moderate,Muscle,Bad,27,1,961,No +404,hospital_4,Lev,58,Male,3020,No,No,No,Moderate,Serosa,Good,6,0,2449,Yes +405,hospital_1,Lev,48,Male,3020,No,No,No,Well,Muscle,Good,6,0,2520,Yes +406,hospital_3,Lev,64,Female,3018,No,No,No,Moderate,Serosa,Bad,1,1,916,No +407,hospital_2,Lev,49,Male,3017,NA,No,No,Well,Serosa,Good,1,0,2227,Yes +408,hospital_2,Obs,55,Female,3014,No,No,No,Moderate,Serosa,Good,1,0,2394,No +409,hospital_1,Lev,60,Male,3013,No,No,No,Moderate,Serosa,Bad,3,0,2029,No +410,hospital_3,Obs,67,Male,3011,No,No,No,Moderate,Serosa,Bad,2,0,2487,Yes +411,hospital_3,Lev,79,Male,3011,No,No,No,Moderate,Muscle,Bad,1,1,2052,No +412,hospital_1,Lev,57,Male,3011,No,No,No,Moderate,Serosa,Good,1,0,2690,Yes +413,hospital_2,Obs,22,Female,3010,No,No,No,Moderate,Serosa,Good,3,0,2234,Yes +414,hospital_5,Obs,59,Male,3007,Yes,No,No,Well,Serosa,Bad,4,1,537,No +415,hospital_2,Lev,66,Female,3003,Yes,No,No,Well,Serosa,Good,1,0,2277,Yes +416,hospital_2,Lev,54,Male,3001,No,No,Yes,Moderate,Adjacent structures,Bad,2,1,729,No +417,hospital_4,Obs,58,Male,3000,No,No,No,Moderate,Muscle,Good,1,0,2194,No +418,hospital_1,Obs,36,Female,2999,Yes,No,No,Moderate,Serosa,Good,7,0,2551,No +419,hospital_5,Obs,52,Male,2999,No,No,No,Moderate,Serosa,Bad,4,1,1692,Yes +420,hospital_5,Obs,61,Female,2997,No,No,No,Moderate,Serosa,Bad,1,1,758,Yes +421,hospital_4,Lev,76,Female,2993,No,No,No,Well,Serosa,Good,2,1,2079,No +422,hospital_3,Lev,58,Female,2993,No,No,Yes,Well,Serosa,Bad,6,1,720,Yes +423,hospital_3,Lev,52,Male,2985,No,No,No,Well,Serosa,Good,5,0,2380,Yes +424,hospital_4,Obs,72,Male,2984,No,No,No,Moderate,Serosa,Bad,1,1,845,Yes +425,hospital_4,Lev,74,Male,2983,No,No,No,Well,Serosa,Good,1,0,2416,Yes +426,hospital_4,Obs,62,Male,2979,No,No,No,Moderate,Muscle,Bad,6,1,863,Yes +427,hospital_2,Obs,46,Female,2977,No,No,Yes,Moderate,Serosa,Bad,1,1,1363,No +428,hospital_2,Obs,66,Male,2976,No,No,No,Moderate,Serosa,Good,1,0,2528,No +429,hospital_2,Lev,52,Male,2976,No,No,No,Moderate,Serosa,Bad,5,1,1145,Yes +430,hospital_5,Lev,38,Female,2976,No,No,No,NA,Serosa,Bad,24,1,499,Yes +431,hospital_4,Obs,61,Male,2976,No,No,No,Moderate,Serosa,Bad,1,1,242,Yes +432,hospital_1,Obs,60,Female,2972,No,No,No,Well,Serosa,Good,1,0,2294,Yes +433,hospital_2,Lev,68,Female,2970,No,No,Yes,Well,Serosa,Bad,2,1,858,Yes +434,hospital_5,Lev,53,Female,2966,No,No,No,Moderate,Serosa,Bad,6,1,122,No +435,hospital_3,Lev,58,Male,2966,No,No,No,Moderate,Serosa,Bad,1,0,2682,Yes +436,hospital_3,Obs,64,Male,2966,No,No,No,Moderate,Serosa,Bad,4,1,1818,Yes +437,hospital_1,Obs,68,Male,2965,Yes,No,Yes,Moderate,Serosa,Good,3,0,2532,Yes +438,hospital_2,Obs,62,Male,2958,No,No,Yes,Moderate,Adjacent structures,Bad,6,1,331,Yes +439,hospital_2,Obs,70,Male,2955,No,No,No,Well,Serosa,Bad,1,1,1048,No +440,hospital_3,Lev,57,Male,2952,No,No,No,Moderate,Serosa,Good,1,0,2513,Yes +441,hospital_1,Lev,66,Female,2950,No,No,Yes,Moderate,Adjacent structures,Bad,1,1,340,Yes +442,hospital_3,Lev,59,Female,2947,NA,No,No,Moderate,Serosa,Good,11,1,1850,Yes +443,hospital_1,Lev,75,Male,2943,No,No,No,Well,Serosa,Good,3,0,2332,Yes +444,hospital_3,Lev,77,Male,2930,No,No,No,Moderate,Serosa,Good,2,0,2279,Yes +445,hospital_5,Lev,57,Male,2929,No,No,No,Moderate,Serosa,Bad,6,1,1041,Yes +446,hospital_3,Obs,72,Male,2925,No,No,No,Well,Muscle,Bad,2,1,1790,No +447,hospital_3,Lev,64,Female,2923,Yes,No,No,Moderate,Serosa,Bad,3,1,304,Yes +448,hospital_2,Lev,33,Male,2923,No,No,No,Poor,Serosa,Bad,2,0,2517,Yes +449,hospital_3,Lev,62,Female,2921,No,No,No,Moderate,Serosa,Bad,2,0,2156,Yes +450,hospital_4,Lev,70,Male,2920,No,No,No,Moderate,Serosa,Bad,1,1,1388,Yes +451,hospital_2,Lev,55,Female,2918,Yes,No,No,Well,Serosa,Good,4,0,2544,Yes +452,hospital_2,Obs,32,Male,2908,Yes,No,Yes,Moderate,Serosa,Good,11,0,1852,No +453,hospital_2,Obs,64,Female,2908,Yes,No,No,Moderate,Muscle,Good,2,0,2122,Yes +454,hospital_1,Obs,48,Female,2906,No,No,No,Moderate,Adjacent structures,Good,1,0,2577,Yes +455,hospital_4,Lev,68,Male,2906,No,No,Yes,Moderate,Serosa,Good,3,1,2023,No +456,hospital_2,Lev,59,Female,2901,No,No,No,Moderate,Serosa,Bad,1,1,1201,Yes +457,hospital_4,Obs,68,Male,2897,No,No,Yes,Poor,Serosa,Bad,9,1,901,Yes +458,hospital_3,Lev,50,Female,2895,No,No,Yes,Well,Serosa,Good,1,0,2385,Yes +459,hospital_2,Obs,41,Female,2895,Yes,No,No,Moderate,Serosa,Bad,4,1,663,Yes +460,hospital_2,Lev,69,Female,2892,No,No,Yes,Moderate,Serosa,Good,1,0,2506,Yes +461,hospital_1,Lev,46,Male,2890,No,No,No,Well,Muscle,Good,2,0,2332,Yes +462,hospital_4,Obs,43,Male,2885,No,No,No,Moderate,Serosa,Good,1,0,2176,Yes +463,hospital_3,Lev,68,Male,2881,No,No,No,Poor,Serosa,Bad,3,1,1212,No +464,hospital_4,Lev,73,Male,2880,No,No,No,Moderate,Serosa,Bad,3,1,890,No +465,hospital_5,Lev,66,Female,2876,No,No,Yes,Poor,Adjacent structures,Bad,4,1,302,Yes +466,hospital_1,Obs,60,Female,2876,No,No,Yes,Moderate,Serosa,Good,1,0,2396,Yes +467,hospital_1,Lev,74,Male,2871,No,No,No,Moderate,Serosa,Good,2,0,2481,No +468,hospital_5,Lev,68,Male,2869,No,No,No,Well,Serosa,Bad,1,1,316,Yes +469,hospital_1,Lev,60,Female,2868,Yes,No,No,Moderate,Serosa,Good,1,0,2245,Yes +470,hospital_2,Obs,71,Male,2864,No,No,Yes,Moderate,Adjacent structures,Good,1,0,2447,No +471,hospital_3,Obs,76,Male,2850,No,No,No,Moderate,Submucosa,Good,2,0,2213,Yes +472,hospital_5,Obs,57,Male,2844,No,No,No,Poor,Muscle,Bad,8,1,1070,Yes +473,hospital_4,Lev,33,Female,3102.4,No,No,No,Poor,Serosa,Bad,7,1,439,Yes +474,hospital_3,Lev,54,Male,3096,No,No,No,Moderate,Serosa,Bad,4,1,905,No +475,hospital_5,Obs,68,Male,3091.2,No,No,No,Moderate,Serosa,Bad,13,1,1723,Yes +476,hospital_5,Obs,70,Female,3086.4,No,No,No,Poor,Muscle,Bad,6,1,241,Yes +477,hospital_5,Obs,66,Male,3086.4,No,No,No,Moderate,Serosa,Bad,5,1,1314,No +478,hospital_5,Lev,45,Female,3068.8,Yes,No,No,Moderate,Serosa,Bad,3,1,438,Yes +479,hospital_1,Lev,61,Female,3068.8,No,No,No,Moderate,Serosa,Good,2,0,1981,Yes +480,hospital_1,Obs,74,Female,3064,No,No,Yes,Poor,Serosa,Good,1,0,2195,Yes +481,hospital_4,Obs,47,Male,3060.8,Yes,Yes,Yes,Moderate,Serosa,Bad,4,1,1101,Yes +482,hospital_5,Lev,58,Female,3051.2,Yes,No,No,Poor,Serosa,Bad,5,1,79,Yes +483,hospital_5,Obs,73,Male,3048,No,No,No,Moderate,Serosa,Bad,1,1,976,Yes +484,hospital_5,Lev,61,Male,3048,No,No,No,Moderate,Serosa,Bad,17,1,664,No +485,hospital_4,Obs,44,Female,3043.2,No,No,No,Moderate,Serosa,Good,4,0,2299,Yes +486,hospital_4,Lev,56,Male,3043.2,No,No,No,Moderate,Serosa,Bad,1,1,279,Yes +487,hospital_5,Lev,66,Female,3033.6,No,No,No,Moderate,Serosa,Bad,7,1,1037,Yes +488,hospital_5,Obs,30,Female,3025.6,No,No,No,Poor,Serosa,Bad,6,1,692,Yes +489,hospital_5,Lev,67,Female,3016,No,No,Yes,Moderate,Serosa,Good,10,1,2174,No +490,hospital_1,Lev,74,Female,3014.4,No,No,No,Moderate,Serosa,Good,2,0,2144,No +491,hospital_4,Lev,74,Female,3006.4,No,No,Yes,Poor,Serosa,Good,1,0,2058,Yes +492,hospital_4,Obs,56,Male,3006.4,No,No,No,Moderate,Serosa,Good,4,0,2485,Yes +493,hospital_1,Lev,60,Female,3000,No,No,No,Moderate,Serosa,Good,2,0,2410,Yes +494,hospital_1,Lev,54,Female,3000,Yes,No,Yes,Poor,Muscle,Good,2,0,2565,Yes +495,hospital_5,Lev,74,Female,2992,No,No,No,Moderate,Muscle,Bad,3,1,884,No +496,hospital_3,Lev,45,Female,2982.4,No,No,No,Moderate,Serosa,Bad,3,1,389,Yes +497,hospital_5,Lev,81,Female,2977.6,No,No,No,Moderate,Serosa,Bad,1,1,692,Yes +498,hospital_4,Lev,73,Male,2969.6,Yes,No,No,Moderate,Serosa,Bad,1,1,642,Yes +499,hospital_3,Lev,71,Male,2969.6,Yes,No,No,Moderate,Serosa,Bad,1,1,846,Yes +500,hospital_1,Lev,70,Male,2968,No,No,No,NA,Serosa,Good,3,0,2203,No +501,hospital_2,Lev,66,Male,2964.8,No,No,No,Moderate,Serosa,Bad,1,0,2164,Yes +502,hospital_3,Lev,71,Female,2963.2,No,No,No,Moderate,Serosa,Bad,NA,1,1273,Yes +503,hospital_3,Obs,48,Male,2961.6,No,No,No,Poor,Muscle,Bad,1,0,2393,Yes +504,hospital_4,Lev,55,Female,2960,No,No,No,Moderate,Serosa,Bad,4,1,862,No +505,hospital_1,Lev,72,Female,2942.4,No,No,No,Poor,Muscle,Good,2,0,2331,Yes +506,hospital_4,Lev,57,Male,2940.8,No,No,No,NA,Serosa,Good,3,0,2264,Yes +507,hospital_5,Lev,57,Male,2929.6,No,No,No,Poor,Serosa,Bad,11,1,144,No +508,hospital_1,Obs,38,Male,2926.4,No,No,No,Well,Serosa,Good,2,0,2429,Yes +509,hospital_2,Lev,52,Male,2924.8,Yes,No,No,Moderate,Serosa,Bad,0,1,723,Yes +510,hospital_2,Obs,57,Male,2923.2,No,No,No,Moderate,Serosa,Good,1,0,2530,Yes +511,hospital_4,Lev,33,Female,2923.2,No,No,No,Moderate,Serosa,Bad,2,1,1568,No +512,hospital_1,Obs,39,Female,2916.8,No,No,No,Moderate,Muscle,Good,2,0,2292,Yes +513,hospital_2,Lev,61,Male,2916.8,No,No,No,Moderate,Serosa,Good,1,0,2252,Yes +514,hospital_1,Lev,71,Female,2912,No,No,No,Poor,Serosa,Good,1,0,2408,No +515,hospital_3,Lev,58,Male,2910.4,No,No,No,Moderate,Serosa,Good,4,0,2555,No +516,hospital_3,Lev,66,Female,2908.8,No,No,No,Poor,Serosa,Bad,7,1,276,Yes +517,hospital_3,Obs,59,Female,2902.4,No,No,No,Moderate,Muscle,Good,4,1,1896,Yes +518,hospital_3,Lev,43,Female,2902.4,Yes,No,No,Moderate,Serosa,Good,1,0,2147,Yes +519,hospital_3,Obs,66,Male,2899.2,No,No,No,Moderate,Serosa,Good,3,0,2269,No +520,hospital_3,Obs,48,Female,2884.8,No,No,No,Moderate,Serosa,Good,1,0,2391,Yes +521,hospital_5,Lev,68,Male,2880,No,No,No,Moderate,Serosa,Bad,1,1,1424,Yes +522,hospital_2,Obs,72,Female,2876.8,No,No,No,Moderate,Serosa,Good,NA,0,2257,Yes +523,hospital_3,Lev,77,Female,2867.2,NA,No,No,Poor,Adjacent structures,Good,10,0,2381,Yes +524,hospital_1,Lev,68,Female,2864,Yes,No,No,Moderate,Serosa,Good,1,0,2103,Yes +525,hospital_4,Obs,44,Female,2860.8,No,No,Yes,Moderate,Adjacent structures,Good,1,0,2210,Yes +526,hospital_1,Lev,63,Female,2852.8,No,No,No,Moderate,Serosa,Good,1,0,2530,No +527,hospital_1,Lev,66,Male,2835.2,No,No,No,Moderate,Serosa,Good,1,0,2386,Yes +528,hospital_5,Lev,50,Male,2828.8,No,No,No,Poor,Serosa,Bad,3,1,219,Yes +529,hospital_3,Lev,72,Male,2827.2,No,No,No,Moderate,Serosa,Bad,1,1,486,No +530,hospital_4,Lev,40,Male,2803.2,No,No,No,Well,Serosa,Bad,5,1,1246,Yes +531,hospital_4,Lev,49,Male,2792,No,No,No,Moderate,Serosa,Good,10,0,2138,Yes +532,hospital_1,Lev,56,Female,2756.8,No,No,No,Poor,Serosa,Good,2,0,2439,No +533,hospital_4,Obs,61,Male,2734.4,No,No,No,Moderate,Muscle,Good,2,0,2231,Yes +534,hospital_5,Obs,65,Male,2707.2,No,No,No,Moderate,Serosa,Bad,6,1,384,Yes +535,hospital_3,Lev,65,Male,2686.4,No,No,No,Moderate,Muscle,Good,2,0,2505,Yes +536,hospital_5,Lev,72,Female,2673.6,No,No,No,Well,Submucosa,Bad,1,1,1652,Yes +537,hospital_1,Lev,68,Female,2668.8,No,No,Yes,Moderate,Serosa,Good,1,0,2441,No +538,hospital_4,Obs,59,Female,2649.6,No,No,No,Moderate,Serosa,Bad,4,1,687,No +539,hospital_4,Lev,59,Male,2643.2,No,No,No,Moderate,Serosa,Good,4,0,2179,Yes +540,hospital_2,Lev,71,Female,2619.2,Yes,No,No,Moderate,Serosa,Good,6,0,2189,Yes +541,hospital_3,Lev,49,Male,2592,No,No,No,Moderate,Serosa,Good,8,0,2472,Yes +542,hospital_1,Lev,70,Male,2571.2,No,No,No,Moderate,Serosa,Good,3,0,2111,Yes +543,hospital_3,Lev,55,Male,2508.8,No,No,No,Poor,Serosa,Good,7,0,2020,Yes +544,hospital_4,Lev,46,Female,2480,No,Yes,No,Moderate,Serosa,Bad,7,1,1161,Yes +545,hospital_1,Obs,77,Male,2476.8,No,No,No,Moderate,Serosa,Good,1,0,2231,Yes +546,hospital_2,Lev,57,Male,2476.8,No,No,No,Moderate,Serosa,Good,4,0,2300,Yes +547,hospital_3,Obs,68,Male,2464,No,No,No,Moderate,Serosa,Good,1,0,2391,Yes +548,hospital_2,Lev,62,Male,2459.2,No,No,Yes,Moderate,Serosa,Bad,1,1,759,No +549,hospital_2,Obs,44,Male,2448,No,No,No,Poor,Serosa,Bad,7,1,166,No +550,hospital_1,Lev,58,Female,2433.6,No,No,Yes,Moderate,Serosa,Good,1,0,2323,Yes +551,hospital_3,Lev,75,Female,2417.6,No,No,No,Well,Serosa,Good,2,0,2321,Yes +552,hospital_1,Obs,70,Female,2414.4,Yes,No,No,Moderate,Serosa,Good,7,0,1976,Yes +553,hospital_4,Obs,82,Male,2392,No,No,No,Moderate,Serosa,Good,6,0,2229,No +554,hospital_3,Lev,61,Female,2371.2,No,No,No,Moderate,Serosa,Bad,3,1,1671,Yes +555,hospital_2,Obs,52,Male,2358.4,No,No,No,Moderate,Serosa,Good,2,1,1907,Yes +556,hospital_4,Lev,47,Male,2315.2,No,No,No,Poor,Serosa,Bad,7,1,1783,Yes +557,hospital_4,Lev,61,Female,2313.6,No,No,No,Poor,Serosa,Bad,7,1,684,Yes +558,hospital_3,Lev,39,Male,2302.4,No,No,No,Moderate,Serosa,Bad,9,1,441,Yes +559,hospital_2,Lev,69,Female,2299.2,No,No,No,Moderate,Muscle,Bad,3,1,902,No +560,hospital_4,Lev,55,Male,2294.4,No,No,No,Poor,Serosa,Good,7,0,2244,Yes +561,hospital_1,Obs,56,Female,2294.4,Yes,No,No,Moderate,Serosa,Good,1,0,2170,Yes +562,hospital_3,Obs,80,Male,2278.4,No,No,No,Poor,Serosa,Good,1,0,1870,No +563,hospital_3,Lev,43,Male,2273.6,No,No,No,Moderate,Serosa,Good,4,0,2066,No +564,hospital_4,Lev,83,Male,2248,No,No,No,Moderate,Serosa,Good,2,0,2030,Yes +565,hospital_4,Obs,85,Female,2238.4,No,No,No,Well,Serosa,Bad,1,1,253,Yes +566,hospital_1,Lev,61,Male,2220.8,No,No,No,Moderate,Serosa,Good,1,0,2047,No +567,hospital_3,Lev,47,Female,2219.2,No,No,No,Moderate,Adjacent structures,Bad,9,1,1768,Yes +568,hospital_4,Lev,76,Female,2200,No,No,No,Moderate,Serosa,Good,1,0,2043,Yes +569,hospital_2,Lev,58,Male,2184,No,No,No,Moderate,Serosa,Good,1,0,2162,Yes +570,hospital_1,Obs,59,Male,2180.8,No,No,No,Moderate,Muscle,Good,2,0,2093,Yes +571,hospital_4,Lev,60,Female,2123.2,No,No,No,Moderate,Serosa,Good,1,0,2310,No +572,hospital_4,Lev,32,Male,2120,No,No,No,Moderate,Serosa,Good,2,1,2128,No +573,hospital_5,Obs,56,Male,2102.4,No,No,No,NA,Adjacent structures,Good,1,1,1884,No +574,hospital_5,Lev,75,Male,2100.8,No,No,No,Moderate,Serosa,Bad,2,1,219,No +575,hospital_4,Lev,62,Male,2089.6,No,No,No,Well,Serosa,Good,3,0,2309,No +576,hospital_4,Obs,69,Female,2086.4,No,No,No,Moderate,Serosa,Bad,12,1,313,Yes +577,hospital_5,Lev,72,Male,2083.2,No,No,Yes,Moderate,Serosa,Bad,4,1,546,Yes +578,hospital_2,Obs,54,Female,2072,No,No,No,Moderate,Serosa,Good,1,1,2213,Yes +579,hospital_5,Lev,72,Male,2072,No,No,No,Moderate,Serosa,Good,1,1,1856,No +580,hospital_2,Lev,27,Female,2064,No,No,No,Moderate,Serosa,NA,1,0,1421,No +581,hospital_4,Lev,62,Female,2046.4,No,No,No,Moderate,Adjacent structures,Bad,4,1,460,Yes +582,hospital_1,Lev,39,Female,2046.4,No,No,No,Moderate,Submucosa,Good,2,0,2173,No +583,hospital_5,Lev,60,Female,2041.6,No,No,No,Moderate,Serosa,Bad,4,1,283,Yes +584,hospital_2,Lev,55,Male,2041.6,Yes,No,No,Poor,Serosa,Bad,5,1,34,Yes +585,hospital_1,Obs,64,Male,2036.8,No,No,No,Moderate,Serosa,Good,1,0,2191,Yes +586,hospital_3,Lev,68,Female,2035.2,No,No,No,Poor,Serosa,Good,12,0,2186,No +587,hospital_3,Obs,65,Female,2019.2,No,No,No,Moderate,Serosa,Bad,2,1,1159,Yes +588,hospital_4,Lev,66,Female,2019.2,Yes,No,No,Well,Serosa,Bad,3,1,616,Yes +589,hospital_1,Lev,39,Male,2003.2,No,No,No,Poor,Serosa,Good,2,0,2270,Yes +590,hospital_1,Lev,54,Male,1993.6,No,No,Yes,Moderate,Serosa,Bad,NA,1,1061,No +591,hospital_5,Obs,34,Male,1993.6,Yes,No,No,Moderate,Serosa,Bad,1,1,591,No +592,hospital_4,Lev,74,Female,1979.2,No,No,No,Moderate,Serosa,Good,4,0,2065,Yes +593,hospital_2,Obs,81,Female,1968,Yes,No,Yes,Moderate,Serosa,Bad,3,1,208,Yes +594,hospital_1,Lev,38,Male,1950.4,No,No,No,Moderate,Serosa,Good,1,0,2360,Yes +595,hospital_2,Lev,59,Female,1945.6,No,No,No,Moderate,Serosa,Good,3,0,2312,Yes +596,hospital_2,Lev,62,Female,1944,No,No,No,Moderate,Serosa,Good,1,0,1902,Yes +597,hospital_2,Lev,61,Male,1939.2,Yes,No,No,Well,Muscle,NA,5,0,1814,Yes +598,hospital_1,Obs,46,Male,1934.4,Yes,No,No,Moderate,Serosa,Good,2,0,2111,No +599,hospital_1,Lev,55,Male,1931.2,No,No,No,Moderate,Serosa,Good,1,0,2330,Yes +600,hospital_4,Obs,57,Male,1921.6,No,No,No,Moderate,Serosa,Good,5,0,2202,Yes +601,hospital_4,Lev,38,Female,1916.8,No,No,No,Moderate,Serosa,Bad,3,1,1295,No +602,hospital_5,Lev,69,Female,1912,No,No,Yes,Moderate,Serosa,Good,19,0,1918,Yes +603,hospital_4,Obs,79,Female,1908.8,No,No,Yes,Moderate,Muscle,Good,6,0,2066,Yes +604,hospital_4,Lev,71,Female,1905.6,No,No,No,Moderate,Serosa,Good,2,0,2136,No +605,hospital_2,Lev,74,Male,1897.6,No,No,No,Poor,Serosa,Good,1,0,2289,Yes +606,hospital_4,Lev,30,Female,1884.8,Yes,No,No,Moderate,Serosa,Bad,12,1,576,Yes +607,hospital_1,Obs,72,Female,1884.8,No,No,No,Poor,Serosa,Good,1,0,2232,Yes +608,hospital_5,Lev,68,Female,1865.6,NA,No,No,Moderate,Serosa,Bad,3,1,1034,Yes +609,hospital_2,Lev,66,Male,1857.6,Yes,No,No,Poor,Submucosa,Bad,NA,1,583,Yes +610,hospital_5,Obs,63,Male,1854.4,No,No,No,Moderate,Serosa,Bad,4,1,417,Yes +611,hospital_3,Lev,52,Female,1846.4,No,No,Yes,Moderate,Serosa,Good,1,0,1905,Yes +612,hospital_4,Lev,64,Male,1841.6,No,No,No,Moderate,Serosa,Bad,4,1,875,Yes +613,hospital_5,Lev,68,Male,1832,No,No,No,Moderate,Serosa,Bad,1,1,674,Yes +614,hospital_3,Lev,74,Male,1832,No,No,No,Moderate,Serosa,Good,2,0,2185,Yes +615,hospital_5,Lev,32,Male,1822.4,No,No,No,Moderate,Serosa,Bad,2,1,1151,No +616,hospital_4,Lev,60,Female,1820.8,Yes,No,No,Moderate,Serosa,Bad,6,1,342,Yes +617,hospital_5,Obs,39,Female,1817.6,No,No,No,Moderate,Serosa,Good,8,0,2187,Yes +618,hospital_5,Obs,76,Female,1816,No,No,Yes,Moderate,Serosa,Bad,5,1,1434,Yes +619,hospital_5,Lev,62,Male,1814.4,No,No,No,Poor,Serosa,Bad,14,1,430,Yes +620,hospital_4,Lev,41,Female,1812.8,No,No,Yes,Moderate,Serosa,Good,2,0,2339,Yes +621,hospital_5,Lev,35,Male,1795.2,No,No,Yes,Moderate,Serosa,Bad,2,1,1365,Yes +622,hospital_4,Obs,59,Female,1787.2,No,No,No,Moderate,Serosa,Good,1,0,2313,No +623,hospital_3,Obs,52,Male,1779.2,No,No,No,Moderate,Serosa,Good,2,0,2153,Yes +624,hospital_2,Lev,65,Male,1768,No,No,No,Moderate,Serosa,Good,1,0,2164,No +625,hospital_3,Lev,61,Male,1764.8,No,No,No,Poor,Serosa,Good,3,0,2180,No +626,hospital_4,Obs,61,Male,1761.6,No,No,No,Well,Serosa,Good,8,0,2110,Yes +627,hospital_1,Obs,59,Male,1747.2,No,No,No,Well,Serosa,Good,1,0,2139,Yes +628,hospital_1,Lev,59,Male,1732.8,No,No,No,NA,Serosa,Good,2,0,2120,No +629,hospital_3,Lev,71,Female,1726.4,No,No,No,Moderate,Muscle,Good,5,1,2197,Yes +630,hospital_2,Obs,39,Male,1712,No,No,No,Poor,Adjacent structures,NA,4,0,453,No +631,hospital_4,Obs,65,Male,1697.6,No,No,No,Poor,Serosa,Bad,7,1,928,No +632,hospital_2,Lev,34,Female,1688,Yes,No,No,Well,Serosa,Bad,3,1,675,Yes +633,hospital_1,Obs,51,Male,1676.8,Yes,No,No,Moderate,Serosa,Good,4,0,2170,No +634,hospital_3,Obs,55,Female,1673.6,No,No,No,Moderate,Serosa,Good,3,0,2138,Yes +635,hospital_4,Lev,65,Male,1665.6,No,Yes,No,Poor,Serosa,Good,3,0,2255,Yes +636,hospital_1,Lev,71,Female,1659.2,No,No,No,Well,Serosa,Good,NA,0,2290,No +637,hospital_2,Lev,68,Female,1654.4,Yes,No,No,Moderate,Serosa,Bad,1,1,1055,Yes +638,hospital_2,Lev,59,Female,1649.6,No,No,No,Moderate,Serosa,Good,1,0,2347,No +639,hospital_4,Lev,66,Male,1635.2,No,No,No,Poor,Serosa,Bad,2,1,573,No +640,hospital_4,Obs,62,Male,1633.6,No,No,No,Moderate,Muscle,Good,2,0,2200,No +641,hospital_5,Lev,40,Female,1628.8,No,No,No,Moderate,Serosa,Bad,8,1,550,Yes +642,hospital_5,Lev,64,Male,1595.2,No,No,No,Poor,Serosa,Bad,3,1,1405,Yes +643,hospital_4,Lev,40,Male,1595.2,Yes,No,No,Poor,Serosa,Good,2,0,2355,No +644,hospital_4,Lev,70,Male,1588.8,No,No,No,Moderate,Serosa,Bad,9,1,1186,Yes +645,hospital_2,Lev,66,Male,1577.6,No,No,Yes,NA,Adjacent structures,Bad,1,1,1540,Yes +646,hospital_3,Lev,73,Male,1563.2,Yes,No,Yes,Moderate,Muscle,Good,1,0,2229,Yes +647,hospital_3,Lev,69,Male,1561.6,No,No,No,Well,Serosa,Bad,1,1,969,Yes +648,hospital_3,Obs,58,Male,1550.4,No,No,No,Moderate,Serosa,Bad,1,1,465,Yes +649,hospital_4,Lev,55,Female,1548.8,No,No,No,Moderate,Serosa,Bad,6,1,603,No +650,hospital_5,Lev,53,Female,1545.6,No,No,Yes,Moderate,Serosa,Bad,6,1,997,No +651,hospital_1,Lev,52,Male,1540.8,No,No,No,Moderate,Serosa,Good,2,0,2274,Yes +652,hospital_3,Obs,62,Female,1537.6,No,No,No,Moderate,Serosa,Bad,3,1,563,Yes +653,hospital_3,Lev,61,Male,1537.6,No,No,Yes,Moderate,Serosa,Bad,2,1,1434,Yes +654,hospital_4,Lev,69,Female,1537.6,No,No,No,Moderate,Serosa,Good,3,0,2316,Yes +655,hospital_5,Lev,41,Female,1537.6,Yes,No,No,Moderate,Serosa,Bad,3,1,692,Yes +656,hospital_5,Obs,64,Male,1531.2,No,No,No,Moderate,Serosa,Bad,3,1,1447,No +657,hospital_5,Lev,59,Female,1523.2,No,No,No,Poor,Serosa,Bad,3,1,428,Yes +658,hospital_2,Lev,65,Female,1518.4,No,No,No,Well,Muscle,Good,1,0,2152,Yes +659,hospital_4,Obs,66,Male,1510.4,No,No,No,Moderate,Serosa,Bad,3,1,854,Yes +660,hospital_1,Lev,60,Male,1507.2,No,No,No,Moderate,Serosa,Good,2,0,2093,Yes +661,hospital_2,Lev,43,Male,1504,No,No,Yes,Moderate,Serosa,Good,1,0,2198,No +662,hospital_2,Obs,74,Male,1502.4,No,No,No,Poor,Serosa,Good,1,0,2126,Yes +663,hospital_1,Lev,67,Male,1500.8,No,No,No,Poor,Muscle,Good,2,0,2189,Yes +664,hospital_1,Lev,46,Male,1497.6,Yes,No,No,Moderate,Serosa,Good,1,0,2142,Yes +665,hospital_2,Lev,47,Male,1486.4,No,No,No,Moderate,Muscle,Good,3,0,2278,Yes +666,hospital_3,Obs,66,Male,1484.8,Yes,No,No,Moderate,Serosa,Bad,4,1,622,Yes +667,hospital_2,Lev,36,Female,1478.4,Yes,No,No,Moderate,Serosa,Good,6,0,2192,Yes +668,hospital_3,Obs,62,Male,1465.6,Yes,No,No,Poor,Serosa,Bad,2,1,413,No +669,hospital_5,Lev,69,Female,1457.6,No,No,No,Moderate,Serosa,Bad,2,1,1191,Yes +670,hospital_3,Obs,76,Female,1454.4,No,No,No,Well,Serosa,Bad,3,1,1139,Yes +671,hospital_5,Lev,36,Male,1448,Yes,No,No,Poor,Serosa,Bad,2,1,165,Yes +672,hospital_1,Obs,73,Male,1448,No,No,Yes,NA,Muscle,Good,3,0,2210,Yes +673,hospital_3,Obs,72,Male,1443.2,No,No,No,Moderate,Muscle,Good,5,0,2227,Yes +674,hospital_4,Lev,61,Male,1441.6,No,No,No,Moderate,Muscle,Good,1,0,2076,No +675,hospital_1,Obs,58,Male,1424,No,No,No,Moderate,Serosa,Good,2,0,2132,Yes +676,hospital_2,Lev,52,Female,1419.2,Yes,No,No,Well,Serosa,Good,3,0,2084,Yes +677,hospital_3,Obs,66,Male,1419.2,No,No,No,Moderate,Adjacent structures,Good,2,0,1905,No +678,hospital_3,Lev,43,Female,1419.2,No,No,No,Moderate,Serosa,Bad,7,1,608,Yes +679,hospital_1,Lev,60,Male,1416,No,No,No,Moderate,Muscle,Good,1,0,2066,Yes +680,hospital_3,Obs,61,Female,1414.4,No,No,No,Moderate,Serosa,Good,4,0,2006,Yes +681,hospital_4,Lev,61,Male,1412.8,No,No,No,Moderate,Muscle,Good,3,0,2183,Yes +682,hospital_2,Lev,46,Male,1400,No,No,No,Moderate,Submucosa,Good,1,0,2099,Yes +683,hospital_3,Lev,73,Male,1398.4,No,No,No,Moderate,Serosa,Good,1,0,1879,Yes +684,hospital_4,Obs,65,Female,1380.8,Yes,No,No,Moderate,Serosa,Bad,3,1,264,Yes +685,hospital_2,Lev,61,Female,1379.2,Yes,No,No,Moderate,Serosa,Good,1,0,2107,No +686,hospital_5,Lev,65,Male,1372.8,No,No,No,Poor,Serosa,Bad,15,1,743,No +687,hospital_3,Obs,68,Male,1366.4,No,No,No,Moderate,Serosa,Bad,2,1,966,Yes +688,hospital_4,Lev,63,Male,1353.6,No,No,No,Moderate,Serosa,Good,1,0,2076,Yes +689,hospital_5,Lev,72,Male,1352,Yes,No,No,Poor,Serosa,Bad,4,1,24,No +690,hospital_4,Lev,74,Female,1350.4,No,Yes,No,Moderate,Serosa,Bad,2,1,448,Yes +691,hospital_5,Lev,45,Female,1344,No,No,No,Moderate,Serosa,Bad,9,1,909,Yes +692,hospital_3,Lev,66,Female,1332.8,No,No,No,Well,Serosa,Good,1,0,2188,No +693,hospital_3,Obs,38,Male,1332.8,NA,No,No,NA,Adjacent structures,Bad,2,1,469,Yes +694,hospital_2,Obs,46,Female,1331.2,No,Yes,Yes,Poor,Adjacent structures,Bad,2,1,594,Yes +695,hospital_1,Lev,51,Female,1297.6,No,No,No,Moderate,Serosa,Good,1,0,2008,Yes +696,hospital_2,Lev,65,Male,1289.6,No,No,No,Moderate,Adjacent structures,Bad,3,1,1276,No +697,hospital_3,Obs,55,Male,1289.6,No,No,No,Moderate,Serosa,Bad,2,1,957,Yes +698,hospital_4,Obs,58,Male,1283.2,No,No,No,Moderate,Serosa,Good,4,1,1950,Yes +699,hospital_1,Lev,65,Male,1283.2,No,No,No,Moderate,Serosa,Good,1,0,2668,No +700,hospital_1,Lev,46,Female,1275.2,Yes,No,No,Well,Serosa,Good,2,0,2250,Yes +701,hospital_1,Lev,57,Female,1272,No,No,No,Moderate,Serosa,Good,1,0,2191,Yes +702,hospital_2,Obs,67,Male,1240,No,No,Yes,Moderate,Serosa,Good,1,0,2365,Yes +703,hospital_1,Lev,75,Female,1238.4,No,No,No,Moderate,Serosa,Good,1,0,2331,Yes +704,hospital_5,Lev,64,Male,1232,No,No,Yes,Moderate,Serosa,Bad,5,1,1262,Yes +705,hospital_2,Lev,63,Male,1225.6,No,No,No,Moderate,Serosa,NA,2,0,1537,Yes +706,hospital_1,Lev,64,Male,1224,No,No,No,Moderate,Serosa,Good,3,0,2387,No +707,hospital_1,Obs,59,Male,1222.4,No,No,No,Moderate,Serosa,Bad,1,0,2235,Yes +708,hospital_3,Lev,78,Female,1217.6,No,No,No,Moderate,Serosa,Bad,3,0,1980,Yes +709,hospital_4,Lev,63,Male,1216,No,No,No,Well,Submucosa,Bad,2,1,578,Yes +710,hospital_3,Obs,57,Male,1214.4,No,No,No,Well,Serosa,Bad,4,1,1083,Yes +711,hospital_5,Obs,52,Male,1214.4,No,No,No,Moderate,Serosa,Good,3,1,1875,No +712,hospital_1,Obs,50,Female,1212.8,No,No,No,Moderate,Serosa,Good,3,0,2384,No +713,hospital_2,Obs,36,Male,1208,Yes,No,No,Moderate,Serosa,Bad,3,1,563,Yes +714,hospital_1,Lev,50,Female,1204.8,No,No,No,Poor,Serosa,Good,4,0,2076,Yes +715,hospital_1,Obs,53,Male,1188.8,No,No,No,Moderate,Serosa,Good,1,0,2025,Yes +716,hospital_4,Lev,48,Male,1188.8,No,No,No,Moderate,Serosa,Good,7,0,2055,Yes +717,hospital_3,Obs,55,Female,1182.4,No,No,No,Moderate,Serosa,Bad,2,1,1375,No +718,hospital_2,Lev,47,Male,1177.6,No,No,No,Moderate,Muscle,Good,2,0,2350,Yes +719,hospital_1,Lev,74,Female,1168,No,No,Yes,Moderate,Serosa,Good,1,0,2200,Yes +720,hospital_3,Lev,53,Male,1166.4,Yes,Yes,No,Moderate,Serosa,Good,3,0,2222,Yes +721,hospital_2,Obs,55,Male,1156.8,No,No,No,Moderate,Serosa,Good,7,0,2149,Yes +722,hospital_3,Lev,53,Male,1153.6,No,No,No,Moderate,Muscle,Good,4,0,2303,No +723,hospital_3,Obs,67,Male,1152,No,Yes,No,Moderate,Adjacent structures,Bad,4,1,322,Yes +724,hospital_5,Lev,56,Male,1148.8,No,No,No,Moderate,Serosa,Bad,3,1,764,Yes +725,hospital_3,Lev,30,Female,1147.2,Yes,No,Yes,Moderate,Serosa,Bad,1,1,765,Yes +726,hospital_5,Lev,56,Female,1145.6,No,No,No,Well,Serosa,Bad,8,1,93,No +727,hospital_1,Lev,46,Male,1139.2,Yes,No,No,Moderate,Serosa,Good,3,0,1918,Yes +728,hospital_4,Lev,60,Male,1134.4,No,No,No,Well,Muscle,Good,1,1,1932,Yes +729,hospital_1,Obs,60,Female,1134.4,No,No,No,Moderate,Muscle,Good,1,0,2278,No +730,hospital_5,Obs,57,Male,1132.8,Yes,No,No,Poor,Serosa,Bad,9,1,145,Yes +731,hospital_1,Lev,42,Female,1129.6,No,No,No,Poor,Serosa,Good,1,0,1913,Yes +732,hospital_2,Obs,58,Male,1113.6,No,No,No,Moderate,Serosa,Good,2,0,2176,Yes +733,hospital_3,Obs,53,Female,1108.8,No,No,No,Poor,Serosa,Good,1,0,1995,No +734,hospital_4,Lev,73,Male,1107.2,No,No,Yes,Moderate,Serosa,Good,1,0,2023,Yes +735,hospital_2,Obs,73,Male,1107.2,No,No,No,Moderate,Serosa,Good,7,0,1935,Yes +736,hospital_2,Obs,57,Male,1107.2,No,No,No,Moderate,Serosa,Good,NA,0,2191,No +737,hospital_2,Lev,77,Female,1099.2,No,No,No,Poor,Serosa,Good,1,0,2191,No +738,hospital_1,Obs,60,Male,1096,No,No,No,NA,Serosa,Good,2,0,1856,Yes +739,hospital_4,Lev,74,Male,1094.4,No,No,No,Moderate,Serosa,Bad,8,1,628,Yes +740,hospital_2,Lev,70,Male,1084.8,No,No,No,Moderate,Muscle,Good,3,0,1976,Yes +741,hospital_1,Obs,53,Female,1080,No,No,No,Moderate,Serosa,NA,5,0,1819,No +742,hospital_4,Lev,68,Female,1078.4,No,No,Yes,Moderate,Adjacent structures,Bad,8,1,141,Yes +743,hospital_4,Lev,59,Male,1076.8,Yes,No,No,Moderate,Serosa,Bad,2,1,422,Yes +744,hospital_3,Lev,29,Male,1072,Yes,No,No,Moderate,Serosa,Good,3,0,2006,Yes +745,hospital_1,Obs,57,Female,1070.4,No,No,No,Moderate,Muscle,Good,2,0,2113,Yes +746,hospital_3,Obs,61,Male,1065.6,No,No,No,Moderate,Muscle,NA,4,0,1823,Yes +747,hospital_2,Obs,68,Male,1064,Yes,No,No,Moderate,Serosa,Good,3,0,2170,Yes +748,hospital_3,Lev,49,Male,1062.4,No,No,No,Moderate,Serosa,Bad,11,1,1812,No +749,hospital_1,Lev,70,Female,1060.8,No,No,No,Moderate,Serosa,Good,2,0,1838,Yes +750,hospital_1,Obs,53,Male,1054.4,Yes,No,No,Moderate,Serosa,Good,2,0,1855,Yes +751,hospital_2,Lev,57,Female,1035.2,Yes,No,No,Poor,Serosa,Bad,2,1,269,No +752,hospital_2,Lev,76,Male,1028.8,No,No,No,Moderate,Serosa,Good,1,0,2414,Yes +753,hospital_2,Lev,59,Male,1028.8,No,No,Yes,Moderate,Muscle,Good,2,0,2174,Yes +754,hospital_3,Lev,56,Male,1027.2,No,No,No,Moderate,Muscle,Good,1,0,2263,No +755,hospital_4,Lev,38,Male,1027.2,No,No,No,Moderate,Serosa,Bad,7,1,1495,Yes +756,hospital_4,Lev,61,Female,1025.6,No,No,No,Poor,Serosa,Bad,10,1,314,Yes +757,hospital_3,Obs,49,Male,1006.4,No,No,No,Moderate,Serosa,Good,2,0,2261,Yes +758,hospital_5,Obs,69,Female,1004.8,No,No,No,Moderate,Serosa,Bad,12,1,716,Yes +759,hospital_3,Obs,53,Male,995.2,No,No,No,Moderate,Serosa,Good,1,0,2190,No +760,hospital_2,Lev,72,Female,985.6,No,No,No,Poor,Serosa,Good,6,0,2331,No +761,hospital_1,Lev,57,Female,982.4,No,No,No,Moderate,Serosa,Good,3,0,2187,Yes +762,hospital_5,Lev,73,Male,979.2,No,No,Yes,Moderate,Adjacent structures,Bad,1,1,602,Yes +763,hospital_4,Lev,58,Female,974.4,No,No,Yes,Well,Serosa,Bad,2,1,666,Yes +764,hospital_5,Lev,69,Male,972.8,No,No,No,Moderate,Serosa,Bad,5,1,138,Yes +765,hospital_1,Obs,69,Female,964.8,Yes,No,No,Poor,Serosa,Good,3,0,2001,Yes +766,hospital_5,Lev,47,Female,963.2,No,No,No,Moderate,Serosa,Bad,5,1,887,Yes +767,hospital_2,Lev,80,Female,963.2,No,Yes,No,Well,Muscle,Bad,2,1,1207,Yes +768,hospital_1,Lev,67,Male,961.6,No,No,No,Moderate,Serosa,Good,2,0,1997,Yes +769,hospital_1,Lev,54,Female,958.4,No,No,No,Moderate,Serosa,Good,1,0,1864,Yes +770,hospital_3,Lev,63,Male,952,NA,No,Yes,Poor,Serosa,Good,7,0,2422,No +771,hospital_4,Lev,65,Female,950.4,Yes,No,No,Poor,Serosa,Bad,NA,1,444,No +772,hospital_4,Lev,65,Female,947.2,No,Yes,Yes,Moderate,Serosa,Good,3,0,2375,Yes +773,hospital_5,Obs,48,Female,945.6,Yes,No,No,Moderate,Serosa,Bad,2,1,718,Yes +774,hospital_1,Obs,52,Male,942.4,No,No,No,Moderate,Serosa,Good,2,0,2204,Yes +775,hospital_1,Obs,67,Male,939.2,No,No,Yes,Well,Serosa,Good,1,0,2120,No +776,hospital_5,Lev,70,Female,932.8,No,Yes,Yes,Well,Serosa,Bad,5,1,766,Yes +777,hospital_5,Lev,51,Female,931.2,Yes,No,Yes,Poor,Serosa,Bad,6,1,366,Yes +778,hospital_5,Lev,32,Female,928,No,No,No,Poor,Muscle,Bad,14,1,1752,Yes +779,hospital_1,Lev,63,Male,928,No,No,Yes,Poor,Serosa,Good,7,0,2183,Yes +780,hospital_1,Obs,81,Female,924.8,No,No,Yes,Moderate,Serosa,Good,1,0,1902,Yes +781,hospital_3,Obs,66,Male,921.6,No,No,No,Moderate,Adjacent structures,Bad,7,1,259,No +782,hospital_4,Lev,60,Female,921.6,No,Yes,Yes,Poor,Serosa,Bad,4,1,609,Yes +783,hospital_5,Obs,81,Female,916.8,Yes,No,No,Well,Serosa,Bad,1,1,832,Yes +784,hospital_2,Obs,66,Male,912,Yes,No,Yes,Moderate,Serosa,Bad,4,1,164,No +785,hospital_2,Lev,78,Male,910.4,No,No,Yes,Poor,Serosa,Good,2,0,1828,No +786,hospital_2,Lev,46,Female,900.8,No,No,No,Moderate,Serosa,Good,3,0,2147,Yes +787,hospital_4,Obs,57,Female,900.8,No,No,No,Moderate,Serosa,Bad,NA,1,201,Yes +788,hospital_1,Lev,57,Female,894.4,No,No,No,Moderate,Submucosa,Good,3,0,2221,No +789,hospital_2,Lev,67,Female,884.8,No,No,No,Poor,Serosa,Bad,2,1,503,Yes +790,hospital_5,Lev,68,Male,880,No,No,No,Moderate,Serosa,Bad,9,1,376,Yes +791,hospital_2,Lev,38,Female,873.6,No,No,No,Moderate,Serosa,Bad,2,1,811,Yes +792,hospital_1,Lev,70,Female,859.2,No,No,No,Moderate,Serosa,Good,3,0,1985,Yes +793,hospital_1,Obs,66,Male,846.4,No,No,No,Moderate,Serosa,Good,2,0,2076,No +794,hospital_4,Lev,63,Male,844.8,No,No,No,Moderate,Serosa,Bad,8,1,1154,No +795,hospital_5,Lev,72,Male,835.2,No,No,No,Moderate,Muscle,Bad,5,1,844,No +796,hospital_2,Obs,61,Male,819.2,Yes,No,Yes,Well,Serosa,Bad,1,1,1031,No +797,hospital_5,Lev,46,Male,816,No,No,No,Moderate,Serosa,Bad,3,1,1302,No +798,hospital_2,Lev,36,Female,809.6,Yes,No,No,Moderate,Serosa,Good,3,0,2169,Yes +799,hospital_2,Obs,69,Female,804.8,No,No,No,Moderate,Muscle,Good,1,0,1929,Yes +800,hospital_2,Lev,75,Female,798.4,No,No,No,Moderate,Serosa,NA,1,0,1800,Yes +801,hospital_5,Lev,64,Female,798.4,No,No,No,Moderate,Serosa,Bad,12,1,355,No +802,hospital_1,Lev,77,Male,798.4,No,No,No,Moderate,Serosa,Bad,1,1,669,No +803,hospital_3,Obs,51,Female,796.8,NA,No,No,Moderate,Muscle,Bad,7,1,465,Yes +804,hospital_4,Obs,36,Male,784,No,No,No,Moderate,Serosa,Bad,6,0,2157,No +805,hospital_5,Obs,56,Male,777.6,No,No,No,Moderate,Serosa,Bad,7,1,929,Yes +806,hospital_3,Lev,63,Female,776,No,No,No,Moderate,Serosa,Good,2,0,2242,Yes +807,hospital_2,Lev,64,Male,774.4,No,No,No,Moderate,Serosa,Good,2,0,2212,Yes +808,hospital_1,Lev,44,Male,760,No,No,No,Moderate,Serosa,Good,1,0,2148,No +809,hospital_5,Lev,73,Male,758.4,Yes,No,No,Moderate,Serosa,Bad,7,1,171,Yes +810,hospital_3,Lev,54,Male,755.2,Yes,No,No,Moderate,Adjacent structures,Bad,1,1,629,Yes +811,hospital_2,Lev,44,Male,750.4,No,No,No,Moderate,Muscle,Good,2,1,1829,Yes +812,hospital_2,Lev,30,Male,744,No,Yes,No,Moderate,Serosa,Good,9,0,1939,No +813,hospital_5,Lev,65,Female,744,No,No,No,Moderate,Serosa,Bad,7,1,529,No +814,hospital_2,Obs,68,Female,742.4,Yes,No,No,Moderate,Serosa,Good,2,0,2130,Yes +815,hospital_1,Obs,56,Female,739.2,No,No,No,NA,Submucosa,Good,2,0,1990,Yes +816,hospital_3,Obs,62,Male,736,No,No,No,Poor,Serosa,Bad,5,1,587,Yes +817,hospital_4,Lev,36,Female,734.4,No,No,No,Well,Muscle,Bad,7,1,1145,Yes +818,hospital_1,Lev,57,Male,726.4,No,No,No,Well,Serosa,Good,2,0,2162,Yes +819,hospital_5,Lev,31,Male,724.8,Yes,No,No,Well,Serosa,Bad,NA,1,643,Yes +820,hospital_4,Lev,39,Male,716.8,No,No,No,Moderate,Serosa,Good,11,0,2129,No +821,hospital_5,Obs,53,Male,710.4,No,No,No,Moderate,Serosa,Bad,3,1,1437,Yes +822,hospital_5,Lev,60,Male,708.8,Yes,No,No,Moderate,Adjacent structures,Bad,14,1,512,Yes +823,hospital_1,Obs,65,Female,705.6,Yes,No,No,Moderate,Serosa,Good,1,0,2008,No +824,hospital_1,Lev,61,Female,702.4,No,No,No,Moderate,Serosa,NA,1,0,1814,Yes +825,hospital_4,Lev,77,Female,700.8,Yes,No,Yes,Moderate,Serosa,Good,3,0,2161,Yes +826,hospital_5,Obs,48,Female,700.8,Yes,No,No,Moderate,Serosa,Bad,5,1,506,No +827,hospital_2,Obs,77,Male,699.2,No,No,No,Well,Serosa,Bad,3,1,1482,Yes +828,hospital_3,Lev,69,Male,692.8,No,No,No,Poor,Serosa,Good,10,0,1964,Yes +829,hospital_5,Lev,36,Female,688,No,No,No,Poor,Serosa,Bad,17,1,693,Yes +830,hospital_3,Lev,64,Female,688,No,No,Yes,Moderate,Serosa,Bad,4,1,592,Yes +831,hospital_2,Lev,70,Male,684.8,No,No,No,Moderate,Muscle,Good,1,0,2207,Yes +832,hospital_1,Lev,74,Female,675.2,No,No,No,Well,Serosa,Good,3,0,2181,Yes +833,hospital_5,Lev,63,Male,673.6,No,No,No,Poor,Serosa,Bad,9,1,696,Yes +834,hospital_5,Lev,52,Female,672,No,No,No,Poor,Serosa,Bad,10,1,257,Yes +835,hospital_5,Lev,54,Female,667.2,No,No,No,Moderate,Serosa,Good,3,1,2171,Yes +836,hospital_4,Lev,54,Female,660.8,Yes,No,No,Moderate,Serosa,Good,4,0,2209,Yes +837,hospital_5,Lev,41,Female,660.8,Yes,No,No,Well,Serosa,Bad,1,1,1122,No +838,hospital_5,Obs,61,Female,657.6,No,No,No,Moderate,Serosa,Bad,4,1,936,Yes +839,hospital_5,Lev,34,Female,654.4,Yes,No,No,Poor,Serosa,Bad,10,1,601,Yes +840,hospital_1,Obs,59,Female,649.6,Yes,No,No,Moderate,Serosa,Good,3,0,2265,Yes +841,hospital_1,Lev,57,Female,643.2,No,No,No,Moderate,Serosa,Good,3,0,2198,Yes +842,hospital_5,Obs,39,Female,640,No,No,No,Moderate,Muscle,Bad,6,1,275,Yes +843,hospital_3,Obs,74,Male,624,No,No,No,Poor,Serosa,Bad,3,1,1195,Yes +844,hospital_4,Lev,45,Male,622.4,Yes,No,No,Moderate,Serosa,Good,3,0,2099,No +845,hospital_1,Lev,66,Female,614.4,No,No,No,Moderate,Serosa,Good,1,0,2165,Yes +846,hospital_4,Lev,60,Male,614.4,No,No,No,Moderate,Serosa,Good,2,0,2212,No +847,hospital_5,Lev,73,Male,611.2,No,No,No,Moderate,Serosa,Bad,1,1,355,No +848,hospital_1,Obs,76,Female,609.6,No,No,No,Poor,Muscle,Good,1,0,2097,Yes +849,hospital_2,Lev,79,Female,601.6,Yes,No,No,Moderate,Serosa,Bad,1,1,56,Yes +850,hospital_5,Lev,47,Male,595.2,Yes,No,No,Moderate,Serosa,Bad,4,1,589,No +851,hospital_5,Obs,60,Male,585.6,No,No,No,Moderate,Serosa,Bad,9,1,510,Yes +852,hospital_1,Lev,62,Female,584,No,No,No,Moderate,Serosa,Good,3,0,2250,No +853,hospital_5,Obs,18,Male,580.8,Yes,No,Yes,Poor,Muscle,Bad,4,1,612,No +854,hospital_4,Lev,75,Female,579.2,No,No,No,Moderate,Serosa,Good,5,0,2284,Yes +855,hospital_2,Lev,56,Female,569.6,No,No,No,Well,Serosa,Good,3,0,1992,No +856,hospital_4,Lev,70,Male,568,Yes,No,No,Moderate,Muscle,Bad,5,1,251,Yes +857,hospital_2,Lev,54,Female,568,No,No,No,NA,Muscle,Good,3,0,2070,Yes +858,hospital_5,Obs,64,Female,558.4,No,No,No,Moderate,Serosa,Bad,1,1,1209,No +859,hospital_3,Lev,63,Female,548.8,No,No,No,Moderate,Serosa,Good,1,0,2122,Yes +860,hospital_3,Lev,52,Female,547.2,Yes,No,No,Well,Serosa,Good,2,0,2111,No +861,hospital_5,Lev,71,Female,544,No,No,Yes,Moderate,Serosa,Bad,11,1,274,No +862,hospital_3,Lev,54,Female,529.6,No,No,No,Well,Serosa,Bad,1,1,1306,No +863,hospital_3,Lev,27,Female,521.6,No,No,No,Poor,Muscle,Bad,1,1,1325,Yes +864,hospital_2,Obs,68,Male,518.4,No,No,Yes,Moderate,Serosa,Good,10,0,1968,Yes +865,hospital_4,Obs,49,Female,516.8,No,No,No,Moderate,Serosa,Bad,2,1,753,No +866,hospital_4,Obs,61,Male,515.2,No,No,Yes,Moderate,Adjacent structures,Bad,2,1,760,Yes +867,hospital_2,Lev,40,Male,505.6,No,No,No,Moderate,Serosa,Good,16,0,1861,Yes +868,hospital_5,Lev,38,Male,502.4,No,No,No,Well,Serosa,Bad,3,1,1138,Yes +869,hospital_1,Obs,56,Female,502.4,No,No,No,Moderate,Muscle,Good,2,0,2167,Yes +870,hospital_4,Lev,79,Male,500.8,Yes,No,No,Moderate,Serosa,Good,1,0,1944,Yes +871,hospital_4,Obs,55,Female,497.6,No,No,No,Poor,Serosa,Bad,13,1,372,No +872,hospital_4,Obs,59,Female,486.4,No,No,No,Moderate,Submucosa,NA,1,0,1792,No +873,hospital_5,Lev,36,Male,483.2,No,No,Yes,Moderate,Serosa,Bad,4,1,986,Yes +874,hospital_4,Lev,63,Female,468.8,Yes,No,No,Moderate,Serosa,Good,2,0,2378,Yes +875,hospital_5,Obs,27,Male,462.4,No,Yes,Yes,Moderate,Serosa,Bad,12,1,390,Yes +876,hospital_5,Lev,66,Female,452.8,No,No,Yes,Moderate,Muscle,Bad,2,1,642,Yes +877,hospital_3,Lev,63,Male,452.8,No,No,No,Moderate,Serosa,Good,3,0,2345,Yes +878,hospital_4,Lev,64,Male,446.4,No,No,No,Moderate,Muscle,Good,2,0,2254,No +879,hospital_1,Obs,78,Female,441.6,No,No,No,Moderate,Serosa,Good,1,0,2118,Yes +880,hospital_5,Lev,66,Female,440,Yes,No,No,Moderate,Serosa,Good,2,1,1831,Yes +881,hospital_2,Obs,64,Female,438.4,No,No,No,Poor,Serosa,Good,3,0,2167,Yes +882,hospital_4,Obs,68,Male,433.6,No,No,No,Moderate,Serosa,Bad,2,1,1198,Yes +883,hospital_2,Lev,35,Male,430.4,No,No,Yes,Moderate,Serosa,Good,2,0,2050,No +884,hospital_4,Lev,64,Male,422.4,No,No,Yes,Poor,Serosa,Bad,2,1,271,Yes +885,hospital_1,Lev,60,Female,414.4,No,No,No,Moderate,Muscle,Good,2,0,2138,Yes +886,hospital_3,Obs,55,Female,414.4,Yes,No,No,Moderate,Serosa,Good,1,0,1891,Yes +887,hospital_5,Obs,39,Male,411.2,No,No,No,Moderate,Serosa,Bad,6,1,1313,Yes +888,hospital_3,Lev,67,Male,404.8,No,No,No,Moderate,Serosa,Good,3,0,1853,Yes +889,hospital_1,Lev,55,Male,401.6,Yes,No,No,Poor,Serosa,Good,3,0,2130,Yes +890,hospital_5,Lev,61,Male,387.2,No,No,No,Moderate,Serosa,Bad,8,1,150,No +891,hospital_5,Lev,67,Female,385.6,No,No,No,Moderate,Serosa,Bad,6,1,759,Yes +892,hospital_3,Lev,62,Male,380.8,No,No,No,Moderate,Serosa,Good,1,0,2100,Yes +893,hospital_1,Lev,52,Female,371.2,No,No,No,Moderate,Serosa,Good,4,0,2101,Yes +894,hospital_5,Lev,80,Male,361.6,No,No,No,Moderate,Serosa,Bad,1,1,942,Yes +895,hospital_4,Obs,51,Female,355.2,No,No,No,Moderate,Serosa,NA,11,0,1823,Yes +896,hospital_5,Obs,74,Male,350.4,No,No,No,Poor,Submucosa,Bad,1,1,665,No +897,hospital_5,Obs,70,Male,350.4,Yes,Yes,Yes,Moderate,Serosa,Bad,4,1,1656,Yes +898,hospital_1,Lev,73,Male,348.8,No,No,No,Moderate,Serosa,Good,4,0,1969,Yes +899,hospital_3,Lev,56,Female,344,No,No,No,Poor,Adjacent structures,Good,3,0,2190,No +900,hospital_5,Obs,70,Female,332.8,Yes,No,No,Moderate,Serosa,Bad,15,1,576,Yes +901,hospital_5,Lev,68,Male,329.6,No,No,No,Moderate,Serosa,Bad,12,1,1103,Yes +902,hospital_5,Lev,51,Male,321.6,No,No,Yes,Poor,Serosa,Bad,2,1,1046,Yes +903,hospital_1,Lev,56,Female,305.6,No,No,No,Moderate,Serosa,Good,3,0,1929,Yes +904,hospital_5,Obs,71,Male,299.2,No,No,No,Well,Serosa,Bad,10,1,125,Yes +905,hospital_2,Obs,63,Female,297.6,No,No,No,Well,Serosa,Bad,2,1,187,Yes +906,hospital_2,Lev,82,Male,273.6,NA,No,No,Moderate,Serosa,Bad,3,1,939,Yes +907,hospital_4,Obs,68,Female,273.6,No,No,No,Poor,Serosa,Bad,12,1,887,No +908,hospital_2,Obs,55,Female,265.6,No,No,No,Moderate,Serosa,NA,2,0,1803,No +909,hospital_1,Lev,71,Male,264,No,No,No,Moderate,Serosa,Good,1,0,2018,Yes +910,hospital_5,Lev,68,Female,262.4,No,No,Yes,Moderate,Serosa,Bad,12,1,1509,Yes +911,hospital_5,Lev,60,Male,240,No,No,No,Moderate,Serosa,Bad,13,1,314,No +912,hospital_1,Lev,72,Male,232,No,No,No,Well,Serosa,Good,3,0,1971,Yes +913,hospital_2,Lev,69,Male,230.4,Yes,Yes,Yes,Moderate,Serosa,Good,3,0,1827,Yes +914,hospital_5,Obs,46,Female,225.6,Yes,No,No,Moderate,Muscle,Bad,3,1,1079,No +915,hospital_4,Lev,42,Female,220.8,No,No,No,Well,Serosa,Good,6,0,2114,Yes +916,hospital_5,Obs,37,Female,212.8,No,No,No,Moderate,Serosa,Bad,8,1,1262,Yes +917,hospital_4,Obs,71,Female,206.4,No,No,No,Poor,Serosa,Bad,5,1,259,Yes +918,hospital_3,Lev,50,Male,203.2,No,No,No,Moderate,Muscle,Bad,7,1,323,No +919,hospital_5,Lev,70,Female,200,Yes,No,Yes,Moderate,Muscle,Bad,1,1,678,Yes +920,hospital_4,Lev,70,Female,195.2,No,No,Yes,Moderate,Muscle,Good,5,0,1827,Yes +921,hospital_5,Lev,58,Male,180.8,Yes,No,No,Moderate,Adjacent structures,Bad,3,1,1399,No +922,hospital_4,Lev,70,Female,148.8,No,No,No,Moderate,Serosa,Bad,1,1,1022,Yes +923,hospital_4,Lev,55,Male,126.4,Yes,No,No,Poor,Serosa,Good,2,0,2240,Yes +924,hospital_1,Obs,64,Male,89.6,Yes,No,Yes,Poor,Serosa,Good,2,0,2158,Yes +925,hospital_4,Lev,71,Male,83.2,No,No,Yes,Moderate,Serosa,Good,4,0,1875,Yes +926,hospital_2,Lev,72,Female,72,No,No,No,Moderate,Serosa,Good,1,0,2154,Yes +927,hospital_2,Lev,76,Male,54.4,No,No,Yes,Poor,Serosa,Bad,1,1,1018,Yes +928,hospital_2,Lev,48,Female,38.4,Yes,No,No,Moderate,Serosa,Good,4,0,2072,No +929,hospital_2,Lev,66,Female,36.8,Yes,No,No,Moderate,Serosa,NA,1,0,1820,Yes diff --git a/data/cancer.xlsx b/data/cancer.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..4680846ad2e6891c7436871e37e40a64d7cec393 GIT binary patch literal 28041 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 literal 0 HcmV?d00001 diff --git a/radiant-master/DESCRIPTION b/radiant-master/DESCRIPTION index d4f05fe..beb0420 100644 --- a/radiant-master/DESCRIPTION +++ b/radiant-master/DESCRIPTION @@ -14,7 +14,8 @@ Depends: radiant.design (>= 1.6.6), radiant.basics (>= 1.6.6), radiant.model (>= 1.6.6), - radiant.multivariate (>= 1.6.6) + radiant.multivariate (>= 1.6.6), + radiant.quickgen Imports: shiny (>= 1.8.1), import (>= 1.1.0), diff --git a/radiant-master/inst/app/global.R b/radiant-master/inst/app/global.R index 58acd78..1a1e7b7 100644 --- a/radiant-master/inst/app/global.R +++ b/radiant-master/inst/app/global.R @@ -42,7 +42,6 @@ source(file.path(getOption("radiant.path.design"), "app/init.R"), encoding = get source(file.path(getOption("radiant.path.basics"), "app/init.R"), encoding = getOption("radiant.encoding"), local = TRUE) source(file.path(getOption("radiant.path.model"), "app/init.R"), encoding = getOption("radiant.encoding"), local = TRUE) source(file.path(getOption("radiant.path.multivariate"), "app/init.R"), encoding = getOption("radiant.encoding"), local = TRUE) -# 添加quickgen模块的init.R source(file.path(getOption("radiant.path.quickgen"), "app/init.R"), encoding = getOption("radiant.encoding"), local = TRUE) options(radiant.url.patterns = make_url_patterns()) diff --git a/radiant-master/inst/translations/translation_zh.csv b/radiant-master/inst/translations/translation_zh.csv index d59a979..f487706 100644 --- a/radiant-master/inst/translations/translation_zh.csv +++ b/radiant-master/inst/translations/translation_zh.csv @@ -20,7 +20,7 @@ Sample size:,样本大小:,"clt_ui.R,sampling_ui.R" # of samples:,样本数量:,clt_ui.R Number of bins:,分箱数量:,"clt_ui.R,visualize_ui.R" Central Limit Theorem,中心极限定理,"clt_ui.R,init.R" -Basics > Probability,基础 > 概率,clt_ui.R +Basics > Probability,基础统计 > 概率,clt_ui.R Please choose a sample size larger than 2,请选择一个大于 2 的样本大小,clt_ui.R Please choose 2 or more samples,请选择 2 个或更多样本,clt_ui.R Please choose a minimum value for the uniform distribution,请为均匀分布选择一个最小值,clt_ui.R @@ -61,9 +61,9 @@ Wilcox,Wilcoxon 检验,compare_means_ui.R Select plots:,选择绘图类型:,compare_means_ui.R Select plots,选择绘图,compare_means_ui.R Compare means,均值比较,"compare_means_ui.R,init.R" -Summary,摘要,"compare_means_ui.R,doe_ui.R, randomizer_ui.R, sample_size_comp.R, sample_size_ui.R, sampling_ui.R,gbt_ui.R,conjoint_ui.R" -Plot,图形,"compare_means_ui.R,sample_size_comp.R,dtree_ui.R, gbt_ui.R,conjoint_ui.R" -Basics > Means,基础 > 均值,compare_means_ui.R +Summary,摘要,"compare_means_ui.R,doe_ui.R, randomizer_ui.R, sample_size_comp.R, sample_size_ui.R, sampling_ui.R,gbt_ui.R,conjoint_ui.R,crtree_ui.R,crs_ui.R" +Plot,图形,"compare_means_ui.R,sample_size_comp.R,dtree_ui.R, gbt_ui.R,conjoint_ui.R,crtree_ui.R,crs_ui.R" +Basics > Means,基础统计 > 均值,compare_means_ui.R "This analysis requires at least two variables. The first can be of type factor, numeric, or interval. The second must be of type numeric or interval. If these variable types are not available please select another dataset. @@ -72,7 +72,7 @@ If these variable types are not available please select another dataset. ",compare_means_ui.R Nothing to plot. Please select a plot type,没有可绘制的内容,请选择绘图类型,compare_means_ui.R Save compare means plot,保存均值比较图,compare_means_ui.R -Basics > Proportions,基础 > 比例,compare_props_ui.R +Basics > Proportions,基础统计 > 比例,compare_props_ui.R Compare proportions,比较比例,"compare_props_ui.R,init.R" "This analysis requires two categorical variables. The first must have two or more levels. The second can have only two levels. If these @@ -88,7 +88,7 @@ Pearson,皮尔逊积矩相关,correlation_ui.R Spearman,斯皮尔曼秩相关,correlation_ui.R Kendall,肯德尔秩相关,correlation_ui.R Calculate correlation,计算相关性,correlation_ui.R -Basics > Tables,基础 > 表格,correlation_ui.R +Basics > Tables,基础统计 > 表格,correlation_ui.R Correlation,相关性,"correlation_ui.R,init.R" Adjust for {factor} variables,针对 {factor} 变量进行调整,"correlation_ui.R,full_factor_ui.R" Calculate adjusted p.values,计算调整后的 p 值,correlation_ui.R @@ -252,7 +252,7 @@ Load data,加载数据,manage_ui.R Description,描述,manage_ui.R Paste,粘贴,manage_ui.R Copy data,复制数据,manage_ui.R -Save,保存,"manage_ui.R,logistic_ui.R,radiant.R" +Save,保存,"manage_ui.R,logistic_ui.R,radiant.R,quickgen_ai_ui.R" Save data,保存数据,manage_ui.R Save radiant state file,保存 Radiant 状态文件,"manage_ui.R,global.R" Add/edit data description,添加/编辑数据描述,manage_ui.R @@ -608,7 +608,7 @@ Estimate model,估计模型,"crs_ui.R, crtree_ui.R, gbt_ui.R, logistic_ui.R,conj Re-estimate model,重新估计模型,"crs_ui.R, crtree_ui.R, gbt_ui.R, logistic_ui.R,conjoint_ui.R" ,,crs_ui.R Collaborative Filtering,协同过滤,"crs_ui.R,init.R" -Model > Recommend,模型 > 推荐,crs_ui.R +Model > Recommend,模型方法 > 推荐,crs_ui.R "This analysis requires a user id, a product id, and product ratings. If these variables are not available please select another dataset. @@ -675,7 +675,7 @@ Save decision tree plot,保存决策树图,crtree_ui.R Generating predictions,正在生成预测,"crtree_ui.R, gbt_ui.R, logistic_ui.R,conjoint_ui.R" Generating prediction plot,正在生成预测图,"crtree_ui.R, gbt_ui.R, logistic_ui.R,conjoint_ui.R" Generating tree diagramm,正在生成树图,crtree_ui.R -Model > Estimate,模型 > 估计,"crtree_ui.R, logistic_ui.R" +Model > Estimate,模型方法 > 估计,"crtree_ui.R, logistic_ui.R" ** Press the Estimate button to estimate the model **,** 点击“估计模型”按钮来估计模型 **,"crtree_ui.R, gbt_ui.R,conjoint_ui.R" Please select one or more explanatory variables.,请选择一个或多个自变量。,"crtree_ui.R, gbt_ui.R, nn_ui.R" Max,最大化,dtree_ui.R @@ -689,7 +689,7 @@ Select decisions to evaluate,选择要评估的决策,dtree_ui.R ","",dtree_ui.R Step:,步长:,dtree_ui.R -Model,模型,"dtree_ui.R,init.R" +Model,模型方法,"dtree_ui.R,init.R" Decision analysis,决策分析,"dtree_ui.R,init.R" ,,dtree_ui.R ,,dtree_ui.R @@ -757,7 +757,7 @@ Save model evaluation plot,保存模型评估图,"evalbin_ui.R, evalreg_ui.R" Save confusion plots,保存混淆图,evalbin_ui.R Save uplift plots,保存提升图,evalbin_ui.R Evaluate,评估,"evalbin_ui.R,init.R" -Model > Evaluate,模型 > 评估,"evalbin_ui.R, evalreg_ui.R" +Model > Evaluate,模型方法 > 评估,"evalbin_ui.R, evalreg_ui.R" ** Press the Evaluate button to evaluate models **,** 请点击“评估”按钮以评估模型 **,"evalbin_ui.R, evalreg_ui.R" ,,evalbin_ui.R "This analysis requires a response variable of type factor and one or more @@ -784,7 +784,7 @@ Sub-sample:,子样本比例:,gbt_ui.R # rounds:,迭代轮数:,gbt_ui.R Early stopping:,提前停止:,gbt_ui.R Gradient Boosted Trees,梯度提升树,"gbt_ui.R,init.R" -Model > Trees,模型 > 树模型,gbt_ui.R +Model > Trees,模型方法 > 树模型,gbt_ui.R ** Select prediction input **,** 请选择预测输入 **,"gbt_ui.R, logistic_ui.R,conjoint_ui.R" ** Select data for prediction **,** 请选择用于预测的数据 **,"gbt_ui.R, logistic_ui.R,conjoint_ui.R" ** Enter prediction commands **,** 请输入预测命令 **,"gbt_ui.R, logistic_ui.R,conjoint_ui.R" @@ -796,7 +796,7 @@ Save gradient boosted trees prediction plot,保存梯度提升树预测图,gbt_u Save gradient boosted trees plot,保存梯度提升树图,gbt_ui.R This analysis requires a response variable with two levels and one\nor more explanatory variables. If these variables are not available\nplease select another dataset.\n\n,此分析需要一个具有两个水平的响应变量和一个\n或多个解释变量。如果这些变量不可用\n请选择其他数据集。\n\n,gbt_ui.R This analysis requires a response variable of type integer\nor numeric and one or more explanatory variables.\nIf these variables are not available please select another dataset.\n\n,此分析需要一个整数类型的响应变量\n或数值型,以及一个或多个解释变量。\n如果这些变量不可用,请选择其他数据集。\n\n,gbt_ui.R -Predict,预测,"gbt_ui.R,conjoint_ui.R" +Predict,预测,"gbt_ui.R,conjoint_ui.R,crtree_ui.R" Storing residuals,存储残差,logistic_ui.R Save coefficients,保存系数,logistic_ui.R Save logistic prediction plot,保存逻辑回归预测图,logistic_ui.R @@ -1090,7 +1090,7 @@ Radiant docs,Radiant文档,global.R Report issue,报告问题,global.R Design,设计,init.R Sample,样本,init.R -Basics,基础,init.R +Basics,基础统计,init.R Probability,概率,init.R Means,均值,init.R Proportions,比例,init.R @@ -1127,12 +1127,12 @@ Base dir:,根目录:,global.R Generate descriptive statistics with one click,一键生成描述性统计,"quickgen_basic_ui.R,init.R" Oneclick generation > Generate descriptive statistics,一键生成 > 生成描述性统计,quickgen_basic_ui.R Oneclick generation,一键生成,init.R -LLM generates descriptive statistics,大模型生成描述性统计,init.R +AI generates descriptive statistics,大模型生成描述性统计,"init.R,quickgen_ai_ui.R" Select All,全选,quickgen_basic_ui.R Deselect All,全不选,quickgen_basic_ui.R Invert,反选,quickgen_basic_ui.R Radiant screenshot,截图,radiant.R -Cancel,取消,radiant.R +Cancel,取消,"radiant.R,quickgen_ai_ui.R" Table,表格,quickgen_basic_ui.R OneClick table generation,一键成表,quickgen_basic_ui.R Select numeric variables,选择数值变量,quickgen_basic_ui.R @@ -1143,3 +1143,46 @@ Select X variable(s),选择X变量,quickgen_basic_ui.R No data available,暂无数据,quickgen_basic_ui.R No numerical variable available,无可用数值变量,quickgen_basic_ui.R ### Current data overview,### 当前数据概况,quickgen_basic_ui.R +Describe your analysis request:,描述您的分析请求:,quickgen_ai_ui.R +Oneclick generation > AI generates descriptive statistics,一键生成 > 大模型生成描述性统计,quickgen_ai_ui.R +AI assistant,AI助手,quickgen_ai_ui.R +Run code,运行,quickgen_ai_ui.R +Edit code,编辑,quickgen_ai_ui.R +Generated R code,生成的R代码,quickgen_ai_ui.R +Send,发送,quickgen_ai_ui.R +e. g. Please help me draw a scatter plot of diamonds prices and carats,e.g. 请帮我画一张 diamonds 价格与克拉的散点图,quickgen_ai_ui.R +Please enter an analysis request,请输入分析请求,quickgen_ai_ui.R +Save Changes,保存,quickgen_ai_ui.R +Edit R Code,编辑R代码,quickgen_ai_ui.R +Save AI-generated plot,保存大模型生成的图表,quickgen_ai_ui.R +Edit the generated R code here...,在此处编辑生成的R代码...,quickgen_ai_ui.R +Normality test,正态性检验,init.R +Homogeneity of variance test,方差齐性检验,init.R +Basics > Normality,基础统计 > 正态性,normality_test_ui.R +Shapiro-Wilk,SW 检验,normality_test_ui.R +Kolmogorov-Smirnov,K-S 检验,normality_test_ui.R +Anderson-Darling,AD 检验,normality_test_ui.R +Basics > Homogeneity,基础统计 > 方差齐性,homo_variance_test_ui.R +Grouping variable:,分组变量:,homo_variance_test_ui.R +Test method:,检验方法:,homo_variance_test_ui.R +Levene,莱文检验,homo_variance_test_ui.R +Bartlett,巴特利特检验,homo_variance_test_ui.R +Fligner,弗林格检验,homo_variance_test_ui.R +Cox Proportional Hazards Regression,比例风险回归,init.R +Support Vector Machine (SVM),支持向量机(SVM),init.R +Kernel:,核函数:,svm_ui.R +Linear,线性,svm_ui.R +Polynomial,多项式,svm_ui.R +Radial,径向基,svm_ui.R +Cost (C):,惩罚系数 (C):,svm_ui.R +Gamma:,伽马系数:,svm_ui.R +Coef0:,常数项:,svm_ui.R +Epsilon (tube):,Epsilon 间隔带:,svm_ui.R +Estimate class probabilities,估计类别概率,svm_ui.R +Choose Excel file:,选择Excel文件:,manage_ui.R +Sheet index (1-based):,工作表索引(从1开始):,manage_ui.R +First row as header,第一行为表头,manage_ui.R +Time variable:,生存时间变量:,cox_ui.R +Status variable:,事件状态变量:,cox_ui.R +AI running...,大模型运行中...,quickgen_ai_ui.R +Warning:Please enter a request related to descriptive statistics or visualization.,警告:请输入与描述性统计或可视化相关的请求。,quickgen_ai_ui.R diff --git a/radiant.quickgen/DESCRIPTION b/radiant.quickgen/DESCRIPTION index 9f58e63..425bf4c 100644 --- a/radiant.quickgen/DESCRIPTION +++ b/radiant.quickgen/DESCRIPTION @@ -2,3 +2,21 @@ Package: radiant.quickgen Version: 0.0.1 Title: Quick Generator table and chart for Radiant Description: Provides a simple data generator for the Radiant interface. +Depends: + R (>= 4.3.0), + radiant.data (>= 1.6.6) +Imports: + shiny (>= 1.8.1), + shiny.i18n, + httr2 (>= 1.0.0), + shinyjs, + shinyAce, + shinyWidgets(>= 0.8.0), + patchwork +Suggests: + testthat (>= 2.0.0), + pkgdown (>= 1.1.0), + markdown (>= 1.3) +Encoding: UTF-8 +Language: en-US +RoxygenNote: 7.3.2 diff --git a/radiant.quickgen/NAMESPACE b/radiant.quickgen/NAMESPACE new file mode 100644 index 0000000..907d611 --- /dev/null +++ b/radiant.quickgen/NAMESPACE @@ -0,0 +1,40 @@ +# Generated by roxygen2: do not edit by hand + +S3method(dtab,explore) +S3method(store,explore) +S3method(summary,explore) +export(ai_generate) +export(ai_get_data_call) +export(ai_run_code) +export(build_r_prompt) +export(chat_completion) +export(cv) +export(does_vary) +export(empty_level) +export(explore) +export(flip) +export(ln) +export(me) +export(meprop) +export(modal) +export(n_missing) +export(n_obs) +export(p01) +export(p025) +export(p05) +export(p10) +export(p25) +export(p75) +export(p90) +export(p95) +export(p975) +export(p99) +export(prop) +export(qscatter) +export(sdpop) +export(sdprop) +export(se) +export(seprop) +export(varpop) +export(varprop) +export(visualize) diff --git a/radiant.quickgen/R/quickgen_ai.R b/radiant.quickgen/R/quickgen_ai.R index 696fd7d..7107e9a 100644 --- a/radiant.quickgen/R/quickgen_ai.R +++ b/radiant.quickgen/R/quickgen_ai.R @@ -1,9 +1,98 @@ -#' 一键生成模块服务器逻辑 +# === 配置 === +MODELSCOPE_OPENAI_URL <- "https://api-inference.modelscope.cn/v1" +MODELSCOPE_API_KEY <- Sys.getenv("MODELSCOPE_API_KEY", "ms-b2746d72-f897-4faf-8089-89e5e511ed5a") +MODEL_ID <- "deepseek-ai/DeepSeek-V3.1" + +# === 低层封装:单次对话 === #' @export -quickgen_server <- function(input, output, session, r_data, r_info, r_state) { - # 为模块创建命名空间 - ns <- session$ns +chat_completion <- function(user_prompt, + max_tokens = 1500, + temperature = 0.3) { + req <- httr2::request(paste0(MODELSCOPE_OPENAI_URL, "/chat/completions")) %>% + httr2::req_headers( + "Authorization" = paste("Bearer", MODELSCOPE_API_KEY), + "Content-Type" = "application/json" + ) %>% + httr2::req_body_json(list( + model = MODEL_ID, + messages = list(list(role = "user", content = user_prompt)), + temperature = temperature, + max_tokens = max_tokens, + stream = FALSE + )) - # 空函数,确保模块能正确加载 - # 后续开发时可在此添加实际逻辑 + resp <- httr2::req_perform(req) + body <- httr2::resp_body_json(resp) + + if (is.null(body$choices[[1]]$message$content)) + stop("ModelScope API 返回空内容:", body) + + body$choices[[1]]$message$content +} + +# === 构造发给模型的 Prompt === +#' @export +build_r_prompt <- function(user_prompt, data_call) { + sprintf( + "你是 R 语言专家,必须严格遵守以下规则: + +〓 输出格式 〓 +- 只返回可运行 R 代码,用 ```r 包裹,禁止任何解释、注释、空行。 +- 若用户请求不符合下方【白名单】,一律返回空代码块(仅 ```r\n``` ),不对话。 + +〓 白名单关键词(必须至少出现 1 个)〓 +箱线图|柱状图|条形图|散点图|折线图|密度图|直方图|热图|森林图|瀑布图|饼图|气泡图|生存曲线|KM 曲线|ggsurvplot|tbl_summary|tableone|CreateTableOne|描述性统计|基线表|相关性|group comparison|distribution|ggplot|geom_|patchwork + +〓 否定示例(立即返回空块)〓 +- 仅输入:“图表”“表格”“画图”“来张图” +- 非医学/统计描述:笑话、故事、计算、翻译、写文章、写代码注释、解释概念、生成非 ggplot 图形(base、lattice) + +〓 技术细节 〓 +1. 数据集已读入:%s +2. 主题函数带括号:theme_minimal()、theme_bw() ... +3. 多张图用 patchwork 拼页。 +4. 包函数写全名,不得省略括号。 + +用户请求:%s", + data_call, user_prompt + ) +} + +#' @export +ai_generate <- function(prompt, dataset, envir = parent.frame()) { + data_call <- ai_get_data_call(dataset, envir) + sys_prompt <- build_r_prompt(prompt, data_call) + r_code <- try(chat_completion(sys_prompt), silent = TRUE) + if (inherits(r_code, "try-error")) + stop("AI API error: ", attr(r_code, "condition")$message) + + r_code <- gsub("(?s)```r\\s*|```", "", r_code, perl = TRUE) + r_code <- trimws(r_code) + + if (r_code == "") { + return(list(r_code = "", + type = "empty", + auto_run = FALSE)) + } + + r_code <- gsub("(theme_minimal|theme_bw|theme_classic|theme_gray|theme_void|theme_dark)\\b(?!\\s*\\()", + "\\1()", r_code, perl = TRUE) + r_code <- paste0(data_call, "\n", r_code) + + has_gg <- grepl("ggplot\\(|geom_", r_code) + has_tbl <- grepl("data\\.frame\\(|tibble\\(|tbl_summary|tableOne|CreateTableOne", r_code) + type <- if (has_gg) "plot" else if (has_tbl) "table" else "text" + list(r_code = r_code, type = type, auto_run = TRUE) +} + +#' @export +ai_get_data_call <- function(dataset, envir) { + df_name <- if (is_string(dataset)) dataset else deparse1(substitute(dataset)) + paste0("df <- eval(quote(get_data(\"", df_name, "\", envir = ", + deparse1(substitute(envir)), ")), envir = parent.frame())") +} + +#' @export +ai_run_code <- function(r_code, envir = parent.frame()) { + eval(parse(text = r_code), envir = envir) } \ No newline at end of file diff --git a/radiant.quickgen/R/quickgen_basic.R b/radiant.quickgen/R/quickgen_basic.R index 02da8b0..da304f7 100644 --- a/radiant.quickgen/R/quickgen_basic.R +++ b/radiant.quickgen/R/quickgen_basic.R @@ -1,4 +1,4 @@ - +#' @export explore <- function(dataset, vars = "", byvar = "", fun = c("mean", "sd"), top = "fun", tabfilt = "", tabsort = "", tabslice = "", nr = Inf, data_filter = "", arr = "", rows = NULL, @@ -171,7 +171,7 @@ explore <- function(dataset, vars = "", byvar = "", fun = c("mean", "sd"), ) %>% add_class("explore") } - +#' @export summary.explore <- function(object, dec = 3, ...) { cat("Explore\n") cat("Data :", object$df_name, "\n") @@ -209,7 +209,7 @@ summary.explore <- function(object, dec = 3, ...) { invisible() } - +#' @export store.explore <- function(dataset, object, name, ...) { if (missing(name)) { object$tab @@ -225,7 +225,7 @@ store.explore <- function(dataset, object, name, ...) { } } - +#' @export flip <- function(expl, top = "fun") { cvars <- expl$byvar %>% (function(x) if (is.empty(x[1])) character(0) else x) @@ -245,7 +245,7 @@ flip <- function(expl, top = "fun") { expl$tab } - +#' @export dtab.explore <- function(object, dec = 3, searchCols = NULL, order = NULL, pageLength = NULL, caption = NULL, ...) { @@ -330,31 +330,31 @@ dtab.explore <- function(object, dec = 3, searchCols = NULL, ## turn functions below into functional ... ########################################### - +#' @export n_obs <- function(x, ...) length(x) - +#' @export n_missing <- function(x, ...) sum(is.na(x)) - +#' @export p01 <- function(x, na.rm = TRUE) quantile(x, .01, na.rm = na.rm) - +#' @export p025 <- function(x, na.rm = TRUE) quantile(x, .025, na.rm = na.rm) - +#' @export p05 <- function(x, na.rm = TRUE) quantile(x, .05, na.rm = na.rm) - +#' @export p10 <- function(x, na.rm = TRUE) quantile(x, .1, na.rm = na.rm) - +#' @export p25 <- function(x, na.rm = TRUE) quantile(x, .25, na.rm = na.rm) - +#' @export p75 <- function(x, na.rm = TRUE) quantile(x, .75, na.rm = na.rm) - +#' @export p90 <- function(x, na.rm = TRUE) quantile(x, .90, na.rm = na.rm) - +#' @export p95 <- function(x, na.rm = TRUE) quantile(x, .95, na.rm = na.rm) - +#' @export p975 <- function(x, na.rm = TRUE) quantile(x, .975, na.rm = na.rm) - +#' @export p99 <- function(x, na.rm = TRUE) quantile(x, .99, na.rm = na.rm) - +#' @export cv <- function(x, na.rm = TRUE) { m <- mean(x, na.rm = na.rm) if (m == 0) { @@ -364,17 +364,17 @@ cv <- function(x, na.rm = TRUE) { sd(x, na.rm = na.rm) / m } } - +#' @export se <- function(x, na.rm = TRUE) { if (na.rm) x <- na.omit(x) sd(x) / sqrt(length(x)) } - +#' @export me <- function(x, conf_lev = 0.95, na.rm = TRUE) { if (na.rm) x <- na.omit(x) se(x) * qt(conf_lev / 2 + .5, length(x) - 1, lower.tail = TRUE) } - +#' @export prop <- function(x, na.rm = TRUE) { if (na.rm) x <- na.omit(x) if (is.numeric(x)) { @@ -387,36 +387,36 @@ prop <- function(x, na.rm = TRUE) { NA } } - +#' @export varprop <- function(x, na.rm = TRUE) { p <- prop(x, na.rm = na.rm) p * (1 - p) } - +#' @export sdprop <- function(x, na.rm = TRUE) sqrt(varprop(x, na.rm = na.rm)) - +#' @export seprop <- function(x, na.rm = TRUE) { if (na.rm) x <- na.omit(x) sqrt(varprop(x, na.rm = FALSE) / length(x)) } - +#' @export meprop <- function(x, conf_lev = 0.95, na.rm = TRUE) { if (na.rm) x <- na.omit(x) seprop(x) * qnorm(conf_lev / 2 + .5, lower.tail = TRUE) } - +#' @export varpop <- function(x, na.rm = TRUE) { if (na.rm) x <- na.omit(x) n <- length(x) var(x) * ((n - 1) / n) } - +#' @export sdpop <- function(x, na.rm = TRUE) sqrt(varpop(x, na.rm = na.rm)) - +#' @export ln <- function(x, na.rm = TRUE) { if (na.rm) log(na.omit(x)) else log(x) } - +#' @export does_vary <- function(x, na.rm = TRUE) { ## based on http://stackoverflow.com/questions/4752275/test-for-equality-among-all-elements-of-a-single-vector if (length(x) == 1L) { @@ -429,7 +429,7 @@ does_vary <- function(x, na.rm = TRUE) { } } } - +#' @export empty_level <- function(x) { if (!is.factor(x)) x <- as.factor(x) levs <- levels(x) @@ -443,7 +443,7 @@ empty_level <- function(x) { } x } - +#' @export modal <- function(x, na.rm = TRUE) { if (na.rm) x <- na.omit(x) unv <- unique(x) @@ -451,7 +451,7 @@ modal <- function(x, na.rm = TRUE) { } #—————————————————————————————————————————————————绘图部分——————————————————————————————————————————— - +#' @export visualize <- function(dataset, xvar, yvar = "", comby = FALSE, combx = FALSE, type = ifelse(is.empty(yvar), "dist", "scatter"), nrobs = -1, facet_row = ".", facet_col = ".", color = "none", fill = "none", @@ -1131,7 +1131,7 @@ visualize <- function(dataset, xvar, yvar = "", comby = FALSE, combx = FALSE, (function(x) if (isTRUE(shiny)) x else print(x)) } } - +#' @export qscatter <- function(dataset, xvar, yvar, lev = "", fun = "mean", bins = 20) { if (is.character(dataset[[yvar]])) { dataset <- mutate_at(dataset, .vars = yvar, .funs = as.factor) diff --git a/radiant.quickgen/inst/app/init.R b/radiant.quickgen/inst/app/init.R index 403e99a..636bf72 100644 --- a/radiant.quickgen/inst/app/init.R +++ b/radiant.quickgen/inst/app/init.R @@ -15,7 +15,7 @@ options( tags$script(src = "www_quickgen/js/run_return.js") ), tabPanel(i18n$t("Generate descriptive statistics with one click"), uiOutput("quickgen_basic")), - tabPanel(i18n$t("LLM generates descriptive statistics"), uiOutput("quickgen_ai")) + tabPanel(i18n$t("AI generates descriptive statistics"), uiOutput("quickgen_ai")) ) ) ) \ No newline at end of file diff --git a/radiant.quickgen/inst/app/tools/analysis/quickgen_ai_ui.R b/radiant.quickgen/inst/app/tools/analysis/quickgen_ai_ui.R index 86b2a99..72d9270 100644 --- a/radiant.quickgen/inst/app/tools/analysis/quickgen_ai_ui.R +++ b/radiant.quickgen/inst/app/tools/analysis/quickgen_ai_ui.R @@ -1,9 +1,295 @@ -#' 大模型生成描述性统计界面 -quickgen_ai_ui <- function() { +# quickgen_ai_ui.R +library(shinyjs) +library(shinyAce) + +## ==================== 右下角浮框 ==================== +ui_ai_progress <- tags$div( + id = "ai_progress_box", + style = "display:none; + position:fixed; + bottom:15px; right:15px; + width:220px; z-index:9999; + background:#f5f5f5; color:#333; + border:1px solid #337ab7; border-radius:4px; + padding:10px 15px; box-shadow:0 2px 8px rgba(0,0,0,.25);", + tags$strong(i18n$t("AI running...")), + tags$div(class = "progress", + tags$div(class = "progress-bar progress-bar-striped active", + style = "width:100%")) +) + +## ======== 警告弹窗======== +ui_ai_warn <- tags$div( + id = "ai_warn_box", + style = "display:none; + position:fixed; + bottom:15px; right:15px; + width:220px; z-index:9999; + background:#fff3cd; color:#856404; + border:1px solid #ffeaa7; border-radius:4px; + padding:10px 15px; box-shadow:0 2px 8px rgba(0,0,0,.25);", + tags$strong(i18n$t("Warning:Please enter a request related to descriptive statistics or visualization.")) +) + +## ==================== 统一入口 ==================== +output$quickgen_ai <- renderUI({ + stat_tab_panel( + menu = i18n$t("Oneclick generation > AI generates descriptive statistics"), + tool = i18n$t("AI generates descriptive statistics"), + tool_ui = "ai_main_ui", + output_panels = tabPanel( + title = i18n$t("AI assistant"), + value = "ai_panel", + uiOutput("ai_result_area") + ) + ) +}) + +## ==================== 右侧 AI 面板 ==================== +output$ai_main_ui <- renderUI({ tagList( - h3("大模型生成描述性统计"), - p("正在开发中...") + useShinyjs(), + ui_ai_progress, + ui_ai_warn, + wellPanel( + i18n$t("Describe your analysis request"), + returnTextAreaInput("ai_prompt", + label = NULL, + placeholder = i18n$t("e. g. Please help me draw a scatter plot of diamonds prices and carats"), + rows = 4, + value = state_init("ai_prompt", "")), + fluidRow( + column(6, uiOutput("ui_ai_submit")), + column(6, uiOutput("ai_loading")) + ) + ), + + wellPanel( + i18n$t("Generated R code"), + uiOutput("ai_r_code_block"), + fluidRow( + column(6, actionButton("ai_run_code", i18n$t("Run code"), icon = icon("play"), class = "btn-success")), + column(6, actionButton("ai_edit_code", i18n$t("Edit code"), icon = icon("edit"), class = "btn-default")) + ) + ), + + help_and_report( + modal_title = i18n$t("AI generates descriptive statistics"), + fun_name = "quickgen_ai", + help_file = inclMD(file.path(getOption("radiant.path.quickgen"), "app/tools/help/quickgen_ai.md")), + lic = "by-sa" + ) ) +}) + +## ==================== 控件渲染 ==================== +output$ui_ai_submit <- renderUI({ + req(input$dataset) + actionButton("ai_submit", i18n$t("Send"), icon = icon("magic"), class = "btn-primary") +}) + +output$ai_loading <- renderUI({ + if (isTRUE(r_values$ai_loading)) + tags$div(class = "progress", + tags$div(class = "progress-bar progress-bar-striped active", + style = "width:100%", + i18n$t("Calling AI model..."))) +}) + +## ==================== reactiveValues ==================== +r_values <- reactiveValues( + ai_r_code = "", + ai_result_type = "text", + ai_result_ready = FALSE, + ai_loading = FALSE +) + +## ==================== 生成代码 ==================== +observeEvent(input$ai_submit, { + if (is.empty(input$ai_prompt)) + return(showNotification(i18n$t("Please enter an analysis request"), type = "error")) + + r_values$ai_loading <- TRUE + shinyjs::show("ai_progress_box") # 显示右下角进度框 + on.exit({ + r_values$ai_loading <- FALSE + shinyjs::hide("ai_progress_box") # 无论成功失败都隐藏 + }) + + res <- try(do.call(ai_generate, + list(prompt = input$ai_prompt, + dataset = input$dataset, + envir = r_data)), + silent = TRUE) + if (inherits(res, "try-error")) { + showNotification(paste(i18n$t("AI API error:"), res), type = "error") + return() + } + + r_values$ai_r_code <- res$r_code + r_values$ai_result_type <- res$type + r_values$ai_result_ready <- FALSE + r_values$auto_run <- res$auto_run + + if (res$type == "empty") { + shinyjs::show("ai_warn_box") + shinyjs::delay(3000, shinyjs::hide("ai_warn_box")) + return() + } + + if (isTRUE(r_values$auto_run)) + shinyjs::click("ai_run_code") +}) + +## ==================== 显示 R 代码 ==================== +output$ai_r_code_block <- renderUI({ + codes <- r_values$ai_r_code + tags$pre(codes, style = "background:#f5f5f5; padding:10px; border-radius:4px; + font-family:monospace; white-space:pre-wrap; min-height:100px;") +}) + +## ==================== 运行代码 ==================== +observeEvent(input$ai_run_code, { + shinyjs::hide("ai_progress_box") + if (is.empty(r_values$ai_r_code)) return() + + if (trimws(r_values$ai_r_code) == "" || identical(r_values$ai_result_type, "empty")) { + shinyjs::show("ai_warn_box") + shinyjs::delay(3000, shinyjs::hide("ai_warn_box")) + return() + } + + tryCatch({ + result <- do.call(ai_run_code, + list(r_code = r_values$ai_r_code, envir = r_data)) + r_data$ai_temp_result <- result + + if (inherits(result, "gg") || inherits(result, "ggplot")) { + r_values$ai_result_type <- "plot" + output$ai_result_plot <- renderPlot(print(result)) + } else if (is.data.frame(result) || is.matrix(result)) { + r_values$ai_result_type <- "table" + output$ai_result_table <- DT::renderDataTable( + DT::datatable(result, options = list(scrollX = TRUE, pageLength = 10))) + } else { + r_values$ai_result_type <- "text" + output$ai_result_text <- renderText(capture.output(print(result))) + } + r_values$ai_result_ready <- TRUE + }, error = function(e) { + r_values$ai_result_type <- "error" + output$ai_result_error <- renderText(paste0(i18n$t("Error: "), e$message)) + r_values$ai_result_ready <- TRUE + showNotification(paste0(i18n$t("Run code error: "), e$message), + type = "error", duration = NULL) + }) +}, ignoreInit = TRUE) + +## ======== 结果展示区======== +output$ai_result_area <- renderUI({ + req(r_values$ai_result_ready) + tagList( + conditionalPanel( + condition = "output.ai_result_type == 'plot'", + download_link("dlp_ai_plot"), br(), + plotOutput("ai_result_plot", width = "100%", height = "500px") + ), + conditionalPanel( + condition = "output.ai_result_type == 'table'", + download_link("dlp_ai_table"), br(), + DT::dataTableOutput("ai_result_table") + ), + conditionalPanel( + condition = "output.ai_result_type == 'text' || output.ai_result_type == 'error'", + verbatimTextOutput("ai_result_text") + ) + ) +}) + + +output$ai_result_type <- reactive({ + r_values$ai_result_type +}) + +outputOptions(output, "ai_result_type", suspendWhenHidden = FALSE) + +## ==================== 编辑代码模态框 ==================== +observeEvent(input$ai_edit_code, { + showModal( + modalDialog( + title = i18n$t("Edit R Code"), + size = "l", + footer = tagList( + actionButton("ai_save_code", i18n$t("Save Changes"), class = "btn-primary"), + modalButton(i18n$t("Cancel")) + ), + aceEditor( + "ai_code_editor", + mode = "r", + theme = getOption("radiant.ace_theme", "tomorrow"), + wordWrap = TRUE, + value = r_values$ai_r_code, + placeholder = i18n$t("Edit the generated R code here..."), + vimKeyBinding = getOption("radiant.ace_vim.keys", FALSE), + tabSize = getOption("radiant.ace_tabSize", 2), + useSoftTabs = getOption("radiant.ace_useSoftTabs", TRUE), + showInvisibles = getOption("radiant.ace_showInvisibles", FALSE), + autoScrollEditorIntoView = TRUE, + minLines = 15, + maxLines = 30 + ) + ) + ) +}) + +## ==================== 保存代码 ==================== +observeEvent(input$ai_save_code, { + r_values$ai_r_code <- input$ai_code_editor + r_values$auto_run <- FALSE + removeModal() +}) + +## ==================== PNG 下载处理器 ==================== +dlp_ai_plot <- function(path) { + result <- r_data$ai_temp_result + if (inherits(result, "gg") || inherits(result, "ggplot")) { + png(path, width = 800, height = 500, res = 96) + print(result) + dev.off() + } else { + png(path, width = 400, height = 400) + plot(1, type = "n", axes = FALSE, xlab = "", ylab = "") + text(1, 1, "No plot available", cex = 1.5) + dev.off() + } +} +download_handler( + id = "dlp_ai_plot", + fun = dlp_ai_plot, + fn = function() paste0("plot_", Sys.Date()), + type = "png", + caption = i18n$t("Save AI-generated plot") +) + +# ======== 表格 CSV 下载处理器 ======== +dlp_ai_table <- function(path) { + result <- r_data$ai_temp_result + if (is.data.frame(result)) { + write.csv(result, file = path, row.names = FALSE) + } else { + write.csv(data.frame(msg = "No table available"), file = path, row.names = FALSE) + } } +download_handler( + id = "dlp_ai_table", + fun = dlp_ai_table, + fn = function() paste0("table_", Sys.Date()), + type = "csv", + caption = i18n$t("Save AI-generated table") +) -quickgen_ai_ui() \ No newline at end of file +## ==================== 报告 / 截图 ==================== +ai_report <- function() {} +observeEvent(input$ai_report, ai_report()) +observeEvent(input$ai_screenshot, radiant_screenshot_modal("modal_ai_screenshot")) +observeEvent(input$modal_ai_screenshot, { ai_report(); removeModal() }) \ No newline at end of file diff --git a/radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui .txt b/radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui .txt deleted file mode 100644 index 4540774..0000000 --- a/radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui .txt +++ /dev/null @@ -1,1115 +0,0 @@ -make_desc_text <- function(df) { - if (is.null(df) || nrow(df) == 0) return(i18n$t("No data available")) - ## 只保留数值列 - num_cols <- sapply(df, is.numeric) - if (sum(num_cols) == 0) return("No numerical variable available") - df_num <- df[, num_cols, drop = FALSE] - - buf <- c(i18n$t("### Current data overview")) - buf <- c(buf, sprintf("- **Sample size**:%d records", nrow(df))) - ## 连续变量 - for (v in names(df_num)) { - x <- df_num[[v]] - x <- x[!is.na(x)] - if (length(x) == 0) next - buf <- c(buf, sprintf( - "- **%s**: mean %.2f ± %.2f; median %.2f; range [%.2f, %.2f]; missing %.1f%%", - v, - mean(x), sd(x), median(x), min(x), max(x), - 100 * (1 - length(x) / nrow(df)) - )) - } - ## 分类变量 - cat_cols <- sapply(df, function(z) is.factor(z) || is.character(z)) - for (v in names(df)[cat_cols]) { - tbl <- table(df[[v]], useNA = "ifany") - lev_txt <- paste(sprintf("%s (%d, %.1f%%)", - names(tbl), tbl, - 100 * tbl / sum(tbl)), collapse = "、") - buf <- c(buf, sprintf("- **%s**:%s", v, lev_txt)) - } - paste(buf, collapse = "\n") -} - -## quickgen_basic 的形参列表 -default_funs <- c("n_obs", "mean", "sd", "min", "max") -qib_type <- c( - "分布图(dist)" = "dist", "密度图(density)" = "density", "散点图(scatter)" = "scatter", - "曲面图(surface)" = "surface", "折线图(line)" = "line", "条形图(bar)" = "bar", "箱线图(box)" = "box" -) -qib_check <- c( - "直线(line)" = "line", "局部加权回归(loess)" = "loess", - "抖动(jitter)" = "jitter", - "插值(interpolate)" = "interpolate" -) -qib_axes <- c( - "翻转坐标轴(flip)" = "flip", "X轴对数变换(log_x)" = "log_x", "Y轴对数变换(log_y)" = "log_y", - "Y轴缩放(scale_y)" = "scale_y", "密度(density)" = "density", "排序(sort)" = "sort" -) -qib_theme <- c( - "灰色主题(gray)" = "theme_gray", "黑白主题(bw)" = "theme_bw", - "明亮主题(light)" = "theme_light", "暗黑主题(dark)" = "theme_dark", - "极简主题(minimal)" = "theme_minimal", "经典主题(classic)" = "theme_classic" -) - -os_type <- Sys.info()["sysname"] -if (os_type == "Windows") { - fnt <- names(windowsFonts()) - names(fnt) <- tools::toTitleCase(fnt) - qib_base_family <- c("Theme default" = "", fnt) -} else { - qib_base_family <- c( - "Theme default" = "", "Helvetica" = "Helvetica", "Serif" = "serif", - "Sans" = "sans", "Mono" = "mono", "Courier" = "Courier", "Times" = "Times" - ) -} - -qib_labs <- c(i18n$t("title"), i18n$t("subtitle"), i18n$t("caption"), i18n$t("x"), i18n$t("y")) -qib_add_labs <- function() { - lab_list <- list() - for (l in qib_labs) { - inp <- input[[paste0("qib_labs_", l)]] - if (!is.empty(inp)) lab_list[[l]] <- inp - } - lab_list -} - -qgb_args <- as.list(formals(explore)) -qib_args <- as.list(formals(visualize)) - -## 收集用户输入的 reactive 列表 -qgb_inputs <- reactive({ - qgb_args$data_filter <- if (input$show_filter) input$data_filter else "" - qgb_args$arr <- if (input$show_filter) input$data_arrange else "" - qgb_args$rows <- if (input$show_filter) input$data_rows else "" - qgb_args$dataset <- input$dataset - - for (i in r_drop(names(qgb_args))) { - qgb_args[[i]] <- input[[paste0("qgb_", i)]] - } - qgb_args -}) - -qgb_sum_args <- as.list(if (exists("summary.explore")) { - formals(summary.explore) -} else { - formals(radiant.data:::summary.explore) -}) - -qib_inputs <- reactive({ - qib_args$data_filter <- if (isTRUE(input$show_filter)) input$data_filter else "" - qib_args$arr <- if (isTRUE(input$show_filter)) input$data_arrange else "" - qib_args$rows <- if (isTRUE(input$show_filter)) input$data_rows else "" - qib_args$dataset <- input$dataset - qib_args$shiny <- input$shiny - qib_args$labs <- qib_add_labs() - for (i in r_drop(names(qib_args), drop = c(i18n$t("dataset"), i18n$t("data_filter"), i18n$t("arr"), i18n$t("rows"), i18n$t("labs")))) { - qib_args[[i]] <- input[[paste0("qib_", i)]] - } - qib_args -}) - -## list of function inputs selected by user -qgb_sum_inputs <- reactive({ - ## loop needed because reactive values don't allow single bracket indexing - for (i in names(qgb_sum_args)) { - qgb_sum_args[[i]] <- input[[paste0("qgb_", i)]] - } - qgb_sum_args -}) - -## UI-elements -output$ui_qgb_vars <- renderUI({ - vars <- varnames() - req(available(vars)) - selectizeInput( - "qgb_vars", - label = i18n$t("Numeric variable(s):"), - choices = vars, - selected = state_multiple("qgb_vars", vars, isolate(input$qgb_vars)), - multiple = TRUE, - options = list( - placeholder = i18n$t("Select numeric variables"), - plugins = list("remove_button", "drag_drop") - ) - ) -}) - -output$ui_qgb_byvar <- renderUI({ - withProgress(message = i18n$t("Acquiring variable information"), value = 1, { - vars <- groupable_vars() - }) - req(available(vars)) - - if (any(vars %in% input$qgb_vars)) { - vars <- base::setdiff(vars, input$qgb_vars) - names(vars) <- varnames() %>% - (function(x) x[match(vars, x)]) %>% - names() - } - isolate({ - ## if nothing is selected expl_byvar is also null - if ("qgb_byvar" %in% names(input) && is.null(input$qgb_byvar)) { - r_state$qgb_byvar <<- NULL - } else { - if (available(r_state$qgb_byvar) && all(r_state$qgb_byvar %in% vars)) { - vars <- unique(c(r_state$qgb_byvar, vars)) - names(vars) <- varnames() %>% - (function(x) x[match(vars, x)]) %>% - names() - } - } - }) - selectizeInput( - "qgb_byvar", - label = i18n$t("Group by:"), choices = vars, - selected = state_multiple("qgb_byvar", vars, isolate(input$qgb_byvar)), - multiple = TRUE, - options = list( - placeholder = i18n$t("Select group-by variable"), - plugins = list("remove_button", "drag_drop") - ) - ) -}) - -output$ui_qgb_fun <- renderUI({ - r_funs <- getOption("radiant.functions") - selected <- isolate( - if (is.empty(input$qgb_fun)) default_funs else input$qgb_fun - ) - tagList( - div( - style = "margin-top: 5px; display: flex; gap: 3px; flex-wrap: wrap;", - actionButton("qgb_select_all", i18n$t("Select All"), - class = "btn-xs btn-primary", icon = icon("check-square")), - actionButton("qgb_deselect_all", i18n$t("Deselect All"), - class = "btn-xs btn-primary", icon = icon("square")), - actionButton("qgb_invert_selection", i18n$t("Invert"), - class = "btn-xs btn-primary", icon = icon("undo")) - ), - checkboxGroupInput( - inputId = "qgb_fun", - label = i18n$t("Apply function(s):"), - choices = r_funs, - selected = selected - ) - ) -}) - -output$ui_qgb_top <- renderUI({ - if (is.empty(input$qgb_vars)) { - return() - } - top_var <- setNames( - c("fun", "var", "byvar"), - c(i18n$t("Function"), i18n$t("Variables"), i18n$t("Group by")) - ) - if (is.empty(input$qgb_byvar)) top_var <- top_var[1:2] - selectizeInput( - "qgb_top", - label = i18n$t("Column header:"), - choices = top_var, - selected = state_single("qgb_top", top_var, isolate(input$qgb_top)), - multiple = FALSE - ) -}) - -output$ui_qgb_name <- renderUI({ - req(input$dataset) - textInput("qgb_name", i18n$t("Store as:"), "", placeholder = i18n$t("Provide a table name")) -}) - -output$ui_qgb_run <- renderUI({ - ## updates when dataset changes - req(input$dataset) - actionButton("qgb_run", i18n$t("OneClick table generation"), width = "100%", icon = icon("play", verify_fa = FALSE), class = "btn-success") -}) - -## add a spinning refresh icon if the table needs to be (re)calculated -run_refresh(qgb_args, "qgb", init = "vars", label = i18n$t("OneClick table generation"), relabel = i18n$t("Update table")) - -####################################### -# Visualize data -####################################### -output$ui_qib_type <- renderUI({ - selectInput( - inputId = "qib_type", label = i18n$t("Plot-type:"), choices = qib_type, - selected = state_single("qib_type", qib_type), - multiple = FALSE - ) -}) - -output$ui_qib_nrobs <- renderUI({ - req(input$qib_type == "scatter") - nrobs <- nrow(.get_data()) - choices <- c("1,000" = 1000, "5,000" = 5000, "10,000" = 10000, "All" = -1) %>% - .[. < nrobs] - selectInput( - "qib_nrobs", i18n$t("Number of data points plotted:"), - choices = choices, - selected = state_single("qib_nrobs", choices, 1000) - ) -}) - -## Y - variable -output$ui_qib_yvar <- renderUI({ - req(input$qib_type) - vars <- varying_vars() - req(available(vars)) - vars <- vars["date" != .get_class()[vars]] - if (input$qib_type %in% c("line", "bar", "scatter", "surface", "box")) { - vars <- vars["character" != .get_class()[vars]] - } - if (input$qib_type %in% c("box", "scatter")) { - vars <- vars["factor" != .get_class()[vars]] - } - - selectizeInput( - inputId = "qib_yvar", - label = i18n$t("Y-variable:"), - choices = vars, - selected = state_multiple("qib_yvar", vars, isolate(input$qib_yvar)), - multiple = TRUE, - options = list( - placeholder = i18n$t("Select Y variable(s)"), - plugins = list("remove_button", "drag_drop") - ) - ) -}) - -## X - variable -output$ui_qib_xvar <- renderUI({ - req(input$qib_type) - vars <- varying_vars() - req(available(vars)) - if (input$qib_type == "dist") vars <- vars["date" != .get_class()[vars]] - if (input$qib_type == "density") vars <- vars["factor" != .get_class()[vars]] - if (input$qib_type %in% c("box", "bar")) vars <- groupable_vars_nonum() - - selectizeInput( - inputId = "qib_xvar", - label = i18n$t("X-variable:"), - choices = vars, - selected = state_multiple("qib_xvar", vars, isolate(input$qib_xvar)), - multiple = TRUE, - options = list( - placeholder = i18n$t("Select X variable(s)"), - plugins = list("remove_button", "drag_drop") - ) - ) -}) - -output$ui_qib_comby <- renderUI({ - checkboxInput( - "qib_comby", i18n$t("Combine Y-variables in one plot"), - state_init("qib_comby", FALSE) - ) -}) - -output$ui_qib_combx <- renderUI({ - checkboxInput( - "qib_combx", i18n$t("Combine X-variables in one plot"), - state_init("qib_combx", FALSE) - ) -}) - -observeEvent(length(input$qib_xvar) < 2, { - updateCheckboxInput(session, "qib_combx", value = FALSE) -}) - -observeEvent(length(input$qib_yvar) < 2, { - updateCheckboxInput(session, "qib_comby", value = FALSE) -}) - -observeEvent(input$qib_type, { - if (input$qib_type %in% c("dist", "density")) { - updateCheckboxInput(session, "qib_comby", value = FALSE) - } else { - updateCheckboxInput(session, "qib_combx", value = FALSE) - } -}) - -observeEvent(input$qib_check, { - if (!"loess" %in% input$qib_check && input$qib_smooth != 1) { - updateSliderInput(session, "qib_smooth", value = 1) - } -}) - -# output$ui_qib_facet_row <- renderUI({ -# vars <- c("None" = ".", groupable_vars_nonum()) -# selectizeInput( -# "qib_facet_row", i18n$t("Facet row:"), vars, -# selected = state_single("qib_facet_row", vars, init = "."), -# multiple = FALSE -# ) -# }) - -# output$ui_qib_facet_col <- renderUI({ -# vars <- c("None" = ".", groupable_vars_nonum()) -# selectizeInput( -# "qib_facet_col", i18n$t("Facet column:"), vars, -# selected = state_single("qib_facet_col", vars, init = "."), -# multiple = FALSE -# ) -# }) - -# output$ui_qib_color <- renderUI({ -# req(input$qib_type) -# if (input$qib_type == "line") { -# vars <- c("None" = "none", groupable_vars()) -# } else { -# vars <- c("None" = "none", varnames()) -# } -# -# if (isTRUE(input$qib_comby) && length(input$qib_yvar) > 1) vars <- c("None" = "none") -# selectizeInput( -# "qib_color", i18n$t("Color:"), vars, -# multiple = FALSE, -# selected = state_single("qib_color", vars, init = "none") -# ) -# }) - -# output$ui_qib_fill <- renderUI({ -# vars <- c("None" = "none", groupable_vars()) -# if (isTRUE(input$qib_combx) && length(input$qib_xvar) > 1) vars <- vars[1] -# selectizeInput( -# "qib_fill", i18n$t("Fill:"), vars, -# multiple = FALSE, -# selected = state_single("qib_fill", vars, init = "none") -# ) -# }) - -# output$ui_qib_size <- renderUI({ -# req(input$qib_type) -# isNum <- .get_class() %in% c("integer", "numeric", "ts") -# vars <- c("None" = "none", varnames()[isNum]) -# if (isTRUE(input$qib_comby) && length(input$qib_yvar) > 1) vars <- c("None" = "none") -# selectizeInput( -# "qib_size", i18n$t("Size:"), vars, -# multiple = FALSE, -# selected = state_single("qib_size", vars, init = "none") -# ) -# }) - -output$ui_qib_axes <- renderUI({ - req(input$qib_type) - ind <- 1 - if (input$qib_type %in% c("line", "scatter", "surface")) { - ind <- 1:3 - } else if (input$qib_type == "dist") { - ind <- c(1:2, 5) - } else if (input$qib_type == "density") { - ind <- 1:2 - } else if (input$qib_type %in% c("bar", "box")) { - ind <- c(1, 3) - } - if (!is.empty(input$qib_facet_row, ".") || !is.empty(input$qib_facet_col, ".")) ind <- c(ind, 4) - if (input$qib_type == "bar") ind <- c(ind, 6) - - checkboxGroupInput( - "qib_axes", NULL, qib_axes[ind], - selected = state_group("qib_axes", ""), - inline = TRUE - ) -}) - -output$ui_qib_check <- renderUI({ - req(input$qib_type) - if (input$qib_type == "scatter") { - ind <- 1:3 - } else if (input$qib_type == "box") { - ind <- 3 - } else if (input$qib_type == "surface") { - ind <- 4 - } else { - ind <- c() - } - - if (!input$qib_type %in% c("scatter", "box")) { - r_state$qib_check <<- gsub("jitter", "", r_state$qib_check) - } - if (input$qib_type != "scatter") { - r_state$qib_check <<- gsub("line", "", r_state$qib_check) - r_state$qib_check <<- gsub("loess", "", r_state$qib_check) - } - - checkboxGroupInput( - "qib_check", NULL, qib_check[ind], - selected = state_group("qib_check", ""), - inline = TRUE - ) -}) - -output$ui_qib_run <- renderUI({ - req(input$dataset) - actionButton("qib_run", i18n$t("OneClick chart generation"), width = "100%", icon = icon("play", verify_fa = FALSE), class = "btn-success") -}) - -# output$ui_qib_labs <- renderUI({ -# ## updates when dataset changes -# req(input$dataset) -# wellPanel( -# textAreaInput("qib_labs_title", NULL, "", placeholder = i18n$t("Title"), rows = 1), -# textAreaInput("qib_labs_subtitle", NULL, "", placeholder = i18n$t("Subtitle"), rows = 1), -# textAreaInput("qib_labs_caption", NULL, "", placeholder = i18n$t("Caption"), rows = 1), -# textAreaInput("qib_labs_y", NULL, "", placeholder = i18n$t("Y-label"), rows = 1), -# textAreaInput("qib_labs_x", NULL, "", placeholder = i18n$t("X-label"), rows = 1) -# ) -# }) - -output$ui_qib_colors <- renderUI({ - tagList( - conditionalPanel( - condition = "input.qib_type == 'bar' || - input.qib_type == 'dist' || - input.qib_type == 'box' || - input.qib_type == 'density'", - selectInput( - "qib_fillcol", i18n$t("Fill color:"), - choices = colors(), - selected = state_single("qib_fillcol", colors(), "blue") - ) - ), - conditionalPanel( - condition = "input.qib_type == 'dist' || - input.qib_type == 'density' || - input.qib_type == 'box' || - input.qib_type == 'scatter' || - input.qib_type == 'line'", - selectInput( - "qib_linecol", i18n$t("Line color:"), - choices = colors(), - selected = state_single("qib_linecol", colors(), "black") - ) - ), - conditionalPanel( - condition = "input.qib_type == 'scatter' || - input.qib_type == 'line' || - input.qib_type == 'box'", - selectInput( - "qib_pointcol", i18n$t("Point color:"), - choices = colors(), - selected = state_single("qib_pointcol", colors(), "black") - ) - ) - ) -}) - -run_refresh( - qib_args, "qib", - init = c("xvar", "yvar"), label = i18n$t("OneClick chart generation"), relabel = i18n$t("Update plot"), - inputs = c("labs_title", "labs_subtitle", "labs_caption", "labs_y", "labs_x") -) - - -output$ui_quickgen_basic <- renderUI({ - tagList( - wellPanel( - uiOutput("ui_qgb_run") - ), - checkboxInput("qgb_details_table", i18n$t("Table"), state_init("qgb_details_table", FALSE)), - conditionalPanel( - "input.qgb_details_table == true", - wellPanel( - uiOutput("ui_qgb_vars"), - uiOutput("ui_qgb_byvar"), - uiOutput("ui_qgb_top"), - # returnTextAreaInput("qgb_tab_slice", - # label = i18n$t("Table slice (rows):"), - # rows = 1, - # value = state_init("qgb_tab_slice"), - # placeholder = i18n$t("e.g., 1:5 and press return") - # ), - uiOutput("ui_qgb_fun"), - numericInput("qgb_dec", label = i18n$t("Decimals:"), value = state_init("qgb_dec", 3), min = 0), - tags$table( - tags$td(uiOutput("ui_qgb_name")), - tags$td(actionButton("qgb_store", i18n$t("Store"), icon = icon("plus", verify_fa = FALSE)), class = "top") - ) - ), - ), - wellPanel( - uiOutput("ui_qib_run") - ), - checkboxInput("qib_details_chart", i18n$t("Chart"), state_init("qib_details_chart", FALSE)), - conditionalPanel( - "input.qib_details_chart == true", - wellPanel( - uiOutput("ui_qib_type"), - conditionalPanel( - "input.qib_type == 'scatter'", - uiOutput("ui_qib_nrobs") - ), - conditionalPanel( - condition = "input.qib_type != 'dist' && input.qib_type != 'density'", - uiOutput("ui_qib_yvar"), - conditionalPanel( - "input.qib_yvar != undefined && input.qib_yvar != null && input.qib_yvar.length > 1", - uiOutput("ui_qib_comby") - ) - ), - uiOutput("ui_qib_xvar"), - conditionalPanel( - "input.qib_type == 'dist' || input.qib_type == 'density'", - conditionalPanel( - "input.qib_xvar != undefined && input.qib_xvar != null && input.qib_xvar.length > 1", - uiOutput("ui_qib_combx") - ) - ), - # uiOutput("ui_qib_facet_row"), - # uiOutput("ui_qib_facet_col"), - # conditionalPanel( - # condition = "input.qib_type == 'bar' || - # input.qib_type == 'dist' || - # input.qib_type == 'density' || - # input.qib_type == 'surface'", - # uiOutput("ui_qib_fill") - # ), - # conditionalPanel( - # condition = "input.qib_type == 'scatter' || - # input.qib_type == 'line' || - # input.qib_type == 'box'", - # uiOutput("ui_qib_color") - # ), - # conditionalPanel( - # condition = "input.qib_type == 'scatter'", - # uiOutput("ui_qib_size") - # ), - conditionalPanel( - condition = "input.qib_type == 'bar' || - input.qib_type == 'scatter' || - input.qib_type == 'line'", - selectInput( - "qib_fun", i18n$t("Function:"), - choices = getOption("radiant.functions"), - selected = state_single("qib_fun", getOption("radiant.functions"), "mean") - ) - ), - # conditionalPanel( - # condition = "input.qib_type == 'scatter' || - # input.qib_type == 'line' || - # input.qib_type == 'surface' || - # input.qib_type == 'box'", - # uiOutput("ui_qib_check") - # ), - # uiOutput("ui_qib_axes"), - conditionalPanel( - condition = "input.qib_type == 'dist'", - sliderInput( - "qib_bins", - label = i18n$t("Number of bins:"), - value = state_init("qib_bins", 10), - min = 2, max = 50, step = 1 - ) - ), - conditionalPanel( - "input.qib_type == 'density' || - input.qib_type == 'dist' && (input.qib_axes && input.qib_axes.indexOf('density')) >= 0 || - (input.qib_type == 'scatter' && (input.qib_check && input.qib_check.indexOf('loess') >= 0))", - sliderInput( - "qib_smooth", - label = i18n$t("Smooth:"), - value = state_init("qib_smooth", 1), - min = 0.1, max = 3, step = .1 - ) - ) - ) - ), - # checkboxInput("qib_details_labels", i18n$t("Labels"), state_init("qib_details_labels", FALSE)), - # conditionalPanel( - # "input.qib_details_labels == true", - # uiOutput("ui_qib_labs") - # ), - checkboxInput("qib_details_style", i18n$t("Style"), state_init("qib_details_style", FALSE)), - conditionalPanel( - "input.qib_details_style == true", - wellPanel( - selectInput( - "qib_theme", i18n$t("Plot theme:"), - choices = qib_theme, - selected = state_single("qib_theme", qib_theme, "theme_gray") - ), - numericInput( - "qib_base_size", i18n$t("Base font size:"), - value = state_init("qib_base_size", 11) - ), - selectInput( - "qib_base_family", i18n$t("Font family:"), - choices = qib_base_family, - selected = state_single("qib_base_family", qib_base_family, "helvetica") - ), - uiOutput("ui_qib_colors"), - sliderInput( - "qib_alpha", - label = i18n$t("Opacity:"), - value = state_init("qib_alpha", .5), - min = 0, max = 1, step = .01 - ), - tags$table( - tags$td( - numericInput( - "qib_plot_height", - label = i18n$t("Plot height:"), min = 100, - max = 2000, step = 50, - value = state_init("qib_plot_height", r_info[["plot_height"]]), - width = "117px" - ) - ), - tags$td( - numericInput( - "qib_plot_width", - label = i18n$t("Plot width:"), min = 100, - max = 2000, step = 50, - value = state_init("qib_plot_width", r_info[["plot_width"]]), - width = "117px" - ), - width = "100%" - ) - ) - ) - ), - help_and_report( - modal_title = i18n$t("Generate descriptive statistics with one click"), fun_name = "quickgen_basic", - help_file = inclMD(file.path(getOption("radiant.path.quickgen"), "app/tools/help/quickgen_basic.md")), - lic = "by-sa" - ) - ) -}) - -qib_plot_width <- reactive({ - if (is.empty(input$qib_plot_width)) r_info[["plot_width"]] else input$qib_plot_width -}) - -qib_plot_height <- eventReactive( - { - input$qib_run - input$qib_plot_height - input$qib_plot_width - }, - { - if (is.empty(input$qib_plot_height)) { - r_info[["plot_height"]] - } else { - lx <- ifelse(not_available(input$qib_xvar) || isTRUE(input$qib_combx), 1, length(input$qib_xvar)) - ly <- ifelse(not_available(input$qib_yvar) || input$qib_type %in% c("dist", "density") || - isTRUE(input$qib_comby), 1, length(input$qib_yvar)) - nr <- lx * ly - if (nr > 1) { - (input$qib_plot_height / 2) * ceiling(nr / 2) - } else { - input$qib_plot_height - } - } - } -) - -.quickgen <- eventReactive(input$qgb_run, { - if (not_available(input$qgb_vars) || is.null(input$qgb_top)) { - return() - } else if (!is.empty(input$qgb_byvar) && not_available(input$qgb_byvar)) { - return() - } else if (available(input$qgb_byvar) && any(input$qgb_byvar %in% input$qgb_vars)) { - return() - } - qgbi <- qgb_inputs() - qgbi$envir <- r_data - sshhr(do.call(explore, qgbi)) -}) - -observeEvent(input$qgb_search_columns, { - r_state$qgb_search_columns <<- input$qgb_search_columns -}) - -observeEvent(input$qgb_state, { - r_state$qgb_state <<- input$qgb_state -}) - - -qgb_reset <- function(var, ncol) { - if (!identical(r_state[[var]], input[[var]])) { - r_state[[var]] <<- input[[var]] - r_state$qgb_state <<- list() - r_state$qgb_search_columns <<- rep("", ncol) - } -} - -output$qgb_tab <- DT::renderDataTable({ - input$qgb_run - withProgress(message = i18n$t("Generating explore table"), value = 1, { - isolate({ - qgb <- .quickgen() - req(!is.null(qgb)) - qgb$shiny <- TRUE - - ## resetting DT when changes occur - nc <- ncol(qgb$tab) - qgb_reset("qgb_vars", nc) - qgb_reset("qgb_byvar", nc) - qgb_reset("qgb_fun", nc) - if (!is.null(r_state$qgb_top) && - !is.null(input$qgb_top) && - !identical(r_state$qgb_top, input$qgb_top)) { - r_state$qgb_top <<- input$qgb_top - r_state$qgb_state <<- list() - r_state$qgb_search_columns <<- rep("", nc) - } - - searchCols <- lapply(r_state$qgb_search_columns, function(x) list(search = x)) - order <- r_state$qgb_state$order - pageLength <- r_state$qgb_state$length - }) - - caption <- if (is.empty(input$qgb_tab_slice)) NULL else glue("Table slice {input$expl_tab_slice} will be applied on Download, Store, or Report") - dtab( - qgb, - dec = input$qgb_dec, searchCols = searchCols, order = order, - pageLength = pageLength, - caption = caption - ) - }) -}) - -dl_qgb_tab <- function(path) { - dat <- try(.quickgen(), silent = TRUE) - if (inherits(dat, "try-error") || is.null(dat)) { - write.csv(tibble::tibble("Data" = "[Empty]"), path, row.names = FALSE) - return() - } - - rows <- input$qgb_rows_all - tmp <- if (is.null(rows)) dat$tab else dat$tab[rows, , drop = FALSE] - - if (is.null(tmp) || nrow(tmp) == 0) { - write.csv(tibble::tibble("Data" = "[Empty]"), path, row.names = FALSE) - } else { - write.csv(tmp, path, row.names = FALSE) - } -} - - -output$qib_chart <- renderPlot( - { - req(input$qib_type) - if (not_available(input$qib_xvar)) { - if (!input$qib_type %in% c("box", "line")) { - return( - plot( - x = 1, type = "n", - main = " ", - axes = FALSE, xlab = "", ylab = "", cex.main = .9 - ) - ) - } - } - .qib_chart() %>% - (function(x) { - if (is.empty(x) || is.character(x)) { - plot(x = 1, type = "n", main = paste0("\n", x), axes = FALSE, xlab = "", ylab = "", cex.main = .9) - } else if (length(x) > 0) { - print(x) - } - }) - }, - width = qib_plot_width, - height = qib_plot_height, - res = 96 -) - -.qib_chart <- eventReactive(input$qib_run, { - req(input$qib_type) - if (input$qib_type == "scatter") req(input$qib_nrobs) - - ## need dependency on .. - req(input$qib_plot_height && input$qib_plot_width) - - if (not_available(input$qib_xvar) && !input$qib_type %in% c("box", "line")) { - return() - } else if (input$qib_type %in% c("scatter", "line", "box", "bar", "surface") && not_available(input$qib_yvar)) { - return(i18n$t("No Y-variable provided for a plot that requires one")) - } else if (input$qib_type == "box" && !all(input$qib_xvar %in% groupable_vars())) { - return() - } - - ## waiting for comby and/or combx to be updated - if (input$qib_type %in% c("dist", "density")) { - if (isTRUE(input$qib_comby)) { - return() - } - if (length(input$qib_xvar) > 1 && is.null(input$qib_combx)) { - return() - } - } else { - if (isTRUE(input$qib_combx)) { - return() - } - if (length(input$qib_yvar) > 1 && is.null(input$qib_comby)) { - return() - } - } - - #req(!is.null(input$qib_color) || !is.null(input$qib_fill)) - qibi <- qib_inputs() - qibi$dataset <- input$dataset - qibi$shiny <- TRUE - qibi$envir <- r_data - qibi$color <- "none" - qibi$fill <- "none" - qibi$facet_row <- "." - qibi$facet_col <- "." - withProgress(message = i18n$t("Making plot"), value = 1, { - do.call(visualize, qibi) - }) -}) - -observeEvent(input$qgb_store, { - req(input$qgb_name) - dat <- .quickgen() - if (is.null(dat)) { - return() - } - dataset <- fix_names(input$qgb_name) - if (input$qgb_name != dataset) { - updateTextInput(session, inputId = "qgb_name", value = dataset) - } - rows <- input$qgb_rows_all - tmp <- if (is.null(rows)) dat$tab else dat$tab[rows, , drop = FALSE] - r_data[[dataset]] <- tmp - register(dataset) - updateSelectInput(session, "dataset", selected = input$dataset) - - showModal( - modalDialog( - title = i18n$t("Data Stored"), - span( - i18n$t("Dataset was successfully added to the datasets dropdown. Add code to Report > Rmd or Report > R to (re)create the results by clicking the report icon on the bottom left of your screen.") - ), - footer = modalButton(i18n$t("OK")), - size = "m", - easyClose = TRUE - ) - ) -}) - -qgb_report <- function() { - ## get the state of the dt table - ts <- dt_state("qgb_tab") - xcmd <- "# summary(result)\ndtab(result" - if (!is.empty(input$qgb_dec, 3)) { - xcmd <- paste0(xcmd, ", dec = ", input$qgb_dec) - } - if (!is.empty(r_state$qgb_state$length, 10)) { - xcmd <- paste0(xcmd, ", pageLength = ", r_state$qgb_state$length) - } - xcmd <- paste0(xcmd, ", caption = \"\") %>% render()") - if (!is.empty(input$qgb_name)) { - dataset <- fix_names(input$qgb_name) - if (input$qgb_name != dataset) { - updateTextInput(session, inputId = "qgb_name", value = dataset) - } - xcmd <- paste0(xcmd, "\n", dataset, " <- result$tab\nregister(\"", dataset, "\")") - } - - inp_main <- clean_args(qgb_inputs(), qgb_args) - if (ts$tabsort != "") inp_main <- c(inp_main, tabsort = ts$tabsort) - if (ts$tabfilt != "") inp_main <- c(inp_main, tabfilt = ts$tabfilt) - if (is.empty(inp_main$rows)) { - inp_main$rows <- NULL - } - if (is.empty(input$qgb_tab_slice)) { - inp_main <- c(inp_main, nr = Inf) - } else { - inp_main$tabslice <- input$qgb_tab_slice - } - - inp_out <- list(clean_args(qgb_sum_inputs(), qgb_sum_args[-1])) - - update_report( - inp_main = inp_main, - fun_name = "qgb", - inp_out = inp_out, - outputs = c(), - figs = FALSE, - xcmd = xcmd - ) -} - -qib_report <- function() { - ## resetting hidden elements to default values - vi <- qib_inputs() - if (input$qib_type != "dist") { - vi$bins <- qib_args$bins - } - if (input$qib_type %in% c("dist", "density")) { - vi$yvar <- qib_args$yvar - } - if (!input$qib_type %in% c("density", "scatter", "dist") || - !("loess" %in% input$qib_check || "density" %in% input$qib_axes || input$qib_type == "density")) { - vi$smooth <- qib_args$smooth - } - if (!input$qib_type %in% c("scatter", "box") && "jitter" %in% input$qib_check) { - vi$check <- base::setdiff(vi$check, "jitter") - } - if (input$qib_type != "scatter") { - vi$size <- "none" - vi$nrobs <- NULL - } else { - vi$nrobs <- as_integer(vi$nrobs) - } - if (!input$qib_type %in% c("scatter", "line", "box")) { - vi$color <- NULL - } - if (!input$qib_type %in% c("bar", "dist", "density", "surface")) { - vi$fill <- NULL - } - - if (!input$qib_type %in% c("bar", "dist", "box", "density")) { - vi$fillcol <- "blue" - } - if (!input$qib_type %in% c("dist", "density", "box", "scatter", "line")) { - vi$linecol <- "black" - } - if (!input$qib_type %in% c("box", "scatter", "line")) { - vi$pointcol <- "black" - } - - if (!input$qib_type %in% c("bar", "line", "scatter")) { - vi$fun <- "mean" - } - if (is.empty(input$data_rows)) { - vi$rows <- NULL - } - - inp_main <- c(clean_args(vi, qib_args), custom = FALSE) - - update_report( - inp_main = inp_main, - fun_name = "qib_chart", - outputs = character(0), - pre_cmd = "", - figs = TRUE, - fig.width = qib_plot_width(), - fig.height = qib_plot_height() - ) -} - -download_handler( - id = "dl_qgb_tab", - fun = dl_qgb_tab, - fn = function() paste0(input$dataset, "_tab"), - type = "csv" -) - -download_handler( - id = "dlp_qib_chart", - fun = download_handler_plot, - fn = function() paste0(input$dataset, "_chart"), - type = "png", - caption = i18n$t("Save visualize plot"), - plot = .qib_chart, - width = qib_plot_width, - height = qib_plot_height -) - - -observeEvent(input$qgb_report, { - r_info[["latest_screenshot"]] <- NULL - qgb_report() -}) - -observeEvent(input$qgb_screenshot, { - r_info[["latest_screenshot"]] <- NULL - radiant_screenshot_modal("modal_qgb_screenshot") -}) - -observeEvent(input$modal_qgb_screenshot, { - qgb_report() - removeModal() -}) - -observeEvent(input$qib_report, { - r_info[["latest_screenshot"]] <- NULL - qib_report() -}) - -observeEvent(input$qib_screenshot, { - r_info[["latest_screenshot"]] <- NULL - radiant_screenshot_modal("modal_qib_screenshot") -}) - -observeEvent(input$modal_qib_screenshot, { - qib_report() - removeModal() -}) - -# 全选功能 -observeEvent(input$qgb_select_all, { - r_funs <- getOption("radiant.functions") - if (!is.null(r_funs)) { - updateCheckboxGroupInput(session, "qgb_fun", selected = r_funs) - } -}) - -# 全不选功能 -observeEvent(input$qgb_deselect_all, { - updateCheckboxGroupInput(session, "qgb_fun", selected = character(0)) -}) - -# 反选功能 -observeEvent(input$qgb_invert_selection, { - current <- input$qgb_fun %||% character(0) - r_funs <- getOption("radiant.functions") - if (!is.null(r_funs)) { - new_selection <- setdiff(r_funs, current) - updateCheckboxGroupInput(session, "qgb_fun", selected = new_selection) - } -}) - -output$quickgen_basic <- renderUI({ - stat_tab_panel( - menu = i18n$t("Oneclick generation > Generate descriptive statistics"), - tool = i18n$t("Generate descriptive statistics with one click"), - tool_ui = "ui_quickgen_basic", - output_panels = tagList( - tabPanel( - title = i18n$t("Table"), - download_link("dl_qgb_tab"),br(), - DT::dataTableOutput("qgb_tab"), - tags$hr(), - htmlOutput("qgb_desc_text", inline = FALSE) - ), - tabPanel( - title = i18n$t("Chart"), - download_link("dlp_qib_chart"), br(), - plotOutput("qib_chart", width = "100%", height = "auto"), - tags$hr(), - htmlOutput("qib_desc_text", inline = FALSE) - ) - ) - ) -}) - -## ---------- 表格的描述文字 ---------- -output$qgb_desc_text <- renderUI({ - dat <- tryCatch(.quickgen(), error = function(e) NULL) - txt <- if (!is.null(dat) && !is.null(dat$tab)) { - make_desc_text(dat$tab) - } else { - " " - } - HTML(markdown::markdownToHTML(text = txt, fragment.only = TRUE)) -}) - -## ---------- 图表的描述文字 ---------- -output$qib_desc_text <- renderUI({ - df <- tryCatch({ - qibi <- qib_inputs() - qibi$envir <- r_data - qibi$dataset <- input$dataset - qibi$shiny <- TRUE - res <- do.call(visualize, qibi) - res$data - }, error = function(e) NULL) - - txt <- if (!is.null(df)) make_desc_text(df) else " " - HTML(markdown::markdownToHTML(text = txt, fragment.only = TRUE)) -}) \ No newline at end of file diff --git a/radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui.R b/radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui.R index 9d84af2..d033c6d 100644 --- a/radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui.R +++ b/radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui.R @@ -1,3 +1,8 @@ +safe_is_empty <- function(x) { + if (is.null(x) || !is.character(x)) return(TRUE) + is.empty(x) +} + make_desc_text <- function(df) { if (is.null(df) || nrow(df) == 0) return(i18n$t("No data available")) num_cols <- sapply(df, is.numeric) @@ -68,7 +73,7 @@ qib_add_labs <- function() { lab_list <- list() for (l in qib_labs) { inp <- input[[paste0("qib_labs_", l)]] - if (!is.empty(inp)) lab_list[[l]] <- inp + if (!safe_is_empty(inp)) lab_list[[l]] <- inp } lab_list } @@ -402,7 +407,7 @@ output$ui_qib_axes <- renderUI({ } else if (input$qib_type %in% c("bar", "box")) { ind <- c(1, 3) } - if (!is.empty(input$qib_facet_row, ".") || !is.empty(input$qib_facet_col, ".")) ind <- c(ind, 4) + if (!safe_is_empty(input$qib_facet_row, ".") || !safe_is_empty(input$qib_facet_col, ".")) ind <- c(ind, 4) if (input$qib_type == "bar") ind <- c(ind, 6) checkboxGroupInput( @@ -676,7 +681,7 @@ output$ui_quickgen_basic <- renderUI({ }) qib_plot_width <- reactive({ - if (is.empty(input$qib_plot_width)) r_info[["plot_width"]] else input$qib_plot_width + if (safe_is_empty(input$qib_plot_width)) r_info[["plot_width"]] else input$qib_plot_width }) qib_plot_height <- eventReactive( @@ -686,7 +691,7 @@ qib_plot_height <- eventReactive( input$qib_plot_width }, { - if (is.empty(input$qib_plot_height)) { + if (safe_is_empty(input$qib_plot_height)) { r_info[["plot_height"]] } else { lx <- ifelse(not_available(input$qib_xvar) || isTRUE(input$qib_combx), 1, length(input$qib_xvar)) @@ -786,77 +791,49 @@ dl_qgb_tab <- function(path) { } -output$qib_chart <- renderPlot( - { - req(input$qib_type) - if (not_available(input$qib_xvar)) { - if (!input$qib_type %in% c("box", "line")) { - return( - plot( - x = 1, type = "n", - main = " ", - axes = FALSE, xlab = "", ylab = "", cex.main = .9 - ) - ) - } - } - .qib_chart() %>% - (function(x) { - if (is.empty(x) || is.character(x)) { - plot(x = 1, type = "n", main = paste0("\n", x), axes = FALSE, xlab = "", ylab = "", cex.main = .9) - } else if (length(x) > 0) { - print(x) - } - }) - }, - width = qib_plot_width, - height = qib_plot_height, - res = 96 -) +output$qib_chart <- renderPlot({ + req(input$qib_type) + p <- .qib_chart() + if (is.null(p)) return(NULL) + print(p) +}, width = qib_plot_width, height = qib_plot_height, res = 96) .qib_chart <- eventReactive(input$qib_run, { req(input$qib_type) if (input$qib_type == "scatter") req(input$qib_nrobs) - - ## need dependency on .. req(input$qib_plot_height && input$qib_plot_width) if (not_available(input$qib_xvar) && !input$qib_type %in% c("box", "line")) { - return() - } else if (input$qib_type %in% c("scatter", "line", "box", "bar", "surface") && not_available(input$qib_yvar)) { - return(i18n$t("No Y-variable provided for a plot that requires one")) - } else if (input$qib_type == "box" && !all(input$qib_xvar %in% groupable_vars())) { - return() + return(NULL) + } + if (input$qib_type %in% c("scatter", "line", "box", "bar", "surface") && not_available(input$qib_yvar)) { + return(NULL) + } + if (input$qib_type == "box" && !all(input$qib_xvar %in% groupable_vars())) { + return(NULL) } - ## waiting for comby and/or combx to be updated + ## 等待 combx / comby 更新 if (input$qib_type %in% c("dist", "density")) { - if (isTRUE(input$qib_comby)) { - return() - } - if (length(input$qib_xvar) > 1 && is.null(input$qib_combx)) { - return() - } + if (isTRUE(input$qib_comby)) return(NULL) + if (length(input$qib_xvar) > 1 && is.null(input$qib_combx)) return(NULL) } else { - if (isTRUE(input$qib_combx)) { - return() - } - if (length(input$qib_yvar) > 1 && is.null(input$qib_comby)) { - return() - } + if (isTRUE(input$qib_combx)) return(NULL) + if (length(input$qib_yvar) > 1 && is.null(input$qib_comby)) return(NULL) } - #req(!is.null(input$qib_color) || !is.null(input$qib_fill)) qibi <- qib_inputs() - qibi$dataset <- input$dataset - qibi$shiny <- TRUE - qibi$envir <- r_data - qibi$color <- "none" - qibi$fill <- "none" + qibi$dataset <- input$dataset + qibi$shiny <- TRUE + qibi$envir <- r_data + qibi$color <- "none" + qibi$fill <- "none" qibi$facet_row <- "." qibi$facet_col <- "." + withProgress(message = i18n$t("Making plot"), value = 1, { - do.call(visualize, qibi) + p <- do.call(visualize, qibi) + if (is.character(p)) return(NULL) else p }) }) @@ -875,7 +852,7 @@ observeEvent(input$qgb_store, { r_data[[dataset]] <- tmp register(dataset) updateSelectInput(session, "dataset", selected = input$dataset) - + showModal( modalDialog( title = i18n$t("Data Stored"), @@ -889,154 +866,95 @@ observeEvent(input$qgb_store, { ) }) -qgb_report <- function() { - ## get the state of the dt table - ts <- dt_state("qgb_tab") - xcmd <- "# summary(result)\ndtab(result" - if (!is.empty(input$qgb_dec, 3)) { - xcmd <- paste0(xcmd, ", dec = ", input$qgb_dec) - } - if (!is.empty(r_state$qgb_state$length, 10)) { - xcmd <- paste0(xcmd, ", pageLength = ", r_state$qgb_state$length) - } +download_handler( + id = "dl_qgb_tab", + fun = dl_qgb_tab, + fn = function() paste0(input$dataset, "_tab"), + type = "csv" +) + +download_handler( + id = "dlp_qib_chart", + fun = download_handler_plot, + fn = function() paste0(input$dataset, "_chart"), + type = "png", + caption = i18n$t("Save visualize plot"), + plot = .qib_chart, + width = qib_plot_width, + height = qib_plot_height +) + +quickgen_basic_report <- function() { + req(input$qgb_vars, input$qib_type) + + ##-------------- 表 格 部 分 -------------- + tabsort <- if (!is.null(input$qgb_state$order)) + paste0("order = ", jsonlite::toJSON(input$qgb_state$order)) else "" + tabfilt <- if (!is.null(input$qgb_search_columns)) + paste0("searchCols = ", jsonlite::toJSON(lapply(input$qgb_search_columns, function(x) list(search = x)))) else "" + xcmd <- "# quickgen table: descriptive statistics\ndtab(result" + if (!is.empty(input$qgb_dec, 3)) xcmd <- paste0(xcmd, ", dec = ", input$qgb_dec) + if (!is.empty(r_state$qgb_state$length, 10)) xcmd <- paste0(xcmd, ", pageLength = ", r_state$qgb_state$length) + if (nzchar(tabsort)) xcmd <- paste0(xcmd, ", ", tabsort) + if (nzchar(tabfilt)) xcmd <- paste0(xcmd, ", ", tabfilt) xcmd <- paste0(xcmd, ", caption = \"\") %>% render()") if (!is.empty(input$qgb_name)) { dataset <- fix_names(input$qgb_name) - if (input$qgb_name != dataset) { + if (input$qgb_name != dataset) updateTextInput(session, inputId = "qgb_name", value = dataset) - } xcmd <- paste0(xcmd, "\n", dataset, " <- result$tab\nregister(\"", dataset, "\")") } - inp_main <- clean_args(qgb_inputs(), qgb_args) - if (ts$tabsort != "") inp_main <- c(inp_main, tabsort = ts$tabsort) - if (ts$tabfilt != "") inp_main <- c(inp_main, tabfilt = ts$tabfilt) - if (is.empty(inp_main$rows)) { - inp_main$rows <- NULL - } - if (is.empty(input$qgb_tab_slice)) { - inp_main <- c(inp_main, nr = Inf) - } else { - inp_main$tabslice <- input$qgb_tab_slice - } + if (is.empty(inp_main$rows)) inp_main$rows <- NULL + if (!is.empty(input$qgb_tab_slice)) inp_main$tabslice <- input$qgb_tab_slice - inp_out <- list(clean_args(qgb_sum_inputs(), qgb_sum_args[-1])) - - update_report( - inp_main = inp_main, - fun_name = "qgb", - inp_out = inp_out, - outputs = c(), - figs = FALSE, - xcmd = xcmd - ) -} - -qib_report <- function() { - ## resetting hidden elements to default values + ##-------------- 图 形 部 分 -------------- vi <- qib_inputs() - if (input$qib_type != "dist") { - vi$bins <- qib_args$bins - } - if (input$qib_type %in% c("dist", "density")) { - vi$yvar <- qib_args$yvar - } + if (input$qib_type != "dist") vi$bins <- qib_args$bins + if (input$qib_type %in% c("dist", "density")) vi$yvar <- qib_args$yvar if (!input$qib_type %in% c("density", "scatter", "dist") || - !("loess" %in% input$qib_check || "density" %in% input$qib_axes || input$qib_type == "density")) { + !("loess" %in% input$qib_check || "density" %in% input$qib_axes || input$qib_type == "density")) vi$smooth <- qib_args$smooth - } - if (!input$qib_type %in% c("scatter", "box") && "jitter" %in% input$qib_check) { + if (!input$qib_type %in% c("scatter", "box") && "jitter" %in% input$qib_check) vi$check <- base::setdiff(vi$check, "jitter") - } if (input$qib_type != "scatter") { - vi$size <- "none" + vi$size <- "none" vi$nrobs <- NULL } else { vi$nrobs <- as_integer(vi$nrobs) } - if (!input$qib_type %in% c("scatter", "line", "box")) { - vi$color <- NULL - } - if (!input$qib_type %in% c("bar", "dist", "density", "surface")) { - vi$fill <- NULL - } + if (!input$qib_type %in% c("scatter", "line", "box")) vi$color <- NULL + if (!input$qib_type %in% c("bar", "dist", "density", "surface")) vi$fill <- NULL + if (!input$qib_type %in% c("bar", "dist", "box", "density")) vi$fillcol <- "blue" + if (!input$qib_type %in% c("dist", "density", "box", "scatter", "line")) vi$linecol <- "black" + if (!input$qib_type %in% c("box", "scatter", "line")) vi$pointcol <- "black" + if (!input$qib_type %in% c("bar", "line", "scatter")) vi$fun <- "mean" + if (safe_is_empty(input$data_rows)) vi$rows <- NULL - if (!input$qib_type %in% c("bar", "dist", "box", "density")) { - vi$fillcol <- "blue" - } - if (!input$qib_type %in% c("dist", "density", "box", "scatter", "line")) { - vi$linecol <- "black" - } - if (!input$qib_type %in% c("box", "scatter", "line")) { - vi$pointcol <- "black" - } - - if (!input$qib_type %in% c("bar", "line", "scatter")) { - vi$fun <- "mean" - } - if (is.empty(input$data_rows)) { - vi$rows <- NULL - } - - inp_main <- c(clean_args(vi, qib_args), custom = FALSE) + inp_main <- c(inp_main, clean_args(vi, qib_args), custom = FALSE) + ##-------------- 一次性写进 Report -------------- update_report( - inp_main = inp_main, - fun_name = "qib_chart", - outputs = character(0), - pre_cmd = "", - figs = TRUE, - fig.width = qib_plot_width(), + inp_main = inp_main, + fun_name = "quickgen_basic", # 统一事件名 + outputs = character(0), + pre_cmd = "", + figs = TRUE, # 需要插图 + fig.width = qib_plot_width(), fig.height = qib_plot_height() ) } -download_handler( - id = "dl_qgb_tab", - fun = dl_qgb_tab, - fn = function() paste0(input$dataset, "_tab"), - type = "csv" -) - -download_handler( - id = "dlp_qib_chart", - fun = download_handler_plot, - fn = function() paste0(input$dataset, "_chart"), - type = "png", - caption = i18n$t("Save visualize plot"), - plot = .qib_chart, - width = qib_plot_width, - height = qib_plot_height -) - - -observeEvent(input$qgb_report, { - r_info[["latest_screenshot"]] <- NULL - qgb_report() -}) - -observeEvent(input$qgb_screenshot, { - r_info[["latest_screenshot"]] <- NULL - radiant_screenshot_modal("modal_qgb_screenshot") -}) - -observeEvent(input$modal_qgb_screenshot, { - qgb_report() - removeModal() -}) - -observeEvent(input$qib_report, { +observeEvent(input$quickgen_basic_report, { r_info[["latest_screenshot"]] <- NULL - qib_report() + quickgen_basic_report() }) - -observeEvent(input$qib_screenshot, { +observeEvent(input$quickgen_basic_screenshot, { r_info[["latest_screenshot"]] <- NULL - radiant_screenshot_modal("modal_qib_screenshot") + radiant_screenshot_modal("modal_quickgen_basic_screenshot") }) - -observeEvent(input$modal_qib_screenshot, { - qib_report() +observeEvent(input$modal_quickgen_basic_screenshot, { + quickgen_basic_report() removeModal() }) diff --git a/radiant.quickgen/inst/app/tools/help/quickgen_ai.md b/radiant.quickgen/inst/app/tools/help/quickgen_ai.md index e69de29..983dea5 100644 --- a/radiant.quickgen/inst/app/tools/help/quickgen_ai.md +++ b/radiant.quickgen/inst/app/tools/help/quickgen_ai.md @@ -0,0 +1,27 @@ +> 大模型生成描述性统计 + +## 使用方法 + +以下是 `大模型生成描述性统计`的使用方法。 + +1.`数据对象`必须要有,且必须和数据集中的名字一致(大小写也一致) + +2.`图像类型`必须要有,比如分布图、散点图等。可以要求模型返回多张图表,需向模型明确。 + +3.`生成代码`如果有误,或者想要修改,可以点击`编辑`按钮对R代码进行修改,保存后点击`运行`按钮即可。 +## 示例 + +**1. 散点图** +请用diamonds画一个散点图,X轴是carat,Y轴是price,用color来区分颜色,并加上theme_bw()。 +**2. 箱线图** +请用diamonds画箱线图,把price按cut分组,看看不同切工的价格分布。 +**3. 直方图** +请用diamonds画carat的直方图,分面按clarity排布,bin宽度取0.1。 +**4. 柱状图** +请用diamonds统计各color等级的数量,画一个柱状图,颜色按实际颜色填充。 +**5. 密度图** +请用diamonds画出0.5~2克拉范围内,不同color的carat密度曲线,要求半透明重叠。 +**6. 分组均值表** +请用diamonds按cut分组,计算每组price与carat的平均值、标准差,输出成表格。 +**7. 价格对数-克拉线性拟合图** +请用diamonds画log(price)和carat的散点图,并加上回归直线,颜色按clarity区分,用theme_minimal()。 \ No newline at end of file diff --git a/set_path.R b/set_path.R index 4f80e1b..391503e 100644 --- a/set_path.R +++ b/set_path.R @@ -1,4 +1,3 @@ -# 创建文件 /home/wuzekai/radiant/set_path.R cat <<'EOF' | sudo tee /home/wuzekai/radiant/set_path.R options(radiant.launch_dir = "/data") options(radiant.project_dir = "/data") -- 2.22.0