# .Rprofileif(interactive()){# Load required packageslibrary(here)library(renv)library(targets)# Set working directorysetwd(here::here())# Initialize renv if not already doneif(!file.exists("renv.lock")){renv::init()}# Restore package versionsrenv::restore()}# Set global optionsoptions(scipen=999,digits=4,stringsAsFactors=FALSE,warn=1)
# R/01-data-import.R#' Import raw data from various sources#'#' @param data_source Character string indicating data source#' @param file_path Path to data file#' @return Data frame with imported dataimport_data<-function(data_source,file_path){switch(data_source,"csv"=import_csv(file_path),"excel"=import_excel(file_path),"json"=import_json(file_path),"database"=import_database(file_path),stop("Unsupported data source: ",data_source))}#' Import CSV data#'#' @param file_path Path to CSV file#' @return Data frameimport_csv<-function(file_path){readr::read_csv(file_path,col_types=cols(),locale=locale(encoding="UTF-8"))}#' Import Excel data#'#' @param file_path Path to Excel file#' @param sheet_name Name of sheet to import#' @return Data frameimport_excel<-function(file_path,sheet_name=NULL){if(is.null(sheet_name)){readxl::read_excel(file_path)}else{readxl::read_excel(file_path,sheet=sheet_name)}}#' Import JSON data#'#' @param file_path Path to JSON file#' @return Data frameimport_json<-function(file_path){jsonlite::fromJSON(file_path,simplifyDataFrame=TRUE)}#' Import data from database#'#' @param connection_string Database connection string#' @param query SQL query#' @return Data frameimport_database<-function(connection_string,query){con<-DBI::dbConnect(odbc::odbc(),.connection_string=connection_string)on.exit(DBI::dbDisconnect(con))DBI::dbGetQuery(con,query)}
# R/02-data-cleaning.R#' Clean and preprocess data#'#' @param data Raw data frame#' @param cleaning_config Cleaning configuration#' @return Cleaned data frameclean_data<-function(data,cleaning_config){cleaned_data<-data# Remove duplicatesif(cleaning_config$remove_duplicates){cleaned_data<-remove_duplicates(cleaned_data)}# Handle missing valuesif(cleaning_config$handle_missing){cleaned_data<-handle_missing_values(cleaned_data,cleaning_config$missing_strategy)}# Standardize text columnsif(cleaning_config$standardize_text){cleaned_data<-standardize_text(cleaned_data,cleaning_config$text_columns)}# Convert data typesif(cleaning_config$convert_types){cleaned_data<-convert_data_types(cleaned_data,cleaning_config$type_conversions)}# Remove outliersif(cleaning_config$remove_outliers){cleaned_data<-remove_outliers(cleaned_data,cleaning_config$outlier_method)}return(cleaned_data)}#' Remove duplicate rows#'#' @param data Data frame#' @return Data frame without duplicatesremove_duplicates<-function(data){dplyr::distinct(data)}#' Handle missing values#'#' @param data Data frame#' @param strategy Missing value handling strategy#' @return Data frame with handled missing valueshandle_missing_values<-function(data,strategy){switch(strategy,"remove"=remove_missing_rows(data),"impute_mean"=impute_missing_values(data,"mean"),"impute_median"=impute_missing_values(data,"median"),"impute_mode"=impute_missing_values(data,"mode"),data)}#' Remove rows with missing values#'#' @param data Data frame#' @return Data frame without missing valuesremove_missing_rows<-function(data){tidyr::drop_na(data)}#' Impute missing values#'#' @param data Data frame#' @param method Imputation method#' @return Data frame with imputed valuesimpute_missing_values<-function(data,method){numeric_cols<-sapply(data,is.numeric)for(colinnames(data)[numeric_cols]){if(method=="mean"){data[[col]][is.na(data[[col]])]<-mean(data[[col]],na.rm=TRUE)}elseif(method=="median"){data[[col]][is.na(data[[col]])]<-median(data[[col]],na.rm=TRUE)}}return(data)}#' Standardize text columns#'#' @param data Data frame#' @param text_columns Columns to standardize#' @return Data frame with standardized textstandardize_text<-function(data,text_columns){for(colintext_columns){if(col%in%names(data)){data[[col]]<-stringr::str_trim(stringr::str_to_lower(data[[col]]))}}return(data)}#' Convert data types#'#' @param data Data frame#' @param type_conversions Type conversion specifications#' @return Data frame with converted typesconvert_data_types<-function(data,type_conversions){for(colinnames(type_conversions)){if(col%in%names(data)){target_type<-type_conversions[[col]]switch(target_type,"character"=data[[col]]<-as.character(data[[col]]),"numeric"=data[[col]]<-as.numeric(data[[col]]),"integer"=data[[col]]<-as.integer(data[[col]]),"logical"=data[[col]]<-as.logical(data[[col]]),"Date"=data[[col]]<-as.Date(data[[col]]),"POSIXct"=data[[col]]<-as.POSIXct(data[[col]]))}}return(data)}#' Remove outliers#'#' @param data Data frame#' @param method Outlier detection method#' @return Data frame without outliersremove_outliers<-function(data,method){numeric_cols<-sapply(data,is.numeric)for(colinnames(data)[numeric_cols]){if(method=="iqr"){Q1<-quantile(data[[col]],0.25,na.rm=TRUE)Q3<-quantile(data[[col]],0.75,na.rm=TRUE)IQR<-Q3-Q1lower_bound<-Q1-1.5*IQRupper_bound<-Q3+1.5*IQRdata<-data[data[[col]]>=lower_bound&data[[col]]<=upper_bound,]}elseif(method=="zscore"){z_scores<-abs(scale(data[[col]]))data<-data[z_scores<3,]}}return(data)}
# R/03-analysis.R#' Run complete analysis pipeline#'#' @param data_path Path to data file#' @param config Analysis configuration#' @return Analysis resultsrun_analysis<-function(data_path,config){# Import dataraw_data<-import_data(config$data_source,data_path)# Validate dataschema<-define_schema()validation<-validate_data(raw_data,schema)if(!validation$valid){stop("Data validation failed: ",paste(validation$errors,collapse="; "))}# Clean datacleaned_data<-clean_data(raw_data,config$cleaning_config)# Run analysisresults<-perform_analysis(cleaned_data,config$analysis_config)# Generate reportgenerate_report(results,config$report_config)return(results)}#' Perform statistical analysis#'#' @param data Cleaned data frame#' @param analysis_config Analysis configuration#' @return Analysis resultsperform_analysis<-function(data,analysis_config){results<-list()# Descriptive statisticsif(analysis_config$descriptive_stats){results$descriptive<-calculate_descriptive_stats(data)}# Correlation analysisif(analysis_config$correlation_analysis){results$correlation<-calculate_correlations(data)}# Regression analysisif(analysis_config$regression_analysis){results$regression<-perform_regression(data,analysis_config$regression_config)}# Time series analysisif(analysis_config$time_series_analysis){results$time_series<-perform_time_series_analysis(data,analysis_config$time_series_config)}return(results)}#' Calculate descriptive statistics#'#' @param data Data frame#' @return Descriptive statisticscalculate_descriptive_stats<-function(data){numeric_cols<-sapply(data,is.numeric)if(sum(numeric_cols)==0){return(NULL)}numeric_data<-data[,numeric_cols,drop=FALSE]stats<-data.frame(variable=names(numeric_data),mean=sapply(numeric_data,mean,na.rm=TRUE),median=sapply(numeric_data,median,na.rm=TRUE),sd=sapply(numeric_data,sd,na.rm=TRUE),min=sapply(numeric_data,min,na.rm=TRUE),max=sapply(numeric_data,max,na.rm=TRUE),q25=sapply(numeric_data,quantile,0.25,na.rm=TRUE),q75=sapply(numeric_data,quantile,0.75,na.rm=TRUE),stringsAsFactors=FALSE)return(stats)}#' Calculate correlations#'#' @param data Data frame#' @return Correlation matrixcalculate_correlations<-function(data){numeric_cols<-sapply(data,is.numeric)if(sum(numeric_cols)<2){return(NULL)}numeric_data<-data[,numeric_cols,drop=FALSE]cor_matrix<-cor(numeric_data,use="complete.obs")return(cor_matrix)}#' Perform regression analysis#'#' @param data Data frame#' @param regression_config Regression configuration#' @return Regression resultsperform_regression<-function(data,regression_config){formula<-as.formula(regression_config$formula)if(regression_config$method=="linear"){model<-lm(formula,data=data)}elseif(regression_config$method=="logistic"){model<-glm(formula,data=data,family=binomial())}results<-list(model=model,summary=summary(model),coefficients=coef(model),r_squared=if(regression_config$method=="linear")summary(model)$r.squaredelseNULL,aic=AIC(model),bic=BIC(model))return(results)}#' Perform time series analysis#'#' @param data Data frame#' @param time_series_config Time series configuration#' @return Time series resultsperform_time_series_analysis<-function(data,time_series_config){# Convert to time series objectts_data<-ts(data[[time_series_config$value_column]],start=time_series_config$start_date,frequency=time_series_config$frequency)# Decompose time seriesdecomposition<-decompose(ts_data)# Calculate trendtrend<-trend_analysis(ts_data)# Calculate seasonalityseasonality<-seasonality_analysis(ts_data)results<-list(time_series=ts_data,decomposition=decomposition,trend=trend,seasonality=seasonality)return(results)}
# R/04-visualization.R#' Create comprehensive visualizations#'#' @param data Data frame#' @param results Analysis results#' @param viz_config Visualization configuration#' @return List of ggplot objectscreate_visualizations<-function(data,results,viz_config){plots<-list()# Distribution plotsif(viz_config$distribution_plots){plots$distributions<-create_distribution_plots(data)}# Correlation heatmapif(viz_config$correlation_heatmap&&!is.null(results$correlation)){plots$correlation<-create_correlation_heatmap(results$correlation)}# Time series plotsif(viz_config$time_series_plots&&!is.null(results$time_series)){plots$time_series<-create_time_series_plots(results$time_series)}# Regression plotsif(viz_config$regression_plots&&!is.null(results$regression)){plots$regression<-create_regression_plots(results$regression)}return(plots)}#' Create distribution plots#'#' @param data Data frame#' @return List of distribution plotscreate_distribution_plots<-function(data){plots<-list()numeric_cols<-sapply(data,is.numeric)for(colinnames(data)[numeric_cols]){p<-ggplot2::ggplot(data,aes_string(x=col))+ggplot2::geom_histogram(bins=30,alpha=0.7,fill="steelblue")+ggplot2::geom_density(alpha=0.5,color="red")+ggplot2::theme_minimal()+ggplot2::labs(title=paste("Distribution of",col),x=col,y="Frequency")plots[[col]]<-p}return(plots)}#' Create correlation heatmap#'#' @param cor_matrix Correlation matrix#' @return Correlation heatmapcreate_correlation_heatmap<-function(cor_matrix){# Convert to long formatcor_data<-reshape2::melt(cor_matrix)ggplot2::ggplot(cor_data,aes_string(x="Var1",y="Var2",fill="value"))+ggplot2::geom_tile()+ggplot2::scale_fill_gradient2(low="blue",high="red",mid="white",midpoint=0,limit=c(-1,1))+ggplot2::theme_minimal()+ggplot2::labs(title="Correlation Heatmap",x="",y="",fill="Correlation")+ggplot2::theme(axis.text.x=element_text(angle=45,hjust=1))}#' Create time series plots#'#' @param time_series_results Time series results#' @return List of time series plotscreate_time_series_plots<-function(time_series_results){plots<-list()# Original time seriests_data<-time_series_results$time_seriests_df<-data.frame(time=time(ts_data),value=as.numeric(ts_data))plots$original<-ggplot2::ggplot(ts_df,aes(x=time,y=value))+ggplot2::geom_line()+ggplot2::theme_minimal()+ggplot2::labs(title="Original Time Series",x="Time",y="Value")# Decompositionif(!is.null(time_series_results$decomposition)){decomp<-time_series_results$decompositiondecomp_df<-data.frame(time=time(decomp$x),original=as.numeric(decomp$x),trend=as.numeric(decomp$trend),seasonal=as.numeric(decomp$seasonal),random=as.numeric(decomp$random))plots$decomposition<-ggplot2::ggplot(decomp_df,aes(x=time))+ggplot2::geom_line(aes(y=original,color="Original"))+ggplot2::geom_line(aes(y=trend,color="Trend"))+ggplot2::geom_line(aes(y=seasonal,color="Seasonal"))+ggplot2::geom_line(aes(y=random,color="Random"))+ggplot2::theme_minimal()+ggplot2::labs(title="Time Series Decomposition",x="Time",y="Value",color="Component")}return(plots)}#' Create regression plots#'#' @param regression_results Regression results#' @return List of regression plotscreate_regression_plots<-function(regression_results){plots<-list()model<-regression_results$model# Residuals vs fittedplots$residuals<-ggplot2::ggplot(data.frame(fitted=fitted(model),residuals=residuals(model)),aes(x=fitted,y=residuals))+ggplot2::geom_point()+ggplot2::geom_hline(yintercept=0,linetype="dashed")+ggplot2::theme_minimal()+ggplot2::labs(title="Residuals vs Fitted",x="Fitted Values",y="Residuals")# Q-Q plotplots$qq<-ggplot2::ggplot(data.frame(residuals=residuals(model)),aes(sample=residuals))+ggplot2::stat_qq()+ggplot2::stat_qq_line()+ggplot2::theme_minimal()+ggplot2::labs(title="Q-Q Plot of Residuals",x="Theoretical Quantiles",y="Sample Quantiles")return(plots)}
# Data importdata<-import_data("csv","data/raw/dataset.csv")# Data validationvalidation<-validate_data(data,schema)if(!validation$valid)stop("Data validation failed")# Data cleaningcleaned_data<-clean_data(data,cleaning_config)# Analysisresults<-perform_analysis(cleaned_data,analysis_config)# Visualizationplots<-create_visualizations(cleaned_data,results,viz_config)# Report generationreport_path<-generate_report(results,report_config)