library(shiny) library(ggplot2) library(dplyr) library(tidyr) ui <- fluidPage( titlePanel("クライアント型電子計算機の分析可視化(連動型)"), sidebarLayout( sidebarPanel( # 残存関数パラメータ sliderInput("alpha", "残存関数のパラメータ alpha:", min = 1, max = 4, value = 2.58, step = 0.01), sliderInput("lambda", "残存関数のパラメータ lambda:", min = 5, max = 15, value = 8.0, step = 0.1), # ストック推計関連パラメータ sliderInput("base_shipment", "基準年出荷台数(万台):", min = 800, max = 1200, value = 1000, step = 10), sliderInput("decline_rate", "出荷台数減少率(%/年):", min = 0, max = 5, value = 2, step = 0.1), # TEC関連パラメータ sliderInput("base_tec", "基準TEC値(kWh):", min = 15, max = 35, value = 25, step = 0.5), sliderInput("tec_improvement", "TEC改善率(%/年):", min = 0, max = 10, value = 3, step = 0.1), # TEC分布共通インタラクティブ項目 sliderInput("screen_min", "画面サイズ(最小)", min = 8, max = 14.9, value = 8, step = 0.1), sliderInput("screen_max", "画面サイズ(最大)", min = 15.1, max = 18, value = 18, step = 0.1), numericInput("mean_tec", "TEC平均値", value = 20, min = 0), numericInput("sd_tec", "TEC標準偏差", value = 5, min = 0.1), checkboxInput("show_medians", "中央値ラベルを表示", value = TRUE), checkboxInput("show_vline", "15インチ区切り線を表示", value = TRUE) ), mainPanel( tabsetPanel( tabPanel("残存関数", plotOutput("residualPlot")), tabPanel("ストック推計", plotOutput("stockPlot")), tabPanel("エネルギー消費量", plotOutput("energyPlot")), tabPanel("TEC分布(ノートPC)", plotOutput("tecNotePlot")), tabPanel("TEC分布(Pスコア)", plotOutput("tecPscorePlot")), tabPanel("TEC分布(デスクトップ)", plotOutput("tecDesktopPlot")), tabPanel("TEC分布(分離型PC)", plotOutput("tecSplitPlot")), tabPanel("パラメータ感度分析", plotOutput("sensitivityPlot")) ) ) ) ) server <- function(input, output) { # Survival function calculation residual_function <- reactive({ n <- 0:30 residual_rate <- exp(- (n / input$lambda)^input$alpha) data.frame(Year = n, ResidualRate = residual_rate) }) # Stock estimation calculation (linked with survival function) stock_estimation <- reactive({ years <- 2000:2030 n_years <- length(years) # Actual data (2000-2022) actual_stock <- c(55000000, 61000000, 67000000, 73000000, 80000000, 86000000, 91000000, 96000000, 101000000, 106000000, 111000000, 115000000, 118000000, 120000000, 121000000, 120000000, 116000000, 113000000, 112000000, 111000000, 108000000, 107000000, 106000000) # Estimated data (2023-2030) - Based on survival function parameters estimated_stock <- numeric(8) base_year_stock <- 106000000 # Based on 2022 value for (i in 1:8) { # Stock estimation using survival function age_distribution <- residual_function() survival_rate <- mean(age_distribution$ResidualRate[1:min(i+5, nrow(age_distribution))]) # Consider shipment decline shipment_factor <- (1 - input$decline_rate/100)^i estimated_stock[i] <- base_year_stock * survival_rate * shipment_factor } # Create data frame data.frame( Year = years, Actual = c(actual_stock, rep(NA, 8)), Estimated = c(rep(NA, 23), estimated_stock) ) }) # Energy consumption calculation (linked with stock estimation and TEC values) energy_consumption <- reactive({ stock_data <- stock_estimation() years <- 2006:2030 # Actual data (2006-2022) actual_consumption <- c(10000, 10300, 10400, 10200, 10100, 10000, 9800, 9400, 9200, 8900, 8500, 8100, 7700, 7200, 6800, 6300, 6000) # Estimated data (2023-2030) - Based on stock and TEC improvement estimated_consumption <- numeric(8) for (i in 1:8) { year_idx <- 23 + i # Index for 2023 onwards in stock_data stock_value <- stock_data$Estimated[year_idx] if (!is.na(stock_value)) { # Consider TEC improvement tec_factor <- input$base_tec * (1 - input$tec_improvement/100)^i # Energy consumption = Stock × TEC × Operating hours factor # Unit conversion: units × kWh → GWh operating_hours_factor <- 2000 # Annual operating hours estimated_consumption[i] <- (stock_value * tec_factor * operating_hours_factor) / 1e9 } else { estimated_consumption[i] <- NA } } data.frame( Year = years, Actual = c(actual_consumption, rep(NA, 8)), Estimated = c(rep(NA, 17), estimated_consumption) ) }) # Plot outputs output$residualPlot <- renderPlot({ df <- residual_function() ggplot(df, aes(x = Year, y = ResidualRate)) + geom_line(color = "darkorange", size = 1.2) + geom_point(color = "darkorange", size = 2) + labs(title = "Survival Function", subtitle = paste("alpha =", input$alpha, ", lambda =", input$lambda), x = "Years (n)", y = "Survival Rate") + theme_minimal() + ylim(0, 1.2) + theme(text = element_text(family = "sans")) }) output$stockPlot <- renderPlot({ df <- stock_estimation() df_long <- df %>% mutate(Year = as.character(Year)) %>% pivot_longer(cols = c(Actual, Estimated), names_to = "Category", values_to = "Stock") %>% filter(!is.na(Stock)) ggplot(df_long, aes(x = Year, y = Stock, fill = Category)) + geom_col(position = "dodge") + scale_fill_manual(values = c("Actual" = "steelblue", "Estimated" = "darkorange")) + scale_y_continuous(labels = scales::comma_format()) + theme_minimal() + theme(axis.text.x = element_text(angle = 90, hjust = 1), text = element_text(family = "sans")) + labs(title = "Stock Estimation (Linked with Survival Function)", subtitle = paste("Decline Rate:", input$decline_rate, "%/year"), x = "Year", y = "Stock (units)") }) output$energyPlot <- renderPlot({ data <- energy_consumption() data_long <- data %>% pivot_longer(cols = c("Actual", "Estimated"), names_to = "Category", values_to = "Consumption") %>% filter(!is.na(Consumption)) ggplot(data_long, aes(x = Year, y = Consumption, fill = Category)) + geom_col(position = "dodge") + scale_fill_manual(values = c("Actual" = "steelblue", "Estimated" = "darkorange")) + scale_y_continuous(labels = scales::comma_format()) + labs(title = "Energy Consumption Trends (Linked with Stock & TEC)", subtitle = paste("TEC Improvement Rate:", input$tec_improvement, "%/year, Base TEC:", input$base_tec, "kWh"), x = "Year", y = "GWh/year") + theme_minimal() + theme(axis.text.x = element_text(angle = 45, hjust = 1), text = element_text(family = "sans")) }) # Sensitivity analysis plot output$sensitivityPlot <- renderPlot({ # Current parameters for 2030 estimation current_stock <- tail(stock_estimation()$Estimated[!is.na(stock_estimation()$Estimated)], 1) current_energy <- tail(energy_consumption()$Estimated[!is.na(energy_consumption()$Estimated)], 1) # Parameter ranges for sensitivity analysis alpha_range <- seq(1.5, 3.5, 0.1) lambda_range <- seq(6, 12, 0.5) sensitivity_data <- expand.grid(alpha = alpha_range, lambda = lambda_range) sensitivity_data$stock_2030 <- NA sensitivity_data$energy_2030 <- NA for (i in 1:nrow(sensitivity_data)) { # Simplified calculation (streamlined calculation logic) alpha_temp <- sensitivity_data$alpha[i] lambda_temp <- sensitivity_data$lambda[i] survival_rate <- exp(-(8/lambda_temp)^alpha_temp) # 8-year survival rate stock_factor <- (1 - input$decline_rate/100)^8 sensitivity_data$stock_2030[i] <- 106000000 * survival_rate * stock_factor sensitivity_data$energy_2030[i] <- (sensitivity_data$stock_2030[i] * input$base_tec * (1 - input$tec_improvement/100)^8 * 2000) / 1e9 } ggplot(sensitivity_data, aes(x = alpha, y = lambda, fill = energy_2030)) + geom_tile() + scale_fill_gradient2(low = "blue", mid = "white", high = "red", midpoint = median(sensitivity_data$energy_2030, na.rm = TRUE)) + geom_point(aes(x = input$alpha, y = input$lambda), color = "black", size = 4, shape = 21, fill = "yellow") + labs(title = "Parameter Sensitivity Analysis (2030 Energy Consumption)", subtitle = "Yellow dot: Current setting", x = "Alpha", y = "Lambda", fill = "GWh/year") + theme_minimal() }) # Existing TEC plots output$tecNotePlot <- renderPlot({ set.seed(123) screen_size <- c(runif(25, input$screen_min, min(14.9, input$screen_max)), runif(15, max(15.1, input$screen_min), input$screen_max)) tec_value <- c(rnorm(25, input$mean_tec - 5, input$sd_tec), rnorm(15, input$mean_tec + 5, input$sd_tec)) df1 <- data.frame(ScreenSize = screen_size, TEC = tec_value) medians1 <- data.frame( ScreenSize = c(mean(c(input$screen_min, 14.9)), mean(c(15.1, input$screen_max))), TEC = c(input$mean_tec - 5, input$mean_tec + 5), Label = sprintf("%.2f", c(input$mean_tec - 5, input$mean_tec + 5)) ) p <- ggplot(df1, aes(x = ScreenSize, y = TEC)) + geom_point(color = "blue") + labs(title = "TEC Distribution: Notebook PC (Category J・K)", x = "Screen Size", y = "TEC[kWh]") + theme_minimal() if (input$show_vline) { p <- p + geom_vline(xintercept = 15, linetype = "dashed") } if (input$show_medians) { p <- p + geom_text(data = medians1, aes(label = Label), vjust = -1, color = "red", size = 4) } p }) output$tecPscorePlot <- renderPlot({ set.seed(124) df2 <- data.frame(P_score = runif(30, 8, 13), TEC = rnorm(30, 20, 5)) ggplot(df2, aes(x = P_score, y = TEC)) + geom_point(color = "darkgreen") + geom_segment(aes(x = 10.5, xend = 12.5, y = 11.34, yend = 11.34), color = "red") + annotate("text", x = 12.7, y = 11.34, label = "11.34") + labs(title = "TEC Distribution: P-score 8 or Higher (Category L)", x = "P-score", y = "TEC[kWh]") + theme_minimal() }) output$tecDesktopPlot <- renderPlot({ set.seed(125) df3 <- data.frame(P_score = runif(40, 2, 15), TEC = runif(40, 30, 180)) ggplot(df3, aes(x = P_score, y = TEC)) + geom_point() + geom_vline(xintercept = 8, linetype = "dashed") + annotate("text", x = 5, y = 180, label = "Category M") + annotate("text", x = 12, y = 180, label = "Category N") + geom_segment(aes(x = 3, xend = 7, y = 39.87, yend = 39.87), color = "red") + geom_segment(aes(x = 10, xend = 14, y = 53.32, yend = 53.32), color = "red") + annotate("text", x = 7.1, y = 39.87, label = "39.87") + annotate("text", x = 14.1, y = 53.32, label = "53.32") + labs(title = "TEC Distribution: Integrated Desktop (M/N)", x = "P-score", y = "TEC[kWh]") + theme_minimal() }) output$tecSplitPlot <- renderPlot({ set.seed(126) df4 <- data.frame(Volume = runif(40, 0, 20), TEC = runif(40, 20, 140)) ggplot(df4, aes(x = Volume, y = TEC)) + geom_point() + geom_vline(xintercept = 10, linetype = "dashed") + annotate("text", x = 4, y = 140, label = "Category O") + annotate("text", x = 14, y = 140, label = "Category P") + geom_segment(aes(x = 3, xend = 8, y = 29.55, yend = 29.55), color = "red") + geom_segment(aes(x = 11, xend = 15, y = 31.33, yend = 31.33), color = "red") + annotate("text", x = 8.1, y = 29.55, label = "29.55") + annotate("text", x = 15.1, y = 31.33, label = "31.33") + labs(title = "TEC Distribution: Separate PC (O/P)", x = "Volume[L]", y = "TEC[kWh]") + theme_minimal() }) } shinyApp(ui = ui, server = server)