Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
R
Radiant
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wuzekai
Radiant
Commits
f926635b
Commit
f926635b
authored
Oct 10, 2025
by
wuzekai
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update
parent
105b9543
Changes
16
Show whitespace changes
Inline
Side-by-side
Showing
16 changed files
with
1090 additions
and
413 deletions
+1090
-413
README.md
README.md
+0
-4
notice.txt
notice.txt
+28
-0
translation_zh.csv
radiant-master/inst/translations/translation_zh.csv
+4
-3
DESCRIPTION
radiant.basics/DESCRIPTION
+42
-40
homo_variance_test.R
radiant.basics/R/homo_variance_test.R
+192
-54
normality_test.R
radiant.basics/R/normality_test.R
+92
-21
homo_variance_test_ui.R
...nt.basics/inst/app/tools/analysis/homo_variance_test_ui.R
+79
-50
normality_test_ui.R
radiant.basics/inst/app/tools/analysis/normality_test_ui.R
+16
-11
DESCRIPTION
radiant.data/DESCRIPTION
+70
-69
global.R
radiant.data/inst/app/global.R
+1
-2
stop.R
radiant.data/inst/app/tools/app/stop.R
+62
-49
visualize_ui.R
radiant.data/inst/app/tools/data/visualize_ui.R
+126
-38
cox.R
radiant.model/R/cox.R
+79
-10
cox_ui.R
radiant.model/inst/app/tools/analysis/cox_ui.R
+107
-24
quickgen_ai.R
radiant.quickgen/R/quickgen_ai.R
+1
-1
quickgen_basic_ui.R
radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui.R
+191
-37
No files found.
README.md
deleted
100644 → 0
View file @
105b9543
# radiant
科研统计分析工具
Statistical Analysis System
\ No newline at end of file
notice.txt
0 → 100644
View file @
f926635b
上传模块
devtools::install_local("/home/wuzekai/radiant/radiant.data", force = TRUE)
devtools::install_local("/home/wuzekai/radiant/radiant.basics", force = TRUE)
devtools::install_local("/home/wuzekai/radiant/radiant.design", force = TRUE)
devtools::install_local("/home/wuzekai/radiant/radiant.model", force = TRUE)
devtools::install_local("/home/wuzekai/radiant/radiant.multivariate", force = TRUE)
devtools::install_local("/home/wuzekai/radiant/radiant.quickgen", force = TRUE)
devtools::install_local("/home/wuzekai/radiant/radiant-master", force = TRUE)
清理原文件
rm -rf /root/miniconda3/envs/radiant/lib/R/library/radiant.data
rm -rf /root/miniconda3/envs/radiant/lib/R/library/radiant.basics
rm -rf /root/miniconda3/envs/radiant/lib/R/library/radiant.design
rm -rf /root/miniconda3/envs/radiant/lib/R/library/radiant.model
rm -rf /root/miniconda3/envs/radiant/lib/R/library/radiant.multivariate
rm -rf /root/miniconda3/envs/radiant/lib/R/library/radiant.quickgen
rm -rf /root/miniconda3/envs/radiant/lib/R/library/radiant-master
启动软件
sudo -i
conda activate radiant
cd /home/wuzekai/radiant
R
options(browser = 'false'); radiant::radiant(host='0.0.0.0', port=8105)
杀掉端口
lsof -i :8105
kill -9 <PID>
\ No newline at end of file
radiant-master/inst/translations/translation_zh.csv
View file @
f926635b
...
@@ -1159,9 +1159,9 @@ Edit the generated R code here...,在此处编辑生成的R代码...,quickgen_ai
...
@@ -1159,9 +1159,9 @@ Edit the generated R code here...,在此处编辑生成的R代码...,quickgen_ai
Normality test,正态性检验,init.R
Normality test,正态性检验,init.R
Homogeneity of variance test,方差齐性检验,init.R
Homogeneity of variance test,方差齐性检验,init.R
Basics > Normality,基础统计 > 正态性,normality_test_ui.R
Basics > Normality,基础统计 > 正态性,normality_test_ui.R
Shapiro-Wilk,SW
检验,normality_test_ui.R
Shapiro-Wilk,SW检验,normality_test_ui.R
Kolmogorov-Smirnov,K-S
检验,normality_test_ui.R
Kolmogorov-Smirnov,K-S检验,normality_test_ui.R
Anderson-Darling,AD
检验,normality_test_ui.R
Anderson-Darling,AD检验,normality_test_ui.R
Basics > Homogeneity,基础统计 > 方差齐性,homo_variance_test_ui.R
Basics > Homogeneity,基础统计 > 方差齐性,homo_variance_test_ui.R
Grouping variable:,分组变量:,homo_variance_test_ui.R
Grouping variable:,分组变量:,homo_variance_test_ui.R
Test method:,检验方法:,homo_variance_test_ui.R
Test method:,检验方法:,homo_variance_test_ui.R
...
@@ -1186,3 +1186,4 @@ Time variable:,生存时间变量:,cox_ui.R
...
@@ -1186,3 +1186,4 @@ Time variable:,生存时间变量:,cox_ui.R
Status variable:,事件状态变量:,cox_ui.R
Status variable:,事件状态变量:,cox_ui.R
AI running...,大模型运行中...,quickgen_ai_ui.R
AI running...,大模型运行中...,quickgen_ai_ui.R
Warning:Please enter a request related to descriptive statistics or visualization.,警告:请输入与描述性统计或可视化相关的请求。,quickgen_ai_ui.R
Warning:Please enter a request related to descriptive statistics or visualization.,警告:请输入与描述性统计或可视化相关的请求。,quickgen_ai_ui.R
Boxplot,箱型图,homo_variance_test_ui.R
radiant.basics/DESCRIPTION
View file @
f926635b
...
@@ -24,7 +24,9 @@ Imports:
...
@@ -24,7 +24,9 @@ Imports:
polycor (>= 0.7.10),
polycor (>= 0.7.10),
patchwork (>= 1.0.0),
patchwork (>= 1.0.0),
shiny.i18n,
shiny.i18n,
rlang (>= 1.0.6)
rlang (>= 1.0.6),
ggpp,
nortest
Suggests:
Suggests:
testthat (>= 2.0.0),
testthat (>= 2.0.0),
pkgdown (>= 1.1.0),
pkgdown (>= 1.1.0),
...
...
radiant.basics/R/homo_variance_test.R
View file @
f926635b
############################################
############################################
## Homogeneity of variance test
- 空壳版(照抄 single_mean)
## Homogeneity of variance test
############################################
############################################
# Homogeneity of variance tests for radiant.basics
#' @export
#' @export
homo_variance_test
<-
function
(
dataset
,
var
,
group
,
method
=
"levene"
,
homo_variance_test
<-
function
(
dataset
,
var
,
group
,
conf_lev
=
.95
,
data_filter
=
""
,
method
=
c
(
"levene"
,
"bartlett"
,
"fligner"
),
data_filter
=
""
,
envir
=
parent.frame
())
{
envir
=
parent.frame
())
{
# 获取数据
df_name
<-
if
(
is_string
(
dataset
))
dataset
else
deparse
(
substitute
(
dataset
))
df_name
<-
if
(
is_string
(
dataset
))
dataset
else
deparse
(
substitute
(
dataset
))
dataset
<-
get_data
(
dataset
,
var
,
group
,
filt
=
data_filter
,
na.rm
=
TRUE
,
envir
=
envir
)
dataset
<-
get_data
(
dataset
,
vars
=
c
(
var
,
group
),
filt
=
data_filter
,
na.rm
=
FALSE
,
envir
=
envir
)
# 校验变量存在性
if
(
!
var
%in%
colnames
(
dataset
))
{
stop
(
paste
(
"变量"
,
var
,
"未在数据集中找到!"
),
call.
=
FALSE
)
}
if
(
!
group
%in%
colnames
(
dataset
))
{
stop
(
paste
(
"分组变量"
,
group
,
"未在数据集中找到!"
),
call.
=
FALSE
)
}
# 提取变量
x
<-
dataset
[[
var
]]
x
<-
dataset
[[
var
]]
g
<-
dataset
[[
group
]]
g_raw
<-
dataset
[[
group
]]
if
(
!
is.numeric
(
x
))
stop
(
i
18
n
$
t
(
"Variable must be numeric"
))
if
(
length
(
unique
(
g
))
<
2
)
stop
(
i
18
n
$
t
(
"Grouping variable must have at least 2 levels"
))
# 校验数值变量类型
if
(
!
is.numeric
(
x
))
{
## ---- 空壳结果 ----
stop
(
paste
(
"变量"
,
var
,
"必须是数值型!"
),
call.
=
FALSE
)
res
<-
tibble
::
tribble
(
}
~
Test
,
~
Statistic
,
~
p.value
,
"Levene"
,
0.42
,
0.52
,
# 计算有效样本
"Bartlett"
,
0.38
,
0.54
,
valid_indices
<-
!
is.na
(
g_raw
)
&
!
is.na
(
x
)
"Fligner"
,
0.45
,
0.50
valid_data
<-
dataset
[
valid_indices
,
]
# 保留有效样本的完整数据(用于绘图)
valid_g
<-
g_raw
[
valid_indices
]
valid_levels
<-
length
(
unique
(
valid_g
))
# 数据不足判断
if
(
valid_levels
<
2
)
{
return
(
structure
(
list
(
df_name
=
df_name
,
var
=
var
,
group
=
group
,
valid_data
=
valid_data
,
# 传递有效数据用于绘图提示
res
=
tibble
(
Test
=
"无法执行检验"
,
Statistic
=
NA_real_
,
p.value
=
NA_character_
)
)
),
class
=
"homo_variance_test"
))
}
# 转换分组为因子
g
<-
factor
(
valid_g
)
dat_summary
<-
dataset
%>%
# 检验计算
group_by
(
!!
sym
(
group
))
%>%
res
<-
tibble
::
tibble
(
summarise
(
Test
=
character
(),
n
=
n
(),
Statistic
=
numeric
(),
mean
=
mean
(
!!
sym
(
var
),
na.rm
=
TRUE
),
p.value
=
numeric
()
sd
=
sd
(
!!
sym
(
var
),
na.rm
=
TRUE
),
.groups
=
"drop"
)
)
## 绘图数据
# Levene检验
plot_obj
<-
list
(
hist
=
list
(
type
=
"hist"
,
data
=
dataset
,
var
=
var
,
group
=
group
),
if
(
"levene"
%in%
method
&&
requireNamespace
(
"car"
,
quietly
=
TRUE
))
{
density
=
list
(
type
=
"density"
,
data
=
dataset
,
var
=
var
,
group
=
group
),
tmp
<-
tryCatch
(
car
::
leveneTest
(
x
[
valid_indices
]
~
g
),
error
=
function
(
e
)
NULL
)
boxplot
=
list
(
type
=
"boxplot"
,
data
=
dataset
,
var
=
var
,
group
=
group
))
if
(
!
is.null
(
tmp
)
&&
nrow
(
tmp
)
>
0
)
{
res
<-
tibble
::
add_row
(
res
,
Test
=
"Levene"
,
Statistic
=
as.numeric
(
tmp
[[
"F value"
]][
1
]),
p.value
=
as.numeric
(
tmp
[[
"Pr(>F)"
]][
1
]))
}
}
as.list
(
environment
())
%>%
add_class
(
"homo_variance_test"
)
# Bartlett检验
if
(
"bartlett"
%in%
method
)
{
tmp
<-
tryCatch
(
stats
::
bartlett.test
(
x
[
valid_indices
],
g
),
error
=
function
(
e
)
NULL
)
if
(
!
is.null
(
tmp
))
{
res
<-
tibble
::
add_row
(
res
,
Test
=
"Bartlett"
,
Statistic
=
as.numeric
(
tmp
$
statistic
),
p.value
=
as.numeric
(
tmp
$
p.value
))
}
}
# Fligner检验
if
(
"fligner"
%in%
method
)
{
tmp
<-
tryCatch
(
stats
::
fligner.test
(
x
[
valid_indices
],
g
),
error
=
function
(
e
)
NULL
)
if
(
!
is.null
(
tmp
))
{
res
<-
tibble
::
add_row
(
res
,
Test
=
"Fligner"
,
Statistic
=
as.numeric
(
tmp
$
statistic
),
p.value
=
as.numeric
(
tmp
$
p.value
))
}
}
# 返回结果(包含有效数据用于绘图)
structure
(
list
(
df_name
=
df_name
,
var
=
var
,
group
=
group
,
valid_data
=
valid_data
,
# 新增:保存有效样本数据
res
=
res
),
class
=
"homo_variance_test"
)
}
}
# Summary method
#' @export
#' @export
summary.homo_variance_test
<-
function
(
object
,
dec
=
3
,
...
)
{
summary.homo_variance_test
<-
function
(
object
,
dec
=
3
,
...
)
{
# 标准化说明文字(与正态性检验格式一致)
cat
(
"Homogeneity of variance tests\n"
)
cat
(
"Homogeneity of variance tests\n"
)
cat
(
"Data :"
,
object
$
df_name
,
"\n"
)
cat
(
"Data :"
,
object
$
df_name
,
"\n"
)
if
(
!
is.empty
(
object
$
data_filter
))
{
cat
(
"Filter :"
,
gsub
(
"\\n"
,
""
,
object
$
data_filter
),
"\n"
)
}
cat
(
"Variable :"
,
object
$
var
,
"\n"
)
cat
(
"Variable :"
,
object
$
var
,
"\n"
)
cat
(
"Group :"
,
object
$
group
,
"\n\n"
)
cat
(
"Group :"
,
object
$
group
,
"\n\n"
)
## 打印统计量表
# 格式化结果表格
object
$
res
%>%
result_table
<-
object
$
res
%>%
as.data.frame
(
stringsAsFactors
=
FALSE
)
%>%
dplyr
::
mutate
(
format_df
(
dec
=
dec
)
%>%
Statistic
=
round
(
Statistic
,
dec
),
print
(
row.names
=
FALSE
)
p.value
=
dplyr
::
case_when
(
cat
(
"\n"
)
p.value
<
0.001
~
"<0.001"
,
is.na
(
p.value
)
~
""
,
TRUE
~
as.character
(
round
(
p.value
,
dec
))
)
)
# 打印结果表格
print
(
as.data.frame
(
result_table
),
row.names
=
FALSE
)
invisible
(
object
)
}
}
# Plot method
#' @export
#' @export
plot.homo_variance_test
<-
function
(
x
,
plots
=
c
(
"boxplot"
,
"density"
),
plot.homo_variance_test
<-
function
(
x
,
plots
=
c
(
"boxplot"
,
"density"
,
"hist"
),
shiny
=
FALSE
,
custom
=
FALSE
,
...
)
{
shiny
=
FALSE
,
custom
=
FALSE
,
...
)
{
# 1. 提取有效数据(用于绘图)
valid_data
<-
x
$
valid_data
if
(
nrow
(
valid_data
)
==
0
)
{
return
(
ggplot2
::
ggplot
()
+
ggplot2
::
annotate
(
"text"
,
x
=
1
,
y
=
1
,
label
=
i
18
n
$
t
(
"No valid data for plotting"
))
+
ggplot2
::
theme_void
())
}
# 2. 定义变量名(用于图表标签)
var_name
<-
x
$
var
group_name
<-
x
$
group
# 3. 初始化图形列表
plot_list
<-
list
()
plot_list
<-
list
()
# 4. 生成箱线图(按分组展示数值变量分布)
if
(
"boxplot"
%in%
plots
)
{
if
(
"boxplot"
%in%
plots
)
{
plot_list
[[
which
(
"boxplot"
==
plots
)]]
<-
p
<-
ggplot2
::
ggplot
(
valid_data
,
ggplot
(
x
$
dat_summary
,
aes
(
x
=
.data
[[
x
$
group
]],
y
=
.data
[[
x
$
var
]]))
+
ggplot2
::
aes
(
x
=
.data
[[
group_name
]],
geom_boxplot
(
fill
=
"lightblue"
,
alpha
=
0.7
)
y
=
.data
[[
var_name
]],
fill
=
.data
[[
group_name
]]))
+
ggplot2
::
geom_boxplot
(
alpha
=
0.7
,
show.legend
=
FALSE
)
+
ggplot2
::
labs
(
x
=
group_name
,
y
=
var_name
,
title
=
i
18
n
$
t
(
"Boxplot by Group"
))
+
ggplot2
::
theme_minimal
()
+
ggplot2
::
theme
(
plot.title
=
ggplot2
::
element_text
(
hjust
=
0.5
))
plot_list
[[
"boxplot"
]]
<-
p
}
}
# 5. 生成密度图(按分组展示数值变量分布)
if
(
"density"
%in%
plots
)
{
if
(
"density"
%in%
plots
)
{
plot_list
[[
which
(
"density"
==
plots
)]]
<-
p
<-
ggplot2
::
ggplot
(
valid_data
,
ggplot
(
x
$
dat_summary
,
aes
(
x
=
.data
[[
x
$
var
]],
fill
=
.data
[[
x
$
group
]]))
+
ggplot2
::
aes
(
x
=
.data
[[
var_name
]],
geom_density
(
alpha
=
0.5
)
fill
=
.data
[[
group_name
]],
color
=
.data
[[
group_name
]]))
+
ggplot2
::
geom_density
(
alpha
=
0.3
)
+
ggplot2
::
labs
(
x
=
var_name
,
y
=
i
18
n
$
t
(
"Density"
),
title
=
i
18
n
$
t
(
"Density by Group"
),
fill
=
group_name
,
color
=
group_name
)
+
ggplot2
::
theme_minimal
()
+
ggplot2
::
theme
(
plot.title
=
ggplot2
::
element_text
(
hjust
=
0.5
))
plot_list
[[
"density"
]]
<-
p
}
}
# 6. 生成直方图(按分组展示数值变量分布)
if
(
"hist"
%in%
plots
)
{
if
(
"hist"
%in%
plots
)
{
plot_list
[[
which
(
"hist"
==
plots
)]]
<-
p
<-
ggplot2
::
ggplot
(
valid_data
,
ggplot
(
x
$
dat_summary
,
aes
(
x
=
.data
[[
x
$
var
]],
fill
=
.data
[[
x
$
group
]]))
+
ggplot2
::
aes
(
x
=
.data
[[
var_name
]],
geom_histogram
(
alpha
=
0.5
,
position
=
"identity"
,
bins
=
30
)
fill
=
.data
[[
group_name
]]))
+
ggplot2
::
geom_histogram
(
position
=
"identity"
,
alpha
=
0.5
,
bins
=
30
)
+
ggplot2
::
labs
(
x
=
var_name
,
y
=
i
18
n
$
t
(
"Count"
),
title
=
i
18
n
$
t
(
"Histogram by Group"
),
fill
=
group_name
)
+
ggplot2
::
theme_minimal
()
+
ggplot2
::
theme
(
plot.title
=
ggplot2
::
element_text
(
hjust
=
0.5
))
plot_list
[[
"hist"
]]
<-
p
}
}
if
(
length
(
plot_list
)
==
0
)
return
(
invisible
())
# 7. 处理未选择图表类型的情况
patchwork
::
wrap_plots
(
plot_list
,
ncol
=
1
)
%>%
if
(
length
(
plot_list
)
==
0
)
{
{
if
(
shiny
)
print
(
.
)
else
print
(
.
)
}
return
(
ggplot2
::
ggplot
()
+
ggplot2
::
annotate
(
"text"
,
x
=
1
,
y
=
1
,
label
=
i
18
n
$
t
(
"No plots selected"
))
+
ggplot2
::
theme_void
())
}
# 8. 组合图表(按选择顺序排列)
combined_plot
<-
patchwork
::
wrap_plots
(
plot_list
[
plots
],
ncol
=
1
)
# 9. 在Shiny中显示或返回图表
if
(
shiny
)
{
print
(
combined_plot
)
invisible
(
x
)
invisible
(
x
)
}
else
{
combined_plot
}
}
}
radiant.basics/R/normality_test.R
View file @
f926635b
...
@@ -3,36 +3,97 @@
...
@@ -3,36 +3,97 @@
############################################
############################################
# Batch normality tests for radiant.basics
# Batch normality tests for radiant.basics
#
#' @export
#' @export
normality_test
<-
function
(
dataset
,
var
,
method
=
"shapiro"
,
normality_test
<-
function
(
dataset
,
conf_lev
=
.95
,
data_filter
=
""
,
var
,
method
=
c
(
"shapiro"
,
"ks"
,
"ad"
),
data_filter
=
""
,
envir
=
parent.frame
())
{
envir
=
parent.frame
())
{
## 1. 定义支持的检验方法
supported_methods
<-
c
(
"shapiro"
,
"ks"
,
"ad"
)
## 2. 处理多选方法:过滤无效值+设置默认
method
<-
intersect
(
method
,
supported_methods
)
if
(
length
(
method
)
==
0
)
method
<-
"shapiro"
method
<-
match.arg
(
method
,
choices
=
supported_methods
,
several.ok
=
TRUE
)
## 3. 取数据
df_name
<-
if
(
is_string
(
dataset
))
dataset
else
deparse
(
substitute
(
dataset
))
df_name
<-
if
(
is_string
(
dataset
))
dataset
else
deparse
(
substitute
(
dataset
))
dataset
<-
get_data
(
dataset
,
var
,
filt
=
data_filter
,
na.rm
=
TRUE
,
envir
=
envir
)
dataset
<-
get_data
(
dataset
,
var
,
filt
=
data_filter
,
na.rm
=
TRUE
,
envir
=
envir
)
x
<-
dataset
[[
var
]]
x
<-
dataset
[[
var
]]
if
(
!
is.numeric
(
x
))
stop
(
i
18
n
$
t
(
"Variable must be numeric"
))
if
(
!
is.numeric
(
x
))
stop
(
i
18
n
$
t
(
"Variable must be numeric"
))
x
<-
x
[
!
is.na
(
x
)]
# 剔除缺失
## ---- 空壳结果 ----
## 4. 初始化结果表格
res
<-
tibble
::
tribble
(
res
<-
tibble
::
tibble
(
~
Test
,
~
Statistic
,
~
p.value
,
Test
=
character
(),
"Shapiro-Wilk"
,
0.99
,
0.12
,
Statistic
=
numeric
(),
"Kolmogorov-Smirnov"
,
0.05
,
0.30
,
p.value
=
numeric
()
"Anderson-Darling"
,
0.80
,
0.25
)
)
dat_summary
<-
tibble
::
tribble
(
## 5. 逐方法计算
~
mean
,
~
n
,
~
n_missing
,
~
sd
,
~
se
,
if
(
"shapiro"
%in%
method
)
{
mean
(
x
,
na.rm
=
TRUE
),
length
(
x
),
sum
(
is.na
(
x
)),
sd
(
x
,
na.rm
=
TRUE
),
sd
(
x
,
na.rm
=
TRUE
)
/
sqrt
(
length
(
x
))
tmp
<-
tryCatch
(
stats
::
shapiro.test
(
x
),
error
=
function
(
e
)
{
stop
(
"Shapiro-Wilk 需要 3 ≤ n ≤ 5000,当前 n = "
,
length
(
x
),
"\n请换 KS 或 AD 方法。"
)
})
res
<-
tibble
::
add_row
(
res
,
Test
=
"Shapiro-Wilk"
,
Statistic
=
tmp
$
statistic
,
p.value
=
tmp
$
p.value
)
}
if
(
"ks"
%in%
method
)
{
if
(
requireNamespace
(
"nortest"
,
quietly
=
TRUE
))
{
tmp
<-
nortest
::
lillie.test
(
x
)
res
<-
tibble
::
add_row
(
res
,
Test
=
"Lilliefors-KS"
,
Statistic
=
tmp
$
statistic
,
p.value
=
tmp
$
p.value
)
}
}
if
(
"ad"
%in%
method
)
{
if
(
requireNamespace
(
"nortest"
,
quietly
=
TRUE
))
{
tmp
<-
nortest
::
ad.test
(
x
)
res
<-
tibble
::
add_row
(
res
,
Test
=
"Anderson-Darling"
,
Statistic
=
tmp
$
statistic
,
p.value
=
tmp
$
p.value
)
}
}
## 6. 样本描述
dat_summary
<-
tibble
::
tibble
(
mean
=
mean
(
x
),
n
=
length
(
x
),
n_missing
=
sum
(
is.na
(
dataset
[[
var
]])),
sd
=
sd
(
x
),
se
=
sd
(
x
)
/
sqrt
(
length
(
x
))
)
)
## 绘图数据
## 7. 绘图对象
plot_obj
<-
list
(
qq
=
list
(
type
=
"qq"
,
data
=
x
),
plot_obj
<-
list
(
qq
=
list
(
type
=
"qq"
,
data
=
x
),
hist
=
list
(
type
=
"hist"
,
data
=
x
),
hist
=
list
(
type
=
"hist"
,
data
=
x
),
pp
=
list
(
type
=
"pp"
,
data
=
x
),
pp
=
list
(
type
=
"pp"
,
data
=
x
),
density
=
list
(
type
=
"density"
,
data
=
x
))
density
=
list
(
type
=
"density"
,
data
=
x
)
)
as.list
(
environment
())
%>%
add_class
(
"normality_test"
)
## 8. 打包返回
out
<-
list
(
df_name
=
df_name
,
var
=
var
,
method
=
method
,
data_filter
=
data_filter
,
res
=
res
,
dat_summary
=
dat_summary
,
x
=
x
,
plot_obj
=
plot_obj
)
class
(
out
)
<-
"normality_test"
out
}
}
# Summary method
# Summary method
...
@@ -47,6 +108,7 @@ summary.normality_test <- function(object, dec = 3, ...) {
...
@@ -47,6 +108,7 @@ summary.normality_test <- function(object, dec = 3, ...) {
## 打印统计量表
## 打印统计量表
object
$
res
%>%
object
$
res
%>%
mutate
(
p.value
=
format.pval
(
p.value
,
digits
=
3
,
eps
=
1e-4
))
%>%
as.data.frame
(
stringsAsFactors
=
FALSE
)
%>%
as.data.frame
(
stringsAsFactors
=
FALSE
)
%>%
format_df
(
dec
=
dec
)
%>%
format_df
(
dec
=
dec
)
%>%
print
(
row.names
=
FALSE
)
print
(
row.names
=
FALSE
)
...
@@ -69,9 +131,18 @@ plot.normality_test <- function(x, plots = c("qq", "hist"),
...
@@ -69,9 +131,18 @@ plot.normality_test <- function(x, plots = c("qq", "hist"),
geom_histogram
(
fill
=
"blue"
,
bins
=
30
)
geom_histogram
(
fill
=
"blue"
,
bins
=
30
)
}
}
if
(
"pp"
%in%
plots
)
{
if
(
"pp"
%in%
plots
)
{
n
<-
length
(
x
$
x
)
i
<-
1
:
n
p
<-
(
i
-
0.5
)
/
n
theoretical
<-
qnorm
(
p
)
empirical
<-
sort
(
scale
(
x
$
x
))
plot_list
[[
which
(
"pp"
==
plots
)]]
<-
plot_list
[[
which
(
"pp"
==
plots
)]]
<-
ggplot
(
data.frame
(
y
=
x
$
x
),
aes
(
sample
=
y
))
+
ggplot
(
data.frame
(
theoretical
=
theoretical
,
empirical
=
empirical
),
aes
(
theoretical
,
empirical
))
+
stat_pp_band
()
+
stat_pp_line
()
+
stat_pp_point
()
geom_point
(
colour
=
"blue"
)
+
geom_abline
(
intercept
=
0
,
slope
=
1
,
linetype
=
"dashed"
,
colour
=
"red"
)
+
labs
(
x
=
"Theoretical quantiles"
,
y
=
"Empirical quantiles"
,
title
=
"P-P plot"
)
+
theme_minimal
()
}
}
if
(
"density"
%in%
plots
)
{
if
(
"density"
%in%
plots
)
{
plot_list
[[
which
(
"density"
==
plots
)]]
<-
plot_list
[[
which
(
"density"
==
plots
)]]
<-
...
...
radiant.basics/inst/app/tools/analysis/homo_variance_test_ui.R
View file @
f926635b
...
@@ -20,31 +20,63 @@ hv_args <- as.list(formals(homo_variance_test))
...
@@ -20,31 +20,63 @@ hv_args <- as.list(formals(homo_variance_test))
hv_inputs
<-
reactive
({
hv_inputs
<-
reactive
({
hv_args
$
data_filter
<-
if
(
input
$
show_filter
)
input
$
data_filter
else
""
hv_args
$
data_filter
<-
if
(
input
$
show_filter
)
input
$
data_filter
else
""
hv_args
$
dataset
<-
input
$
dataset
hv_args
$
dataset
<-
input
$
dataset
hv_args
$
method
<-
input
$
hv_method
# 确保正确收集分组变量和数值变量
for
(
i
in
r_drop
(
names
(
hv_args
)))
{
for
(
i
in
r_drop
(
names
(
hv_args
)))
{
hv_args
[[
i
]]
<-
input
[[
paste0
(
"hv_"
,
i
)]]
hv_args
[[
i
]]
<-
input
[[
paste0
(
"hv_"
,
i
)]]
}
}
hv_args
hv_args
})
})
## 4.
变量选择(numeric + grouping)
## 4.
数值变量选择
output
$
ui_hv_var
<-
renderUI
({
output
$
ui_hv_var
<-
renderUI
({
isNum
<-
.get_class
()
%in%
c
(
"integer"
,
"numeric"
,
"ts"
)
req
(
input
$
dataset
)
vars
<-
c
(
"None"
=
""
,
varnames
()[
isNum
])
current_data
<-
get_data
(
input
$
dataset
,
envir
=
r_data
)
isNum
<-
sapply
(
current_data
,
function
(
col
)
is.numeric
(
col
)
||
is.ts
(
col
))
num_vars
<-
names
(
isNum
)[
isNum
]
if
(
length
(
num_vars
)
==
0
)
{
return
(
div
(
class
=
"alert alert-warning"
,
i
18
n
$
t
(
"No numeric variables in dataset."
)))
}
vars
<-
c
(
"None"
=
""
,
num_vars
)
selectInput
(
selectInput
(
inputId
=
"hv_var"
,
label
=
i
18
n
$
t
(
"Variable (select one):"
),
inputId
=
"hv_var"
,
choices
=
vars
,
selected
=
state_single
(
"hv_var"
,
vars
),
multiple
=
FALSE
label
=
i
18
n
$
t
(
"Variable (select one):"
),
choices
=
vars
,
selected
=
state_single
(
"hv_var"
,
vars
),
multiple
=
FALSE
)
)
})
})
## 5. 分组变量选择
output
$
ui_hv_group
<-
renderUI
({
output
$
ui_hv_group
<-
renderUI
({
vars
<-
groupable_vars
()
req
(
input
$
dataset
)
current_data
<-
get_data
(
input
$
dataset
,
envir
=
r_data
)
# 仅保留因子/字符型变量
group_candidates
<-
names
(
which
(
sapply
(
current_data
,
function
(
col
)
is.factor
(
col
)
||
is.character
(
col
)
)))
# 筛选有效水平≥2的分组变量
valid_groups
<-
character
(
0
)
for
(
grp
in
group_candidates
)
{
grp_vals
<-
current_data
[[
grp
]]
valid_levels
<-
length
(
unique
(
grp_vals
[
!
is.na
(
grp_vals
)]))
if
(
valid_levels
>=
2
)
{
valid_groups
<-
c
(
valid_groups
,
grp
)
}
}
if
(
length
(
valid_groups
)
==
0
)
{
return
(
div
(
class
=
"alert alert-warning"
,
i
18
n
$
t
(
"No valid grouping variables (need ≥2 levels)."
)))
}
selectInput
(
selectInput
(
inputId
=
"hv_group"
,
label
=
i
18
n
$
t
(
"Grouping variable:"
),
inputId
=
"hv_group"
,
choices
=
vars
,
selected
=
state_single
(
"hv_group"
,
vars
),
multiple
=
FALSE
label
=
i
18
n
$
t
(
"Grouping variable:"
),
choices
=
valid_groups
,
selected
=
state_single
(
"hv_group"
,
valid_groups
),
multiple
=
FALSE
)
)
})
})
##
5. 主
UI
##
6. 主
UI
output
$
ui_homo_variance_test
<-
renderUI
({
output
$
ui_homo_variance_test
<-
renderUI
({
req
(
input
$
dataset
)
req
(
input
$
dataset
)
tagList
(
tagList
(
...
@@ -53,22 +85,21 @@ output$ui_homo_variance_test <- renderUI({
...
@@ -53,22 +85,21 @@ output$ui_homo_variance_test <- renderUI({
condition
=
"input.tabs_homo_variance_test == 'Summary'"
,
condition
=
"input.tabs_homo_variance_test == 'Summary'"
,
uiOutput
(
"ui_hv_var"
),
uiOutput
(
"ui_hv_var"
),
uiOutput
(
"ui_hv_group"
),
uiOutput
(
"ui_hv_group"
),
selectInput
(
selectizeInput
(
inputId
=
"hv_method"
,
label
=
i
18
n
$
t
(
"Test method:"
),
inputId
=
"hv_method"
,
label
=
i
18
n
$
t
(
"Test method:"
),
choices
=
hv_method
,
choices
=
hv_method
,
selected
=
state_single
(
"hv_method"
,
hv_method
,
"levene"
),
selected
=
state_multiple
(
"hv_method"
,
hv_method
,
"levene"
),
multiple
=
FALSE
multiple
=
TRUE
,
),
options
=
list
(
placeholder
=
i
18
n
$
t
(
"Select methods"
),
sliderInput
(
plugins
=
list
(
"remove_button"
,
"drag_drop"
))
"hv_conf_lev"
,
i
18
n
$
t
(
"Confidence level:"
),
min
=
0.85
,
max
=
0.99
,
value
=
state_init
(
"hv_conf_lev"
,
0.95
),
step
=
0.01
)
)
),
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.tabs_homo_variance_test == 'Plot'"
,
condition
=
"input.tabs_homo_variance_test == 'Plot'"
,
selectizeInput
(
selectizeInput
(
inputId
=
"hv_plots"
,
label
=
i
18
n
$
t
(
"Select plots:"
),
inputId
=
"hv_plots"
,
label
=
i
18
n
$
t
(
"Select plots:"
),
choices
=
hv_plots
,
choices
=
hv_plots
,
selected
=
state_multiple
(
"hv_plots"
,
hv_plots
,
"boxplot"
),
selected
=
state_multiple
(
"hv_plots"
,
hv_plots
,
"boxplot"
),
multiple
=
TRUE
,
multiple
=
TRUE
,
...
@@ -86,7 +117,7 @@ output$ui_homo_variance_test <- renderUI({
...
@@ -86,7 +117,7 @@ output$ui_homo_variance_test <- renderUI({
)
)
})
})
##
6
. 画图尺寸
##
7
. 画图尺寸
hv_plot
<-
reactive
({
hv_plot
<-
reactive
({
list
(
plot_width
=
650
,
list
(
plot_width
=
650
,
plot_height
=
400
*
max
(
length
(
input
$
hv_plots
),
1
))
plot_height
=
400
*
max
(
length
(
input
$
hv_plots
),
1
))
...
@@ -94,7 +125,7 @@ hv_plot <- reactive({
...
@@ -94,7 +125,7 @@ hv_plot <- reactive({
hv_plot_width
<-
function
()
hv_plot
()
$
plot_width
hv_plot_width
<-
function
()
hv_plot
()
$
plot_width
hv_plot_height
<-
function
()
hv_plot
()
$
plot_height
hv_plot_height
<-
function
()
hv_plot
()
$
plot_height
##
7
. 输出面板
##
8
. 输出面板
output
$
homo_variance_test
<-
renderUI
({
output
$
homo_variance_test
<-
renderUI
({
register_print_output
(
"summary_homo_variance_test"
,
".summary_homo_variance_test"
)
register_print_output
(
"summary_homo_variance_test"
,
".summary_homo_variance_test"
)
register_plot_output
(
"plot_homo_variance_test"
,
".plot_homo_variance_test"
,
register_plot_output
(
"plot_homo_variance_test"
,
".plot_homo_variance_test"
,
...
@@ -102,12 +133,8 @@ output$homo_variance_test <- renderUI({
...
@@ -102,12 +133,8 @@ output$homo_variance_test <- renderUI({
hv_output_panels
<-
tabsetPanel
(
hv_output_panels
<-
tabsetPanel
(
id
=
"tabs_homo_variance_test"
,
id
=
"tabs_homo_variance_test"
,
tabPanel
(
title
=
i
18
n
$
t
(
"Summary"
),
tabPanel
(
title
=
i
18
n
$
t
(
"Summary"
),
value
=
"Summary"
,
verbatimTextOutput
(
"summary_homo_variance_test"
)),
value
=
"Summary"
,
tabPanel
(
title
=
i
18
n
$
t
(
"Plot"
),
value
=
"Plot"
,
download_link
(
"dlp_homo_variance_test"
),
verbatimTextOutput
(
"summary_homo_variance_test"
)),
tabPanel
(
title
=
i
18
n
$
t
(
"Plot"
),
value
=
"Plot"
,
download_link
(
"dlp_homo_variance_test"
),
plotOutput
(
"plot_homo_variance_test"
,
height
=
"100%"
))
plotOutput
(
"plot_homo_variance_test"
,
height
=
"100%"
))
)
)
...
@@ -119,17 +146,34 @@ output$homo_variance_test <- renderUI({
...
@@ -119,17 +146,34 @@ output$homo_variance_test <- renderUI({
)
)
})
})
##
8. 可用性检查
##
9. 可用性检查(强化变量存在性校验)
hv_available
<-
reactive
({
hv_available
<-
reactive
({
if
(
not_available
(
input
$
hv_var
))
req
(
input
$
dataset
)
return
(
i
18
n
$
t
(
"This analysis requires a numeric variable. If none are\navailable please select another dataset."
)
%>%
suggest_data
(
"demand_uk"
))
current_data
<-
get_data
(
input
$
dataset
,
envir
=
r_data
)
if
(
not_available
(
input
$
hv_group
))
return
(
i
18
n
$
t
(
"Please select a grouping variable."
))
# 校验数值变量
if
(
not_available
(
input
$
hv_var
)
||
!
input
$
hv_var
%in%
colnames
(
current_data
))
{
return
(
i
18
n
$
t
(
"Please select a valid numeric variable."
))
}
# 校验分组变量
if
(
not_available
(
input
$
hv_group
)
||
!
input
$
hv_group
%in%
colnames
(
current_data
))
{
return
(
i
18
n
$
t
(
"Please select a valid grouping variable."
))
}
# 校验分组变量水平
group_vals
<-
current_data
[[
input
$
hv_group
]]
valid_levels
<-
length
(
unique
(
group_vals
[
!
is.na
(
group_vals
)]))
if
(
valid_levels
<
2
)
{
return
(
i
18
n
$
t
(
"Grouping variable has <2 valid levels. Choose another."
))
}
"available"
"available"
})
})
##
9
. 计算核心
##
10
. 计算核心
.homo_variance_test
<-
reactive
({
.homo_variance_test
<-
reactive
({
req
(
hv_available
()
==
"available"
)
# 确保通过可用性检查
hvi
<-
hv_inputs
()
hvi
<-
hv_inputs
()
hvi
$
envir
<-
r_data
hvi
$
envir
<-
r_data
do.call
(
homo_variance_test
,
hvi
)
do.call
(
homo_variance_test
,
hvi
)
...
@@ -142,33 +186,18 @@ hv_available <- reactive({
...
@@ -142,33 +186,18 @@ hv_available <- reactive({
.plot_homo_variance_test
<-
reactive
({
.plot_homo_variance_test
<-
reactive
({
if
(
hv_available
()
!=
"available"
)
return
(
hv_available
())
if
(
hv_available
()
!=
"available"
)
return
(
hv_available
())
validate
(
need
(
input
$
hv_plots
,
i
18
n
$
t
(
"
Nothing to plot. Please select a plot type
"
)))
validate
(
need
(
input
$
hv_plots
,
i
18
n
$
t
(
"
Select plot types first
"
)))
withProgress
(
message
=
i
18
n
$
t
(
"Generating plots"
),
value
=
1
,
withProgress
(
message
=
i
18
n
$
t
(
"Generating plots"
),
value
=
1
,
plot
(
.homo_variance_test
(),
plots
=
input
$
hv_plots
,
shiny
=
TRUE
))
plot
(
.homo_variance_test
(),
plots
=
input
$
hv_plots
,
shiny
=
TRUE
))
})
})
## 10. Report
homo_variance_test_report
<-
function
()
{
if
(
is.empty
(
input
$
hv_var
))
return
(
invisible
())
figs
<-
length
(
input
$
hv_plots
)
>
0
outputs
<-
if
(
figs
)
c
(
"summary"
,
"plot"
)
else
"summary"
inp_out
<-
if
(
figs
)
list
(
""
,
list
(
plots
=
input
$
hv_plots
,
custom
=
FALSE
))
else
list
(
""
,
""
)
update_report
(
inp_main
=
clean_args
(
hv_inputs
(),
hv_args
),
fun_name
=
"homo_variance_test"
,
inp_out
=
inp_out
,
outputs
=
outputs
,
figs
=
figs
,
fig.width
=
hv_plot_width
(),
fig.height
=
hv_plot_height
())
}
## 11. 下载 & 截图
## 11. 下载 & 截图
download_handler
(
download_handler
(
id
=
"dlp_homo_variance_test"
,
id
=
"dlp_homo_variance_test"
,
fun
=
download_handler_plot
,
fun
=
download_handler_plot
,
fn
=
function
()
paste0
(
input
$
dataset
,
"_homo_variance_test"
),
fn
=
function
()
paste0
(
input
$
dataset
,
"_homo_variance_test"
),
type
=
"png"
,
type
=
"png"
,
caption
=
i
18
n
$
t
(
"Save
homogeneity of variance
plot"
),
caption
=
i
18
n
$
t
(
"Save plot"
),
plot
=
.plot_homo_variance_test
,
plot
=
.plot_homo_variance_test
,
width
=
hv_plot_width
,
width
=
hv_plot_width
,
height
=
hv_plot_height
height
=
hv_plot_height
...
...
radiant.basics/inst/app/tools/analysis/normality_test_ui.R
View file @
f926635b
...
@@ -3,7 +3,7 @@
...
@@ -3,7 +3,7 @@
############################################
############################################
## 1. 翻译标签
## 1. 翻译标签
nt_method
<-
c
(
"shapiro"
,
"ks"
,
"ad"
)
# 先给 3 个常用方法
nt_method
<-
c
(
"shapiro"
,
"ks"
,
"ad"
)
names
(
nt_method
)
<-
c
(
i
18
n
$
t
(
"Shapiro-Wilk"
),
names
(
nt_method
)
<-
c
(
i
18
n
$
t
(
"Shapiro-Wilk"
),
i
18
n
$
t
(
"Kolmogorov-Smirnov"
),
i
18
n
$
t
(
"Kolmogorov-Smirnov"
),
i
18
n
$
t
(
"Anderson-Darling"
))
i
18
n
$
t
(
"Anderson-Darling"
))
...
@@ -21,13 +21,19 @@ nt_args <- as.list(formals(normality_test))
...
@@ -21,13 +21,19 @@ nt_args <- as.list(formals(normality_test))
nt_inputs
<-
reactive
({
nt_inputs
<-
reactive
({
nt_args
$
data_filter
<-
if
(
input
$
show_filter
)
input
$
data_filter
else
""
nt_args
$
data_filter
<-
if
(
input
$
show_filter
)
input
$
data_filter
else
""
nt_args
$
dataset
<-
input
$
dataset
nt_args
$
dataset
<-
input
$
dataset
for
(
i
in
r_drop
(
names
(
nt_args
)))
{
for
(
i
in
r_drop
(
names
(
nt_args
)))
{
nt_args
[[
i
]]
<-
input
[[
paste0
(
"nt_"
,
i
)]]
input_key
<-
paste0
(
"nt_"
,
i
)
if
(
!
is.null
(
input
[[
input_key
]]))
{
nt_args
[[
i
]]
<-
input
[[
input_key
]]
}
}
}
nt_args
$
method
<-
input
$
nt_method
nt_args
nt_args
})
})
## 4. 变量选择
(仅 numeric)
## 4. 变量选择
output
$
ui_nt_var
<-
renderUI
({
output
$
ui_nt_var
<-
renderUI
({
isNum
<-
.get_class
()
%in%
c
(
"integer"
,
"numeric"
,
"ts"
)
isNum
<-
.get_class
()
%in%
c
(
"integer"
,
"numeric"
,
"ts"
)
vars
<-
c
(
"None"
=
""
,
varnames
()[
isNum
])
vars
<-
c
(
"None"
=
""
,
varnames
()[
isNum
])
...
@@ -45,16 +51,13 @@ output$ui_normality_test <- renderUI({
...
@@ -45,16 +51,13 @@ output$ui_normality_test <- renderUI({
conditionalPanel
(
conditionalPanel
(
condition
=
"input.tabs_normality_test == 'Summary'"
,
condition
=
"input.tabs_normality_test == 'Summary'"
,
uiOutput
(
"ui_nt_var"
),
uiOutput
(
"ui_nt_var"
),
selectInput
(
select
ize
Input
(
inputId
=
"nt_method"
,
label
=
i
18
n
$
t
(
"Test method:"
),
inputId
=
"nt_method"
,
label
=
i
18
n
$
t
(
"Test method:"
),
choices
=
nt_method
,
choices
=
nt_method
,
selected
=
state_single
(
"nt_method"
,
nt_method
,
"shapiro"
),
selected
=
state_multiple
(
"nt_method"
,
nt_method
,
"shapiro"
),
multiple
=
FALSE
multiple
=
TRUE
,
),
options
=
list
(
placeholder
=
i
18
n
$
t
(
"Select methods"
),
sliderInput
(
plugins
=
list
(
"remove_button"
,
"drag_drop"
))
"nt_conf_lev"
,
i
18
n
$
t
(
"Confidence level:"
),
min
=
0.85
,
max
=
0.99
,
value
=
state_init
(
"nt_conf_lev"
,
0.95
),
step
=
0.01
)
)
),
),
conditionalPanel
(
conditionalPanel
(
...
@@ -122,11 +125,13 @@ nt_available <- reactive({
...
@@ -122,11 +125,13 @@ nt_available <- reactive({
## 9. 计算核心
## 9. 计算核心
.normality_test
<-
reactive
({
.normality_test
<-
reactive
({
nti
<-
nt_inputs
()
nti
<-
nt_inputs
()
req
(
nti
$
method
,
nti
$
var
)
nti
$
envir
<-
r_data
nti
$
envir
<-
r_data
do.call
(
normality_test
,
nti
)
do.call
(
normality_test
,
nti
)
})
})
.summary_normality_test
<-
reactive
({
.summary_normality_test
<-
reactive
({
input
$
nt_method
if
(
nt_available
()
!=
"available"
)
return
(
nt_available
())
if
(
nt_available
()
!=
"available"
)
return
(
nt_available
())
summary
(
.normality_test
())
summary
(
.normality_test
())
})
})
...
...
radiant.data/DESCRIPTION
View file @
f926635b
...
@@ -47,6 +47,7 @@ Imports:
...
@@ -47,6 +47,7 @@ Imports:
png,
png,
MASS,
MASS,
base64enc,
base64enc,
shinyalert,
shiny.i18n
shiny.i18n
Suggests:
Suggests:
arrow (>= 12.0.1),
arrow (>= 12.0.1),
...
...
radiant.data/inst/app/global.R
View file @
f926635b
...
@@ -603,8 +603,7 @@ options(
...
@@ -603,8 +603,7 @@ options(
tabPanel
(
tabPanel
(
actionLink
(
actionLink
(
"stop_radiant"
,
i
18
n
$
t
(
"Stop"
),
"stop_radiant"
,
i
18
n
$
t
(
"Stop"
),
icon
=
icon
(
"stop"
,
verify_fa
=
FALSE
),
icon
=
icon
(
"stop"
,
verify_fa
=
FALSE
)
onclick
=
"setTimeout(function(){window.close();}, 100);"
)
)
),
),
tabPanel
(
tags
$
a
(
tabPanel
(
tags
$
a
(
...
...
radiant.data/inst/app/tools/app/stop.R
View file @
f926635b
...
@@ -2,6 +2,19 @@
...
@@ -2,6 +2,19 @@
# Stop menu
# Stop menu
#######################################
#######################################
observeEvent
(
input
$
stop_radiant
,
{
observeEvent
(
input
$
stop_radiant
,
{
shinyalert
::
shinyalert
(
title
=
"确认停止"
,
text
=
"停止按钮会将所有容器都关闭!确定停止吗?"
,
type
=
"warning"
,
showCancelButton
=
TRUE
,
confirmButtonCol
=
"#d33"
,
confirmButtonText
=
"确定"
,
cancelButtonText
=
"取消"
,
callbackJS
=
"function(x){if(x){Shiny.setInputValue('really_stop',Math.random());}}"
)
})
observeEvent
(
input
$
really_stop
,
{
if
(
isTRUE
(
getOption
(
"radiant.local"
)))
stop_radiant
()
if
(
isTRUE
(
getOption
(
"radiant.local"
)))
stop_radiant
()
})
})
...
...
radiant.data/inst/app/tools/data/visualize_ui.R
View file @
f926635b
#############################################
is.empty
<-
function
(
x
,
empty
=
"\\s*"
)
{
# 安全封装:避免 is.empty() 报错
if
(
is.null
(
x
))
return
(
TRUE
)
#############################################
if
(
is.atomic
(
x
)
&&
length
(
x
)
==
0
)
return
(
TRUE
)
safe_is_empty
<-
function
(
x
)
{
if
(
!
is.character
(
x
))
return
(
FALSE
)
i
f
(
is.null
(
x
)
||
!
is.character
(
x
))
return
(
TRUE
)
i
s_not
(
x
)
||
is.empty
(
x
)
(
length
(
x
)
==
1
&&
any
(
grepl
(
paste0
(
"^"
,
empty
,
"$"
),
x
))
)
}
}
#############################################
# 其余代码保持不变,仅替换 is.empty() 调用
#############################################
viz_type
<-
c
(
viz_type
<-
c
(
"分布图(dist)"
=
"dist"
,
"密度图(density)"
=
"density"
,
"散点图(scatter)"
=
"scatter"
,
"分布图(dist)"
=
"dist"
,
"密度图(density)"
=
"density"
,
"散点图(scatter)"
=
"scatter"
,
"曲面图(surface)"
=
"surface"
,
"折线图(line)"
=
"line"
,
"条形图(bar)"
=
"bar"
,
"箱线图(box)"
=
"box"
"曲面图(surface)"
=
"surface"
,
"折线图(line)"
=
"line"
,
"条形图(bar)"
=
"bar"
,
"箱线图(box)"
=
"box"
...
@@ -46,14 +42,17 @@ viz_add_labs <- function() {
...
@@ -46,14 +42,17 @@ viz_add_labs <- function() {
lab_list
<-
list
()
lab_list
<-
list
()
for
(
l
in
viz_labs
)
{
for
(
l
in
viz_labs
)
{
inp
<-
input
[[
paste0
(
"viz_labs_"
,
l
)]]
inp
<-
input
[[
paste0
(
"viz_labs_"
,
l
)]]
if
(
!
safe_is_
empty
(
inp
))
lab_list
[[
l
]]
<-
inp
if
(
!
is.
empty
(
inp
))
lab_list
[[
l
]]
<-
inp
}
}
lab_list
lab_list
}
}
## list of function arguments
viz_args
<-
as.list
(
formals
(
visualize
))
viz_args
<-
as.list
(
formals
(
visualize
))
## list of function inputs selected by user
viz_inputs
<-
reactive
({
viz_inputs
<-
reactive
({
## loop needed because reactive values don't allow single bracket indexing
viz_args
$
data_filter
<-
if
(
isTRUE
(
input
$
show_filter
))
input
$
data_filter
else
""
viz_args
$
data_filter
<-
if
(
isTRUE
(
input
$
show_filter
))
input
$
data_filter
else
""
viz_args
$
arr
<-
if
(
isTRUE
(
input
$
show_filter
))
input
$
data_arrange
else
""
viz_args
$
arr
<-
if
(
isTRUE
(
input
$
show_filter
))
input
$
data_arrange
else
""
viz_args
$
rows
<-
if
(
isTRUE
(
input
$
show_filter
))
input
$
data_rows
else
""
viz_args
$
rows
<-
if
(
isTRUE
(
input
$
show_filter
))
input
$
data_rows
else
""
...
@@ -63,9 +62,16 @@ viz_inputs <- reactive({
...
@@ -63,9 +62,16 @@ viz_inputs <- reactive({
for
(
i
in
r_drop
(
names
(
viz_args
),
drop
=
c
(
i
18
n
$
t
(
"dataset"
),
i
18
n
$
t
(
"data_filter"
),
i
18
n
$
t
(
"arr"
),
i
18
n
$
t
(
"rows"
),
i
18
n
$
t
(
"labs"
))))
{
for
(
i
in
r_drop
(
names
(
viz_args
),
drop
=
c
(
i
18
n
$
t
(
"dataset"
),
i
18
n
$
t
(
"data_filter"
),
i
18
n
$
t
(
"arr"
),
i
18
n
$
t
(
"rows"
),
i
18
n
$
t
(
"labs"
))))
{
viz_args
[[
i
]]
<-
input
[[
paste0
(
"viz_"
,
i
)]]
viz_args
[[
i
]]
<-
input
[[
paste0
(
"viz_"
,
i
)]]
}
}
# isolate({
# # cat(paste0(names(viz_args), " ", viz_args, collapse = ", "), file = stderr(), "\n")
# cat(paste0(names(viz_args), " = ", viz_args, collapse = ", "), "\n")
# })
viz_args
viz_args
})
})
#######################################
# Visualize data
#######################################
output
$
ui_viz_type
<-
renderUI
({
output
$
ui_viz_type
<-
renderUI
({
selectInput
(
selectInput
(
inputId
=
"viz_type"
,
label
=
i
18
n
$
t
(
"Plot-type:"
),
choices
=
viz_type
,
inputId
=
"viz_type"
,
label
=
i
18
n
$
t
(
"Plot-type:"
),
choices
=
viz_type
,
...
@@ -86,6 +92,7 @@ output$ui_viz_nrobs <- renderUI({
...
@@ -86,6 +92,7 @@ output$ui_viz_nrobs <- renderUI({
)
)
})
})
## Y - variable
output
$
ui_viz_yvar
<-
renderUI
({
output
$
ui_viz_yvar
<-
renderUI
({
req
(
input
$
viz_type
)
req
(
input
$
viz_type
)
vars
<-
varying_vars
()
vars
<-
varying_vars
()
...
@@ -95,8 +102,10 @@ output$ui_viz_yvar <- renderUI({
...
@@ -95,8 +102,10 @@ output$ui_viz_yvar <- renderUI({
vars
<-
vars
[
"character"
!=
.get_class
()[
vars
]]
vars
<-
vars
[
"character"
!=
.get_class
()[
vars
]]
}
}
if
(
input
$
viz_type
%in%
c
(
"box"
,
"scatter"
))
{
if
(
input
$
viz_type
%in%
c
(
"box"
,
"scatter"
))
{
## allow factors in yvars for bar plots
vars
<-
vars
[
"factor"
!=
.get_class
()[
vars
]]
vars
<-
vars
[
"factor"
!=
.get_class
()[
vars
]]
}
}
selectInput
(
selectInput
(
inputId
=
"viz_yvar"
,
label
=
i
18
n
$
t
(
"Y-variable:"
),
inputId
=
"viz_yvar"
,
label
=
i
18
n
$
t
(
"Y-variable:"
),
choices
=
vars
,
choices
=
vars
,
...
@@ -105,6 +114,8 @@ output$ui_viz_yvar <- renderUI({
...
@@ -105,6 +114,8 @@ output$ui_viz_yvar <- renderUI({
)
)
})
})
## X - variable
output
$
ui_viz_xvar
<-
renderUI
({
output
$
ui_viz_xvar
<-
renderUI
({
req
(
input
$
viz_type
)
req
(
input
$
viz_type
)
vars
<-
varying_vars
()
vars
<-
varying_vars
()
...
@@ -112,6 +123,7 @@ output$ui_viz_xvar <- renderUI({
...
@@ -112,6 +123,7 @@ output$ui_viz_xvar <- renderUI({
if
(
input
$
viz_type
==
"dist"
)
vars
<-
vars
[
"date"
!=
.get_class
()[
vars
]]
if
(
input
$
viz_type
==
"dist"
)
vars
<-
vars
[
"date"
!=
.get_class
()[
vars
]]
if
(
input
$
viz_type
==
"density"
)
vars
<-
vars
[
"factor"
!=
.get_class
()[
vars
]]
if
(
input
$
viz_type
==
"density"
)
vars
<-
vars
[
"factor"
!=
.get_class
()[
vars
]]
if
(
input
$
viz_type
%in%
c
(
"box"
,
"bar"
))
vars
<-
groupable_vars_nonum
()
if
(
input
$
viz_type
%in%
c
(
"box"
,
"bar"
))
vars
<-
groupable_vars_nonum
()
selectInput
(
selectInput
(
inputId
=
"viz_xvar"
,
label
=
i
18
n
$
t
(
"X-variable:"
),
choices
=
vars
,
inputId
=
"viz_xvar"
,
label
=
i
18
n
$
t
(
"X-variable:"
),
choices
=
vars
,
selected
=
state_multiple
(
"viz_xvar"
,
vars
,
isolate
(
input
$
viz_xvar
)),
selected
=
state_multiple
(
"viz_xvar"
,
vars
,
isolate
(
input
$
viz_xvar
)),
...
@@ -180,6 +192,7 @@ output$ui_viz_color <- renderUI({
...
@@ -180,6 +192,7 @@ output$ui_viz_color <- renderUI({
}
else
{
}
else
{
vars
<-
c
(
"None"
=
"none"
,
varnames
())
vars
<-
c
(
"None"
=
"none"
,
varnames
())
}
}
if
(
isTRUE
(
input
$
viz_comby
)
&&
length
(
input
$
viz_yvar
)
>
1
)
vars
<-
c
(
"None"
=
"none"
)
if
(
isTRUE
(
input
$
viz_comby
)
&&
length
(
input
$
viz_yvar
)
>
1
)
vars
<-
c
(
"None"
=
"none"
)
selectizeInput
(
selectizeInput
(
"viz_color"
,
i
18
n
$
t
(
"Color:"
),
vars
,
"viz_color"
,
i
18
n
$
t
(
"Color:"
),
vars
,
...
@@ -223,6 +236,7 @@ output$ui_viz_axes <- renderUI({
...
@@ -223,6 +236,7 @@ output$ui_viz_axes <- renderUI({
ind
<-
c
(
1
,
3
)
ind
<-
c
(
1
,
3
)
}
}
if
(
input
$
viz_facet_row
!=
"."
||
input
$
viz_facet_col
!=
"."
)
ind
<-
c
(
ind
,
4
)
if
(
input
$
viz_facet_row
!=
"."
||
input
$
viz_facet_col
!=
"."
)
ind
<-
c
(
ind
,
4
)
# if (input$viz_type == "bar" && input$viz_facet_row == "." && input$viz_facet_col == ".") ind <- c(ind, 6)
if
(
input
$
viz_type
==
"bar"
)
ind
<-
c
(
ind
,
6
)
if
(
input
$
viz_type
==
"bar"
)
ind
<-
c
(
ind
,
6
)
checkboxGroupInput
(
checkboxGroupInput
(
...
@@ -243,6 +257,7 @@ output$ui_viz_check <- renderUI({
...
@@ -243,6 +257,7 @@ output$ui_viz_check <- renderUI({
}
else
{
}
else
{
ind
<-
c
()
ind
<-
c
()
}
}
if
(
!
input
$
viz_type
%in%
c
(
"scatter"
,
"box"
))
{
if
(
!
input
$
viz_type
%in%
c
(
"scatter"
,
"box"
))
{
r_state
$
viz_check
<<-
gsub
(
"jitter"
,
""
,
r_state
$
viz_check
)
r_state
$
viz_check
<<-
gsub
(
"jitter"
,
""
,
r_state
$
viz_check
)
}
}
...
@@ -250,6 +265,7 @@ output$ui_viz_check <- renderUI({
...
@@ -250,6 +265,7 @@ output$ui_viz_check <- renderUI({
r_state
$
viz_check
<<-
gsub
(
"line"
,
""
,
r_state
$
viz_check
)
r_state
$
viz_check
<<-
gsub
(
"line"
,
""
,
r_state
$
viz_check
)
r_state
$
viz_check
<<-
gsub
(
"loess"
,
""
,
r_state
$
viz_check
)
r_state
$
viz_check
<<-
gsub
(
"loess"
,
""
,
r_state
$
viz_check
)
}
}
checkboxGroupInput
(
checkboxGroupInput
(
"viz_check"
,
NULL
,
viz_check
[
ind
],
"viz_check"
,
NULL
,
viz_check
[
ind
],
selected
=
state_group
(
"viz_check"
,
""
),
selected
=
state_group
(
"viz_check"
,
""
),
...
@@ -258,11 +274,15 @@ output$ui_viz_check <- renderUI({
...
@@ -258,11 +274,15 @@ output$ui_viz_check <- renderUI({
})
})
output
$
ui_viz_run
<-
renderUI
({
output
$
ui_viz_run
<-
renderUI
({
## updates when dataset changes
req
(
input
$
dataset
)
req
(
input
$
dataset
)
actionButton
(
"viz_run"
,
i
18
n
$
t
(
"Create plot"
),
width
=
"100%"
,
icon
=
icon
(
"play"
,
verify_fa
=
FALSE
),
class
=
"btn-success"
)
actionButton
(
"viz_run"
,
i
18
n
$
t
(
"Create plot"
),
width
=
"100%"
,
icon
=
icon
(
"play"
,
verify_fa
=
FALSE
),
class
=
"btn-success"
)
## this didn't seem to work quite like the observe below
## https://stackoverflow.com/questions/43641103/change-color-actionbutton-shiny-r
})
})
output
$
ui_viz_labs
<-
renderUI
({
output
$
ui_viz_labs
<-
renderUI
({
## updates when dataset changes
req
(
input
$
dataset
)
req
(
input
$
dataset
)
wellPanel
(
wellPanel
(
textAreaInput
(
"viz_labs_title"
,
NULL
,
""
,
placeholder
=
i
18
n
$
t
(
"Title"
),
rows
=
1
),
textAreaInput
(
"viz_labs_title"
,
NULL
,
""
,
placeholder
=
i
18
n
$
t
(
"Title"
),
rows
=
1
),
...
@@ -276,7 +296,10 @@ output$ui_viz_labs <- renderUI({
...
@@ -276,7 +296,10 @@ output$ui_viz_labs <- renderUI({
output
$
ui_viz_colors
<-
renderUI
({
output
$
ui_viz_colors
<-
renderUI
({
tagList
(
tagList
(
conditionalPanel
(
conditionalPanel
(
condition
=
"input.viz_type == 'bar' || input.viz_type == 'dist' || input.viz_type == 'box' || input.viz_type == 'density'"
,
condition
=
"input.viz_type == 'bar' ||
input.viz_type == 'dist' ||
input.viz_type == 'box' ||
input.viz_type == 'density'"
,
selectInput
(
selectInput
(
"viz_fillcol"
,
i
18
n
$
t
(
"Fill color:"
),
"viz_fillcol"
,
i
18
n
$
t
(
"Fill color:"
),
choices
=
colors
(),
choices
=
colors
(),
...
@@ -284,7 +307,11 @@ output$ui_viz_colors <- renderUI({
...
@@ -284,7 +307,11 @@ output$ui_viz_colors <- renderUI({
)
)
),
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.viz_type == 'dist' || input.viz_type == 'density' || input.viz_type == 'box' || input.viz_type == 'scatter' || input.viz_type == 'line'"
,
condition
=
"input.viz_type == 'dist' ||
input.viz_type == 'density' ||
input.viz_type == 'box' ||
input.viz_type == 'scatter' ||
input.viz_type == 'line'"
,
selectInput
(
selectInput
(
"viz_linecol"
,
i
18
n
$
t
(
"Line color:"
),
"viz_linecol"
,
i
18
n
$
t
(
"Line color:"
),
choices
=
colors
(),
choices
=
colors
(),
...
@@ -292,7 +319,9 @@ output$ui_viz_colors <- renderUI({
...
@@ -292,7 +319,9 @@ output$ui_viz_colors <- renderUI({
)
)
),
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.viz_type == 'scatter' || input.viz_type == 'line' || input.viz_type == 'box'"
,
condition
=
"input.viz_type == 'scatter' ||
input.viz_type == 'line' ||
input.viz_type == 'box'"
,
selectInput
(
selectInput
(
"viz_pointcol"
,
i
18
n
$
t
(
"Point color:"
),
"viz_pointcol"
,
i
18
n
$
t
(
"Point color:"
),
choices
=
colors
(),
choices
=
colors
(),
...
@@ -302,6 +331,7 @@ output$ui_viz_colors <- renderUI({
...
@@ -302,6 +331,7 @@ output$ui_viz_colors <- renderUI({
)
)
})
})
## add a spinning refresh icon if the graph needs to be (re)recreated
run_refresh
(
run_refresh
(
viz_args
,
"viz"
,
viz_args
,
"viz"
,
init
=
c
(
"xvar"
,
"yvar"
),
label
=
i
18
n
$
t
(
"Create plot"
),
relabel
=
i
18
n
$
t
(
"Update plot"
),
init
=
c
(
"xvar"
,
"yvar"
),
label
=
i
18
n
$
t
(
"Create plot"
),
relabel
=
i
18
n
$
t
(
"Update plot"
),
...
@@ -341,11 +371,16 @@ output$ui_Visualize <- renderUI({
...
@@ -341,11 +371,16 @@ output$ui_Visualize <- renderUI({
uiOutput
(
"ui_viz_facet_row"
),
uiOutput
(
"ui_viz_facet_row"
),
uiOutput
(
"ui_viz_facet_col"
),
uiOutput
(
"ui_viz_facet_col"
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.viz_type == 'bar' || input.viz_type == 'dist' || input.viz_type == 'density' || input.viz_type == 'surface'"
,
condition
=
"input.viz_type == 'bar' ||
input.viz_type == 'dist' ||
input.viz_type == 'density' ||
input.viz_type == 'surface'"
,
uiOutput
(
"ui_viz_fill"
)
uiOutput
(
"ui_viz_fill"
)
),
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.viz_type == 'scatter' || input.viz_type == 'line' || input.viz_type == 'box'"
,
condition
=
"input.viz_type == 'scatter' ||
input.viz_type == 'line' ||
input.viz_type == 'box'"
,
uiOutput
(
"ui_viz_color"
)
uiOutput
(
"ui_viz_color"
)
),
),
conditionalPanel
(
conditionalPanel
(
...
@@ -353,7 +388,9 @@ output$ui_Visualize <- renderUI({
...
@@ -353,7 +388,9 @@ output$ui_Visualize <- renderUI({
uiOutput
(
"ui_viz_size"
)
uiOutput
(
"ui_viz_size"
)
),
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.viz_type == 'bar' || input.viz_type == 'scatter' || input.viz_type == 'line'"
,
condition
=
"input.viz_type == 'bar' ||
input.viz_type == 'scatter' ||
input.viz_type == 'line'"
,
selectInput
(
selectInput
(
"viz_fun"
,
i
18
n
$
t
(
"Function:"
),
"viz_fun"
,
i
18
n
$
t
(
"Function:"
),
choices
=
getOption
(
"radiant.functions"
),
choices
=
getOption
(
"radiant.functions"
),
...
@@ -361,7 +398,10 @@ output$ui_Visualize <- renderUI({
...
@@ -361,7 +398,10 @@ output$ui_Visualize <- renderUI({
)
)
),
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.viz_type == 'scatter' || input.viz_type == 'line' || input.viz_type == 'surface' || input.viz_type == 'box'"
,
condition
=
"input.viz_type == 'scatter' ||
input.viz_type == 'line' ||
input.viz_type == 'surface' ||
input.viz_type == 'box'"
,
uiOutput
(
"ui_viz_check"
)
uiOutput
(
"ui_viz_check"
)
),
),
uiOutput
(
"ui_viz_axes"
),
uiOutput
(
"ui_viz_axes"
),
...
@@ -375,7 +415,9 @@ output$ui_Visualize <- renderUI({
...
@@ -375,7 +415,9 @@ output$ui_Visualize <- renderUI({
)
)
),
),
conditionalPanel
(
conditionalPanel
(
"input.viz_type == 'density' || input.viz_type == 'dist' && (input.viz_axes && input.viz_axes.indexOf('density')) >= 0 || (input.viz_type == 'scatter' && (input.viz_check && input.viz_check.indexOf('loess') >= 0))"
,
"input.viz_type == 'density' ||
input.viz_type == 'dist' && (input.viz_axes && input.viz_axes.indexOf('density')) >= 0 ||
(input.viz_type == 'scatter' && (input.viz_check && input.viz_check.indexOf('loess') >= 0))"
,
sliderInput
(
sliderInput
(
"viz_smooth"
,
"viz_smooth"
,
label
=
i
18
n
$
t
(
"Smooth:"
),
label
=
i
18
n
$
t
(
"Smooth:"
),
...
@@ -448,9 +490,10 @@ output$ui_Visualize <- renderUI({
...
@@ -448,9 +490,10 @@ output$ui_Visualize <- renderUI({
})
})
viz_plot_width
<-
reactive
({
viz_plot_width
<-
reactive
({
if
(
safe_is_
empty
(
input
$
viz_plot_width
))
r_info
[[
"plot_width"
]]
else
input
$
viz_plot_width
if
(
is.
empty
(
input
$
viz_plot_width
))
r_info
[[
"plot_width"
]]
else
input
$
viz_plot_width
})
})
## based on https://stackoverflow.com/a/40182833/1974918
viz_plot_height
<-
eventReactive
(
viz_plot_height
<-
eventReactive
(
{
{
input
$
viz_run
input
$
viz_run
...
@@ -458,11 +501,12 @@ viz_plot_height <- eventReactive(
...
@@ -458,11 +501,12 @@ viz_plot_height <- eventReactive(
input
$
viz_plot_width
input
$
viz_plot_width
},
},
{
{
if
(
safe_is_
empty
(
input
$
viz_plot_height
))
{
if
(
is.
empty
(
input
$
viz_plot_height
))
{
r_info
[[
"plot_height"
]]
r_info
[[
"plot_height"
]]
}
else
{
}
else
{
lx
<-
ifelse
(
not_available
(
input
$
viz_xvar
)
||
isTRUE
(
input
$
viz_combx
),
1
,
length
(
input
$
viz_xvar
))
lx
<-
ifelse
(
not_available
(
input
$
viz_xvar
)
||
isTRUE
(
input
$
viz_combx
),
1
,
length
(
input
$
viz_xvar
))
ly
<-
ifelse
(
not_available
(
input
$
viz_yvar
)
||
input
$
viz_type
%in%
c
(
"dist"
,
"density"
)
||
isTRUE
(
input
$
viz_comby
),
1
,
length
(
input
$
viz_yvar
))
ly
<-
ifelse
(
not_available
(
input
$
viz_yvar
)
||
input
$
viz_type
%in%
c
(
"dist"
,
"density"
)
||
isTRUE
(
input
$
viz_comby
),
1
,
length
(
input
$
viz_yvar
))
nr
<-
lx
*
ly
nr
<-
lx
*
ly
if
(
nr
>
1
)
{
if
(
nr
>
1
)
{
(
input
$
viz_plot_height
/
2
)
*
ceiling
(
nr
/
2
)
(
input
$
viz_plot_height
/
2
)
*
ceiling
(
nr
/
2
)
...
@@ -473,38 +517,78 @@ viz_plot_height <- eventReactive(
...
@@ -473,38 +517,78 @@ viz_plot_height <- eventReactive(
}
}
)
)
output
$
visualize
<-
renderPlot
({
output
$
visualize
<-
renderPlot
(
{
req
(
input
$
viz_type
)
req
(
input
$
viz_type
)
p
<-
.visualize
()
if
(
not_available
(
input
$
viz_xvar
))
{
if
(
is.null
(
p
))
return
(
NULL
)
if
(
!
input
$
viz_type
%in%
c
(
"box"
,
"line"
))
{
print
(
p
)
return
(
},
width
=
viz_plot_width
,
height
=
viz_plot_height
,
res
=
96
)
plot
(
x
=
1
,
type
=
"n"
,
main
=
i
18
n
$
t
(
"Please select variables from the dropdown menus to create a plot"
),
axes
=
FALSE
,
xlab
=
""
,
ylab
=
""
,
cex.main
=
.9
)
)
}
}
.visualize
()
%>%
(
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
=
viz_plot_width
,
height
=
viz_plot_height
,
res
=
96
)
.visualize
<-
eventReactive
(
input
$
viz_run
,
{
.visualize
<-
eventReactive
(
input
$
viz_run
,
{
req
(
input
$
viz_type
)
req
(
input
$
viz_type
)
if
(
input
$
viz_type
==
"scatter"
)
req
(
input
$
viz_nrobs
)
if
(
input
$
viz_type
==
"scatter"
)
req
(
input
$
viz_nrobs
)
## need dependency on ..
req
(
input
$
viz_plot_height
&&
input
$
viz_plot_width
)
req
(
input
$
viz_plot_height
&&
input
$
viz_plot_width
)
if
(
not_available
(
input
$
viz_xvar
)
&&
!
input
$
viz_type
%in%
c
(
"box"
,
"line"
))
{
if
(
not_available
(
input
$
viz_xvar
)
&&
!
input
$
viz_type
%in%
c
(
"box"
,
"line"
))
{
return
(
NULL
)
return
()
}
else
if
(
input
$
viz_type
%in%
c
(
"scatter"
,
"line"
,
"box"
,
"bar"
,
"surface"
)
&&
not_available
(
input
$
viz_yvar
))
{
return
(
i
18
n
$
t
(
"No Y-variable provided for a plot that requires one"
))
}
else
if
(
input
$
viz_type
==
"box"
&&
!
all
(
input
$
viz_xvar
%in%
groupable_vars
()))
{
return
()
}
## waiting for comby and/or combx to be updated
if
(
input
$
viz_type
%in%
c
(
"dist"
,
"density"
))
{
if
(
isTRUE
(
input
$
viz_comby
))
{
return
()
}
if
(
length
(
input
$
viz_xvar
)
>
1
&&
is.null
(
input
$
viz_combx
))
{
return
()
}
}
else
{
if
(
isTRUE
(
input
$
viz_combx
))
{
return
()
}
if
(
length
(
input
$
viz_yvar
)
>
1
&&
is.null
(
input
$
viz_comby
))
{
return
()
}
}
if
(
input
$
viz_type
%in%
c
(
"scatter"
,
"line"
,
"box"
,
"bar"
,
"surface"
)
&&
not_available
(
input
$
viz_yvar
))
{
return
(
NULL
)
}
}
req
(
!
is.null
(
input
$
viz_color
)
||
!
is.null
(
input
$
viz_fill
))
vizi
<-
viz_inputs
()
vizi
<-
viz_inputs
()
vizi
$
dataset
<-
input
$
dataset
vizi
$
dataset
<-
input
$
dataset
vizi
$
shiny
<-
TRUE
vizi
$
shiny
<-
TRUE
vizi
$
envir
<-
r_data
vizi
$
envir
<-
r_data
withProgress
(
message
=
i
18
n
$
t
(
"Making plot"
),
value
=
1
,
{
withProgress
(
message
=
i
18
n
$
t
(
"Making plot"
),
value
=
1
,
{
p
<-
do.call
(
visualize
,
vizi
)
do.call
(
visualize
,
vizi
)
if
(
is.character
(
p
))
return
(
NULL
)
p
})
})
})
})
visualize_report
<-
function
()
{
visualize_report
<-
function
()
{
## resetting hidden elements to default values
vi
<-
viz_inputs
()
vi
<-
viz_inputs
()
if
(
input
$
viz_type
!=
"dist"
)
{
if
(
input
$
viz_type
!=
"dist"
)
{
vi
$
bins
<-
viz_args
$
bins
vi
$
bins
<-
viz_args
$
bins
...
@@ -531,6 +615,7 @@ visualize_report <- function() {
...
@@ -531,6 +615,7 @@ visualize_report <- function() {
if
(
!
input
$
viz_type
%in%
c
(
"bar"
,
"dist"
,
"density"
,
"surface"
))
{
if
(
!
input
$
viz_type
%in%
c
(
"bar"
,
"dist"
,
"density"
,
"surface"
))
{
vi
$
fill
<-
NULL
vi
$
fill
<-
NULL
}
}
if
(
!
input
$
viz_type
%in%
c
(
"bar"
,
"dist"
,
"box"
,
"density"
))
{
if
(
!
input
$
viz_type
%in%
c
(
"bar"
,
"dist"
,
"box"
,
"density"
))
{
vi
$
fillcol
<-
"blue"
vi
$
fillcol
<-
"blue"
}
}
...
@@ -540,13 +625,16 @@ visualize_report <- function() {
...
@@ -540,13 +625,16 @@ visualize_report <- function() {
if
(
!
input
$
viz_type
%in%
c
(
"box"
,
"scatter"
,
"line"
))
{
if
(
!
input
$
viz_type
%in%
c
(
"box"
,
"scatter"
,
"line"
))
{
vi
$
pointcol
<-
"black"
vi
$
pointcol
<-
"black"
}
}
if
(
!
input
$
viz_type
%in%
c
(
"bar"
,
"line"
,
"scatter"
))
{
if
(
!
input
$
viz_type
%in%
c
(
"bar"
,
"line"
,
"scatter"
))
{
vi
$
fun
<-
"mean"
vi
$
fun
<-
"mean"
}
}
if
(
safe_is_
empty
(
input
$
data_rows
))
{
if
(
is.
empty
(
input
$
data_rows
))
{
vi
$
rows
<-
NULL
vi
$
rows
<-
NULL
}
}
inp_main
<-
c
(
clean_args
(
vi
,
viz_args
),
custom
=
FALSE
)
inp_main
<-
c
(
clean_args
(
vi
,
viz_args
),
custom
=
FALSE
)
update_report
(
update_report
(
inp_main
=
inp_main
,
inp_main
=
inp_main
,
fun_name
=
"visualize"
,
fun_name
=
"visualize"
,
...
...
radiant.model/R/cox.R
View file @
f926635b
#' Cox Proportional Hazards Regression
(minimal)
#' Cox Proportional Hazards Regression
#'
#'
#' @export
#' @export
coxp
<-
function
(
dataset
,
coxp
<-
function
(
dataset
,
...
@@ -13,6 +13,11 @@ coxp <- function(dataset,
...
@@ -13,6 +13,11 @@ coxp <- function(dataset,
rows
=
NULL
,
rows
=
NULL
,
envir
=
parent.frame
())
{
envir
=
parent.frame
())
{
if
(
!
requireNamespace
(
"survival"
,
quietly
=
TRUE
))
stop
(
"survival package is required but not installed."
)
attachNamespace
(
"survival"
)
on.exit
(
detach
(
"package:survival"
),
add
=
TRUE
)
## ---- 公式入口 ----------------------------------------------------------
## ---- 公式入口 ----------------------------------------------------------
if
(
!
missing
(
form
))
{
if
(
!
missing
(
form
))
{
form
<-
as.formula
(
format
(
form
))
form
<-
as.formula
(
format
(
form
))
...
@@ -32,6 +37,26 @@ coxp <- function(dataset,
...
@@ -32,6 +37,26 @@ coxp <- function(dataset,
df_name
<-
if
(
is_string
(
dataset
))
dataset
else
deparse
(
substitute
(
dataset
))
df_name
<-
if
(
is_string
(
dataset
))
dataset
else
deparse
(
substitute
(
dataset
))
dataset
<-
get_data
(
dataset
,
vars
,
filt
=
data_filter
,
arr
=
arr
,
rows
=
rows
,
envir
=
envir
)
dataset
<-
get_data
(
dataset
,
vars
,
filt
=
data_filter
,
arr
=
arr
,
rows
=
rows
,
envir
=
envir
)
## 状态变量检查与转换
surv_status
<-
dataset
[[
status
]]
if
(
!
is.numeric
(
surv_status
))
{
## 允许 0/1、FALSE/TRUE、factor(未事件/事件) 等常见编码
if
(
is.factor
(
surv_status
)
||
is.character
(
surv_status
))
{
lv
<-
unique
(
surv_status
)
if
(
length
(
lv
)
!=
2
)
{
return
(
"Status variable must be binary (0/1 or two levels)."
%>%
add_class
(
"coxp"
))
}
## 统一成 0/1:按字母顺序或因子水平,第二个水平当作“事件=1”
dataset
[[
status
]]
<-
as.numeric
(
factor
(
surv_status
,
levels
=
lv
))
-
1L
}
else
{
return
(
"Status variable must be numeric 0/1 or binary factor."
%>%
add_class
(
"coxp"
))
}
}
else
{
if
(
!
all
(
unique
(
surv_status
)
%in%
c
(
0
,
1
)))
{
return
(
"Status variable must contain only 0 and 1."
%>%
add_class
(
"coxp"
))
}
}
## ---- 构造公式 ----------------------------------------------------------
## ---- 构造公式 ----------------------------------------------------------
if
(
missing
(
form
))
{
if
(
missing
(
form
))
{
rhs
<-
if
(
length
(
evar
)
==
0
)
"1"
else
paste
(
evar
,
collapse
=
" + "
)
rhs
<-
if
(
length
(
evar
)
==
0
)
"1"
else
paste
(
evar
,
collapse
=
" + "
)
...
@@ -46,35 +71,79 @@ coxp <- function(dataset,
...
@@ -46,35 +71,79 @@ coxp <- function(dataset,
model
<-
survival
::
coxph
(
form
,
data
=
dataset
)
model
<-
survival
::
coxph
(
form
,
data
=
dataset
)
}
}
## ---- 打包返回 ----------------------------------------------------------
## 失败模型保护
if
(
inherits
(
model
,
"try-error"
))
{
return
(
"Model estimation failed. Check data separation or collinearity."
%>%
add_class
(
"coxp"
))
}
## 基础摘要信息
coef_df
<-
broom
::
tidy
(
model
,
conf.int
=
TRUE
)
# 系数、HR、CI、p
n
<-
nrow
(
dataset
)
# 样本量
n_event
<-
sum
(
dataset
[[
status
]])
# 事件数
conc
<-
survival
::
survConcordance.fit
(
y
=
Surv
(
dataset
[[
time
]],
dataset
[[
status
]]),
x
=
predict
(
model
,
type
=
"lp"
))
$
concordance
cat
(
"coef:"
,
length
(
coef
(
model
)),
" n="
,
nrow
(
dataset
),
" events="
,
sum
(
dataset
[[
status
]]),
"\n"
)
## 打包返回
out
<-
as.list
(
environment
())
out
<-
as.list
(
environment
())
out
$
model
<-
model
out
$
model
<-
model
out
$
df_name
<-
df_name
out
$
df_name
<-
df_name
out
$
type
<-
"survival"
out
$
type
<-
"survival"
out
$
check
<-
check
out
$
check
<-
check
## 附加对象
out
$
coef_df
<-
coef_df
out
$
n
<-
n
out
$
n_event
<-
n_event
out
$
concordance
<-
conc
add_class
(
out
,
c
(
"coxp"
,
"model"
))
add_class
(
out
,
c
(
"coxp"
,
"model"
))
}
}
#' Summary 占位
#' @export
#' @export
summary.coxp
<-
function
(
object
,
...
)
{
summary.coxp
<-
function
(
object
,
...
)
{
if
(
is.character
(
object
))
return
(
object
)
if
(
is.character
(
object
))
return
(
object
)
# 检查模型对象有效性
if
(
!
inherits
(
object
$
model
,
"coxph"
))
{
cat
(
"** Invalid Cox model object. **\n"
)
return
(
invisible
(
object
))
}
# 输出基础信息
cat
(
"Cox Proportional Hazards\n"
)
cat
(
"Data:"
,
object
$
df_name
,
" N="
,
object
$
n
,
" Events="
,
object
$
n_event
,
"\n"
)
cat
(
"Concordance="
,
round
(
object
$
concordance
,
3
),
"\n\n"
)
# 输出模型summary
summary
(
object
$
model
)
summary
(
object
$
model
)
invisible
(
object
)
}
}
#' Predict 占位
#' @export
#' @export
predict.coxp
<-
function
(
object
,
pred_data
=
NULL
,
pred_cmd
=
""
,
predict.coxp
<-
function
(
object
,
pred_data
=
NULL
,
pred_cmd
=
""
,
dec
=
3
,
envir
=
parent.frame
(),
...
)
{
dec
=
3
,
envir
=
parent.frame
(),
...
)
{
if
(
is.character
(
object
))
return
(
object
)
if
(
is.character
(
object
))
return
(
object
)
## 如需生存预测,可返回 linear.predictors 或 survival 曲线
pfun
<-
function
(
m
,
newdata
)
predict
(
m
,
newdata
=
newdata
,
type
=
"lp"
)
## 构造预测数据框
predict_model
(
object
,
pfun
,
"coxp.predict"
,
if
(
is.null
(
pred_data
))
{
pred_data
,
pred_cmd
,
dec
=
dec
,
envir
=
envir
)
newdata
<-
envir
$
.model_frame
# 若无新数据,默认用训练集
}
else
{
newdata
<-
get_data
(
pred_data
,
envir
=
envir
)
}
if
(
!
is.empty
(
pred_cmd
))
{
newdata
<-
modify_data
(
newdata
,
pred_cmd
,
envir
=
envir
)
}
## 线性预测值 + HR
lp
<-
predict
(
object
$
model
,
newdata
=
newdata
,
type
=
"lp"
)
hr
<-
exp
(
lp
)
res
<-
data.frame
(
lp
=
round
(
lp
,
dec
),
hr
=
round
(
hr
,
dec
))
attr
(
res
,
"pred_type"
)
<-
"linear predictor & hazard ratio"
res
}
}
#' Print 预测占位
#' @export
#' @export
print.coxp.predict
<-
function
(
x
,
...
,
n
=
10
)
{
print.coxp.predict
<-
function
(
x
,
...
,
n
=
10
)
{
print_predict_model
(
x
,
...
,
n
=
n
,
header
=
"Cox Proportional Hazards"
)
cat
(
"Cox PH predictions (linear predictor & hazard ratio):\n"
)
print
(
head
(
x
,
n
))
invisible
(
x
)
}
}
\ No newline at end of file
radiant.model/inst/app/tools/analysis/cox_ui.R
View file @
f926635b
## ========== coxp_ui.R
去错版
==========
## ========== coxp_ui.R ==========
## 1. 常量 -----------------------------------------------------------------
## 1. 常量 -----------------------------------------------------------------
coxp_show_interactions
<-
setNames
(
c
(
""
,
2
,
3
),
coxp_show_interactions
<-
setNames
(
c
(
""
,
2
,
3
),
...
@@ -24,7 +24,6 @@ coxp_plots <- setNames(
...
@@ -24,7 +24,6 @@ coxp_plots <- setNames(
)
)
## 2. 参数收集 -------------------------------------------------------------
## 2. 参数收集 -------------------------------------------------------------
## 不再取 formals,全部用空列表占位
coxp_args
<-
list
()
coxp_args
<-
list
()
coxp_sum_args
<-
list
()
coxp_sum_args
<-
list
()
coxp_plot_args
<-
list
()
coxp_plot_args
<-
list
()
...
@@ -259,7 +258,7 @@ output$ui_coxp <- renderUI({
...
@@ -259,7 +258,7 @@ output$ui_coxp <- renderUI({
selectInput
(
"coxp_plots"
,
i
18
n
$
t
(
"Plots:"
),
choices
=
coxp_plots
,
selectInput
(
"coxp_plots"
,
i
18
n
$
t
(
"Plots:"
),
choices
=
coxp_plots
,
selected
=
state_single
(
"coxp_plots"
,
coxp_plots
)),
selected
=
state_single
(
"coxp_plots"
,
coxp_plots
)),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.coxp_plots == 'coef' |
input.coxp_plots == 'pdp' | input$
coxp_plots == 'pred_plot'"
,
condition
=
"input.coxp_plots == 'coef' |
| input.coxp_plots == 'pdp' || input.
coxp_plots == 'pred_plot'"
,
uiOutput
(
"ui_coxp_incl"
),
uiOutput
(
"ui_coxp_incl"
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.coxp_plots == 'coef'"
,
condition
=
"input.coxp_plots == 'coef'"
,
...
@@ -271,7 +270,7 @@ output$ui_coxp <- renderUI({
...
@@ -271,7 +270,7 @@ output$ui_coxp <- renderUI({
)
)
),
),
conditionalPanel
(
conditionalPanel
(
condition
=
"
input.coxp_plots %in% c('correlations','scatter','dashboard','resid_pred')
"
,
condition
=
"
['correlations', 'scatter', 'dashboard', 'resid_pred'].indexOf(input.coxp_plots) !== -1
"
,
uiOutput
(
"ui_coxp_nrobs"
),
uiOutput
(
"ui_coxp_nrobs"
),
conditionalPanel
(
conditionalPanel
(
condition
=
"input.coxp_plots != 'correlations'"
,
condition
=
"input.coxp_plots != 'correlations'"
,
...
@@ -281,9 +280,9 @@ output$ui_coxp <- renderUI({
...
@@ -281,9 +280,9 @@ output$ui_coxp <- renderUI({
)
)
),
),
conditionalPanel
(
conditionalPanel
(
condition
=
"(input.tabs_coxp == 'Summary' && input
$coxp_sum_check != undefined && input$
coxp_sum_check.indexOf('confint') >= 0) ||
condition
=
"(input.tabs_coxp == 'Summary' && input
.coxp_sum_check != undefined && input.
coxp_sum_check.indexOf('confint') >= 0) ||
(input.tabs_coxp == 'Predict' && input$
coxp_predict != 'none') ||
(input.tabs_coxp == 'Predict' && input.
coxp_predict != 'none') ||
(input.tabs_coxp == 'Plot' && input$
coxp_plots == 'coef')"
,
(input.tabs_coxp == 'Plot' && input.
coxp_plots == 'coef')"
,
sliderInput
(
"coxp_conf_lev"
,
i
18
n
$
t
(
"Confidence level:"
),
sliderInput
(
"coxp_conf_lev"
,
i
18
n
$
t
(
"Confidence level:"
),
min
=
0.80
,
max
=
0.99
,
value
=
state_init
(
"coxp_conf_lev"
,
.95
),
step
=
0.01
)
min
=
0.80
,
max
=
0.99
,
value
=
state_init
(
"coxp_conf_lev"
,
.95
),
step
=
0.01
)
),
),
...
@@ -372,33 +371,117 @@ output$coxp <- renderUI({
...
@@ -372,33 +371,117 @@ output$coxp <- renderUI({
})
})
## 10. 可用性检查 ----------------------------------------------------------
## 10. 可用性检查 ----------------------------------------------------------
coxp_available
<-
eventReactive
(
input
$
coxp_run
,
{
coxp_available
<-
reactive
({
if
(
not_available
(
input
$
coxp_time
))
{
if
(
!
input
$
dataset
%in%
names
(
r_data
))
{
i
18
n
$
t
(
"This analysis requires a time variable of type integer/numeric."
)
%>%
suggest_data
(
"lung"
)
return
(
i
18
n
$
t
(
"数据集不存在:请先加载有效数据集"
))
}
else
if
(
not_available
(
input
$
coxp_status
))
{
}
i
18
n
$
t
(
"Please select a status (event) variable."
)
%>%
suggest_data
(
"lung"
)
# 检查时间变量
}
else
if
(
not_available
(
input
$
coxp_evar
))
{
if
(
is.null
(
input
$
coxp_time
)
||
input
$
coxp_time
==
""
||
!
input
$
coxp_time
%in%
colnames
(
r_data
[[
input
$
dataset
]]))
{
i
18
n
$
t
(
"Please select one or more explanatory variables."
)
%>%
suggest_data
(
"lung"
)
return
(
i
18
n
$
t
(
"时间变量无效:请选择数据集中存在的数值型变量"
))
}
else
{
}
"available"
# 检查状态变量
if
(
is.null
(
input
$
coxp_status
)
||
input
$
coxp_status
==
""
||
!
input
$
coxp_status
%in%
colnames
(
r_data
[[
input
$
dataset
]]))
{
return
(
i
18
n
$
t
(
"状态变量无效:请选择数据集中存在的变量"
))
}
}
# 检查解释变量
if
(
is.null
(
input
$
coxp_evar
)
||
length
(
input
$
coxp_evar
)
==
0
||
length
(
setdiff
(
input
$
coxp_evar
,
colnames
(
r_data
[[
input
$
dataset
]])))
>
0
)
{
return
(
i
18
n
$
t
(
"解释变量无效:请选择至少一个数据集中存在的变量"
))
}
return
(
"available"
)
})
})
## 11. 模型估计 ------------------------------------------------------------
## 11. 模型估计
.coxp
<-
eventReactive
(
input
$
coxp_run
,
{
.coxp
<-
eventReactive
(
input
$
coxp_run
,
{
ci
<-
coxp_inputs
()
cat
(
"---->coxp reactive entered"
)
ci
$
envir
<-
r_data
# 严格校验变量
withProgress
(
message
=
i
18
n
$
t
(
"Estimating Cox model"
),
value
=
1
,
ds
<-
tryCatch
({
do.call
(
coxph
,
ci
))
get_data
(
input
$
dataset
,
vars
=
c
(),
envir
=
r_data
)
# 先获取完整数据集
},
error
=
function
(
e
)
return
(
paste
(
"数据集获取失败:"
,
e
$
message
)))
if
(
is.character
(
ds
))
return
(
ds
)
# 数据集不存在,返回错误
# 校验时间变量
if
(
!
input
$
coxp_time
%in%
colnames
(
ds
))
{
return
(
paste
(
"时间变量不存在:数据集中无「"
,
input
$
coxp_time
,
"」列"
,
sep
=
""
))
}
if
(
!
is.numeric
(
ds
[[
input
$
coxp_time
]]))
{
return
(
paste
(
"时间变量类型错误:「"
,
input
$
coxp_time
,
"」需为数值型(整数/小数)"
,
sep
=
""
))
}
# 校验状态变量
if
(
!
input
$
coxp_status
%in%
colnames
(
ds
))
{
return
(
paste
(
"状态变量不存在:数据集中无「"
,
input
$
coxp_status
,
"」列"
,
sep
=
""
))
}
sv
<-
ds
[[
input
$
coxp_status
]]
sv
<-
if
(
is.factor
(
sv
))
as.numeric
(
sv
)
-
1
else
sv
# 因子转0/1
sv
<-
ifelse
(
sv
%in%
c
(
0
,
1
),
sv
,
0
)
# 非0/1强制为0
n_event
<-
sum
(
sv
)
if
(
n_event
<
1
)
{
return
(
paste
(
"事件数不足:状态变量转换后仅"
,
n_event
,
"个事件(需至少1个),请检查状态变量编码"
))
}
ds
[[
input
$
coxp_status
]]
<-
sv
# 校验解释变量(存在且非空)
evar_missing
<-
setdiff
(
input
$
coxp_evar
,
colnames
(
ds
))
if
(
length
(
evar_missing
)
>
0
)
{
return
(
paste
(
"解释变量不存在:数据集中无「"
,
paste
(
evar_missing
,
collapse
=
"、"
),
"」列"
,
sep
=
""
))
}
# 构建模型并运行
form
<-
as.formula
(
paste0
(
"Surv("
,
input
$
coxp_time
,
", "
,
input
$
coxp_status
,
") ~ "
,
paste
(
input
$
coxp_evar
,
collapse
=
" + "
)))
model
<-
tryCatch
({
survival
::
coxph
(
form
,
data
=
ds
)
},
error
=
function
(
e
)
return
(
paste
(
"coxph模型失败:"
,
gsub
(
"\n"
,
" "
,
e
$
message
))))
return
(
model
)
})
})
## 12. summary / predict / plot --------------------------------------------
## 12. summary / predict / plot --------------------------------------------
.summary_coxp
<-
reactive
({
.summary_coxp
<-
reactive
({
if
(
not_pressed
(
input
$
coxp_run
))
return
(
i
18
n
$
t
(
"** Press the Estimate button to estimate the model **"
))
if
(
not_pressed
(
input
$
coxp_run
))
{
if
(
coxp_available
()
!=
"available"
)
return
(
coxp_available
())
return
(
i
18
n
$
t
(
"** 请点击「估计模型」按钮运行分析 **"
))
summary
(
.coxp
()
$
model
)
# 直接调 survival 的 summary
}
# 先检查可用性(提前拦截无效操作)
avail_msg
<-
coxp_available
()
if
(
avail_msg
!=
"available"
)
{
return
(
paste0
(
"** 前置检查失败:"
,
avail_msg
,
" **"
))
}
# 获取模型结果(可能是coxph对象或错误文本)
model_result
<-
.coxp
()
# 处理错误文本
if
(
is.character
(
model_result
))
{
return
(
paste0
(
"** 模型运行失败:"
,
model_result
,
" **"
))
}
# 处理有效模型
if
(
inherits
(
model_result
,
"coxph"
))
{
# 检查是否有系数(避免无系数的空模型)
if
(
length
(
coef
(
model_result
))
==
0
)
{
return
(
i
18
n
$
t
(
"** 未估计出系数:可能存在完全共线性、事件数不足或变量无效 **"
))
}
# 输出标准summary
return
(
summary
(
model_result
))
}
# 其他未知错误
return
(
i
18
n
$
t
(
"** 未知错误:请检查数据集和变量设置 **"
))
})
## 确保UI输出绑定正确
output
$
summary_coxp
<-
renderPrint
({
res
<-
.summary_coxp
()
if
(
is.character
(
res
))
{
cat
(
res
,
"\n"
)
}
else
{
print
(
res
)
}
})
})
.predict_coxp
<-
reactive
({
.predict_coxp
<-
reactive
({
if
(
not_pressed
(
input
$
coxp_run
))
return
(
i
18
n
$
t
(
"** Press the Estimate button to estimate the model **"
))
if
(
not_pressed
(
input
$
coxp_run
))
return
(
i
18
n
$
t
(
"** Press the Estimate button to estimate the model **"
))
if
(
coxp_available
()
!=
"available"
)
return
(
coxp_available
())
if
(
coxp_available
()
!=
"available"
)
return
(
coxp_available
())
...
...
radiant.quickgen/R/quickgen_ai.R
View file @
f926635b
# === 配置 ===
# === 配置 ===
MODELSCOPE_OPENAI_URL
<-
"https://api-inference.modelscope.cn/v1"
MODELSCOPE_OPENAI_URL
<-
"https://api-inference.modelscope.cn/v1"
MODELSCOPE_API_KEY
<-
Sys.getenv
(
"MODELSCOPE_API_KEY"
,
"ms-
b2746d72-f897-4faf-8089-89e5e511ed5a
"
)
MODELSCOPE_API_KEY
<-
Sys.getenv
(
"MODELSCOPE_API_KEY"
,
"ms-
6638b00e-57e4-4623-996d-214e375d220f
"
)
MODEL_ID
<-
"deepseek-ai/DeepSeek-V3.1"
MODEL_ID
<-
"deepseek-ai/DeepSeek-V3.1"
# === 低层封装:单次对话 ===
# === 低层封装:单次对话 ===
...
...
radiant.quickgen/inst/app/tools/analysis/quickgen_basic_ui.R
View file @
f926635b
safe_is_empty
<-
function
(
x
)
{
if
(
is.null
(
x
)
||
!
is.character
(
x
))
return
(
TRUE
)
is.empty
(
x
)
}
make_desc_text
<-
function
(
df
)
{
make_desc_text
<-
function
(
df
)
{
if
(
is.null
(
df
)
||
nrow
(
df
)
==
0
)
return
(
i
18
n
$
t
(
"No data available"
))
if
(
is.null
(
df
)
||
nrow
(
df
)
==
0
)
return
(
i
18
n
$
t
(
"No data available"
))
num_cols
<-
sapply
(
df
,
is.numeric
)
num_cols
<-
sapply
(
df
,
is.numeric
)
...
@@ -73,7 +68,7 @@ qib_add_labs <- function() {
...
@@ -73,7 +68,7 @@ qib_add_labs <- function() {
lab_list
<-
list
()
lab_list
<-
list
()
for
(
l
in
qib_labs
)
{
for
(
l
in
qib_labs
)
{
inp
<-
input
[[
paste0
(
"qib_labs_"
,
l
)]]
inp
<-
input
[[
paste0
(
"qib_labs_"
,
l
)]]
if
(
!
safe_is_
empty
(
inp
))
lab_list
[[
l
]]
<-
inp
if
(
!
is.
empty
(
inp
))
lab_list
[[
l
]]
<-
inp
}
}
lab_list
lab_list
}
}
...
@@ -407,7 +402,7 @@ output$ui_qib_axes <- renderUI({
...
@@ -407,7 +402,7 @@ output$ui_qib_axes <- renderUI({
}
else
if
(
input
$
qib_type
%in%
c
(
"bar"
,
"box"
))
{
}
else
if
(
input
$
qib_type
%in%
c
(
"bar"
,
"box"
))
{
ind
<-
c
(
1
,
3
)
ind
<-
c
(
1
,
3
)
}
}
if
(
!
safe_is_empty
(
input
$
qib_facet_row
,
"."
)
||
!
safe_is_
empty
(
input
$
qib_facet_col
,
"."
))
ind
<-
c
(
ind
,
4
)
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
)
if
(
input
$
qib_type
==
"bar"
)
ind
<-
c
(
ind
,
6
)
checkboxGroupInput
(
checkboxGroupInput
(
...
@@ -681,7 +676,7 @@ output$ui_quickgen_basic <- renderUI({
...
@@ -681,7 +676,7 @@ output$ui_quickgen_basic <- renderUI({
})
})
qib_plot_width
<-
reactive
({
qib_plot_width
<-
reactive
({
if
(
safe_is_
empty
(
input
$
qib_plot_width
))
r_info
[[
"plot_width"
]]
else
input
$
qib_plot_width
if
(
is.
empty
(
input
$
qib_plot_width
))
r_info
[[
"plot_width"
]]
else
input
$
qib_plot_width
})
})
qib_plot_height
<-
eventReactive
(
qib_plot_height
<-
eventReactive
(
...
@@ -691,7 +686,7 @@ qib_plot_height <- eventReactive(
...
@@ -691,7 +686,7 @@ qib_plot_height <- eventReactive(
input
$
qib_plot_width
input
$
qib_plot_width
},
},
{
{
if
(
safe_is_
empty
(
input
$
qib_plot_height
))
{
if
(
is.
empty
(
input
$
qib_plot_height
))
{
r_info
[[
"plot_height"
]]
r_info
[[
"plot_height"
]]
}
else
{
}
else
{
lx
<-
ifelse
(
not_available
(
input
$
qib_xvar
)
||
isTRUE
(
input
$
qib_combx
),
1
,
length
(
input
$
qib_xvar
))
lx
<-
ifelse
(
not_available
(
input
$
qib_xvar
)
||
isTRUE
(
input
$
qib_combx
),
1
,
length
(
input
$
qib_xvar
))
...
@@ -791,37 +786,67 @@ dl_qgb_tab <- function(path) {
...
@@ -791,37 +786,67 @@ dl_qgb_tab <- function(path) {
}
}
output
$
qib_chart
<-
renderPlot
({
output
$
qib_chart
<-
renderPlot
(
{
req
(
input
$
qib_type
)
req
(
input
$
qib_type
)
p
<-
.qib_chart
()
if
(
not_available
(
input
$
qib_xvar
))
{
if
(
is.null
(
p
))
return
(
NULL
)
if
(
!
input
$
qib_type
%in%
c
(
"box"
,
"line"
))
{
print
(
p
)
return
(
},
width
=
qib_plot_width
,
height
=
qib_plot_height
,
res
=
96
)
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
,
{
.qib_chart
<-
eventReactive
(
input
$
qib_run
,
{
req
(
input
$
qib_type
)
req
(
input
$
qib_type
)
if
(
input
$
qib_type
==
"scatter"
)
req
(
input
$
qib_nrobs
)
if
(
input
$
qib_type
==
"scatter"
)
req
(
input
$
qib_nrobs
)
## need dependency on ..
req
(
input
$
qib_plot_height
&&
input
$
qib_plot_width
)
req
(
input
$
qib_plot_height
&&
input
$
qib_plot_width
)
if
(
not_available
(
input
$
qib_xvar
)
&&
!
input
$
qib_type
%in%
c
(
"box"
,
"line"
))
{
if
(
not_available
(
input
$
qib_xvar
)
&&
!
input
$
qib_type
%in%
c
(
"box"
,
"line"
))
{
return
(
NULL
)
return
()
}
}
else
if
(
input
$
qib_type
%in%
c
(
"scatter"
,
"line"
,
"box"
,
"bar"
,
"surface"
)
&&
not_available
(
input
$
qib_yvar
))
{
if
(
input
$
qib_type
%in%
c
(
"scatter"
,
"line"
,
"box"
,
"bar"
,
"surface"
)
&&
not_available
(
input
$
qib_yvar
))
{
return
(
i
18
n
$
t
(
"No Y-variable provided for a plot that requires one"
))
return
(
NULL
)
}
else
if
(
input
$
qib_type
==
"box"
&&
!
all
(
input
$
qib_xvar
%in%
groupable_vars
()))
{
}
return
()
if
(
input
$
qib_type
==
"box"
&&
!
all
(
input
$
qib_xvar
%in%
groupable_vars
()))
{
return
(
NULL
)
}
}
##
等待 combx / comby 更新
##
waiting for comby and/or combx to be updated
if
(
input
$
qib_type
%in%
c
(
"dist"
,
"density"
))
{
if
(
input
$
qib_type
%in%
c
(
"dist"
,
"density"
))
{
if
(
isTRUE
(
input
$
qib_comby
))
return
(
NULL
)
if
(
isTRUE
(
input
$
qib_comby
))
{
if
(
length
(
input
$
qib_xvar
)
>
1
&&
is.null
(
input
$
qib_combx
))
return
(
NULL
)
return
()
}
if
(
length
(
input
$
qib_xvar
)
>
1
&&
is.null
(
input
$
qib_combx
))
{
return
()
}
}
else
{
}
else
{
if
(
isTRUE
(
input
$
qib_combx
))
return
(
NULL
)
if
(
isTRUE
(
input
$
qib_combx
))
{
if
(
length
(
input
$
qib_yvar
)
>
1
&&
is.null
(
input
$
qib_comby
))
return
(
NULL
)
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
<-
qib_inputs
()
qibi
$
dataset
<-
input
$
dataset
qibi
$
dataset
<-
input
$
dataset
qibi
$
shiny
<-
TRUE
qibi
$
shiny
<-
TRUE
...
@@ -830,10 +855,8 @@ output$qib_chart <- renderPlot({
...
@@ -830,10 +855,8 @@ output$qib_chart <- renderPlot({
qibi
$
fill
<-
"none"
qibi
$
fill
<-
"none"
qibi
$
facet_row
<-
"."
qibi
$
facet_row
<-
"."
qibi
$
facet_col
<-
"."
qibi
$
facet_col
<-
"."
withProgress
(
message
=
i
18
n
$
t
(
"Making plot"
),
value
=
1
,
{
withProgress
(
message
=
i
18
n
$
t
(
"Making plot"
),
value
=
1
,
{
p
<-
do.call
(
visualize
,
qibi
)
do.call
(
visualize
,
qibi
)
if
(
is.character
(
p
))
return
(
NULL
)
else
p
})
})
})
})
...
@@ -866,6 +889,108 @@ observeEvent(input$qgb_store, {
...
@@ -866,6 +889,108 @@ 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)
# }
# 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
(
download_handler
(
id
=
"dl_qgb_tab"
,
id
=
"dl_qgb_tab"
,
fun
=
dl_qgb_tab
,
fun
=
dl_qgb_tab
,
...
@@ -929,7 +1054,7 @@ quickgen_basic_report <- function() {
...
@@ -929,7 +1054,7 @@ quickgen_basic_report <- function() {
if
(
!
input
$
qib_type
%in%
c
(
"dist"
,
"density"
,
"box"
,
"scatter"
,
"line"
))
vi
$
linecol
<-
"black"
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
(
"box"
,
"scatter"
,
"line"
))
vi
$
pointcol
<-
"black"
if
(
!
input
$
qib_type
%in%
c
(
"bar"
,
"line"
,
"scatter"
))
vi
$
fun
<-
"mean"
if
(
!
input
$
qib_type
%in%
c
(
"bar"
,
"line"
,
"scatter"
))
vi
$
fun
<-
"mean"
if
(
safe_is_
empty
(
input
$
data_rows
))
vi
$
rows
<-
NULL
if
(
is.
empty
(
input
$
data_rows
))
vi
$
rows
<-
NULL
inp_main
<-
c
(
inp_main
,
clean_args
(
vi
,
qib_args
),
custom
=
FALSE
)
inp_main
<-
c
(
inp_main
,
clean_args
(
vi
,
qib_args
),
custom
=
FALSE
)
...
@@ -957,6 +1082,35 @@ observeEvent(input$modal_quickgen_basic_screenshot, {
...
@@ -957,6 +1082,35 @@ observeEvent(input$modal_quickgen_basic_screenshot, {
quickgen_basic_report
()
quickgen_basic_report
()
removeModal
()
removeModal
()
})
})
# 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
,
{
observeEvent
(
input
$
qgb_select_all
,
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment