@@ -169,7 +169,7 @@ ED.plus <- function(object, respLev, maxEff = TRUE, trend = "Increase", range =
169
169
}
170
170
}
171
171
} else {
172
- require( bmd )
172
+ requireNamespace( " bmd" , quietly = TRUE )
173
173
# tmp <- lapply(cross2(respLev,modList),function(l){
174
174
# x <- l[[1]]
175
175
# y <- l[[2]]
@@ -456,7 +456,7 @@ plot.modList <- function(modList, respLev = NULL, data = NULL,
456
456
return (newdata )
457
457
})
458
458
predData $ Model <- factor (predData $ Model , levels = unique(predData $ Model ))
459
- require( ggplot2 )
459
+ requireNamespace( " ggplot2" , quietly = TRUE )
460
460
p <- ggplot(ex1 , aes_(x = ~ conc0 , y = as.name(responseName ))) +
461
461
geom_ribbon(data = predData , aes_(x = as.name(doseName ),
462
462
y = ~ p , ymin = ~ pmin ,
@@ -886,3 +886,119 @@ simDRdata <- function(nosim, fct, mpar, xerror, xpar = 1, yerror = "rnorm",
886
886
}
887
887
return (dat )
888
888
}
889
+
890
+
891
+
892
+ # ' Simulate Hierarchical Dose-Response Data
893
+ # '
894
+ # ' This function simulates dose-response data with a hierarchical structure:
895
+ # ' n doses, m tanks per dose, and optionally k individuals per tank, with variance components
896
+ # ' at both the tank and individual levels.
897
+ # '
898
+ # ' @param n_doses Number of dose levels
899
+ # ' @param dose_range Vector of length 2 specifying the min and max dose values
900
+ # ' @param m_tanks Number of tanks per dose
901
+ # ' @param k_individuals Number of individuals per tank (only used if include_individuals = TRUE)
902
+ # ' @param var_tank Variance at the tank level
903
+ # ' @param var_individual Variance at the individual level (only used if include_individuals = TRUE)
904
+ # ' @param include_individuals Logical, whether to simulate individual-level data (TRUE) or only tank-level data (FALSE)
905
+ # ' @param response_function Function that calculates the response given a dose
906
+ # ' @param ... Additional parameters to pass to the response_function
907
+ # '
908
+ # ' @return A data frame containing the simulated dose-response data
909
+ # ' @export
910
+ # '
911
+ # ' @examples
912
+ # ' # Simulate data with individuals
913
+ # ' sim_data_with_individuals <- simulate_dose_response(
914
+ # ' n_doses = 5,
915
+ # ' dose_range = c(0, 20),
916
+ # ' m_tanks = 3,
917
+ # ' include_individuals = TRUE
918
+ # ' )
919
+ # '
920
+ # ' # Simulate data without individuals (tank-level only)
921
+ # ' sim_data_tanks_only <- simulate_dose_response(
922
+ # ' n_doses = 5,
923
+ # ' dose_range = c(0, 20),
924
+ # ' m_tanks = 3,
925
+ # ' include_individuals = FALSE
926
+ # ' )
927
+ simulate_dose_response <- function (n_doses ,
928
+ dose_range = c(0 , 20 ),
929
+ m_tanks = 3 ,
930
+ k_individuals = 10 ,
931
+ var_tank = 4 ,
932
+ var_individual = 2 ,
933
+ include_individuals = TRUE ,
934
+ response_function = NULL ,
935
+ ... ) {
936
+
937
+ # Set default response function if not provided
938
+ if (is.null(response_function )) {
939
+ response_function <- function (dose , lower = 0 , upper = 100 , ED50 = 10 , slope = 1 ) {
940
+ lower + (upper - lower ) / (1 + exp(- slope * (dose - ED50 )))
941
+ }
942
+ }
943
+
944
+ # Define doses
945
+ doses <- seq(dose_range [1 ], dose_range [2 ], length.out = n_doses )
946
+
947
+ if (include_individuals ) {
948
+ # Simulate data with individuals
949
+
950
+ # Create a data frame with all combinations of dose, tank, and individual
951
+ simulated_data <- expand.grid(
952
+ Dose = doses ,
953
+ Tank = 1 : m_tanks ,
954
+ Individual = 1 : k_individuals
955
+ )
956
+
957
+ # Calculate the base response for each dose (vectorized)
958
+ simulated_data $ BaseResponse <- response_function(simulated_data $ Dose , ... )
959
+
960
+ # Generate tank-level random effects (vectorized)
961
+ # First, create a unique identifier for each dose-tank combination
962
+ simulated_data $ DoseTank <- paste(simulated_data $ Dose , simulated_data $ Tank , sep = " _" )
963
+ unique_dose_tanks <- unique(simulated_data $ DoseTank )
964
+
965
+ # Generate tank effects for each unique dose-tank combination
966
+ tank_effects <- stats :: rnorm(length(unique_dose_tanks ), mean = 0 , sd = sqrt(var_tank ))
967
+ names(tank_effects ) <- unique_dose_tanks
968
+
969
+ # Add tank effects to the data frame
970
+ simulated_data $ TankEffect <- tank_effects [simulated_data $ DoseTank ]
971
+
972
+ # Generate individual-level random effects (vectorized)
973
+ simulated_data $ IndividualEffect <- stats :: rnorm(nrow(simulated_data ), mean = 0 , sd = sqrt(var_individual ))
974
+
975
+ # Calculate the final response
976
+ simulated_data $ Response <- simulated_data $ BaseResponse + simulated_data $ TankEffect + simulated_data $ IndividualEffect
977
+
978
+ # Clean up the data frame by removing intermediate columns
979
+ simulated_data <- simulated_data [, c(" Dose" , " Tank" , " Individual" , " Response" )]
980
+
981
+ } else {
982
+ # Simulate data at tank level only
983
+
984
+ # Create a data frame with all combinations of dose and tank
985
+ simulated_data <- expand.grid(
986
+ Dose = doses ,
987
+ Tank = 1 : m_tanks
988
+ )
989
+
990
+ # Calculate the base response for each dose (vectorized)
991
+ simulated_data $ BaseResponse <- response_function(simulated_data $ Dose , ... )
992
+
993
+ # Generate tank-level random effects (vectorized)
994
+ simulated_data $ TankEffect <- stats :: rnorm(nrow(simulated_data ), mean = 0 , sd = sqrt(var_tank ))
995
+
996
+ # Calculate the final response (no individual effects)
997
+ simulated_data $ Response <- simulated_data $ BaseResponse + simulated_data $ TankEffect
998
+
999
+ # Clean up the data frame by removing intermediate columns
1000
+ simulated_data <- simulated_data [, c(" Dose" , " Tank" , " Response" )]
1001
+ }
1002
+
1003
+ return (simulated_data )
1004
+ }
0 commit comments