1 - Importing the Raw LMD Data
library(readxl)
LMD = read_excel("C:/Users/Samsung/OneDrive/Documentos/2 - Material de trabalho/7 - Projetos/7.1 Pesquisa/LMD/LMD Raw Data 06-24 apr 2026.xlsx", sheet = "R table")
head(LMD)
This chunk imports the raw LMD dataset from the Excel file into R for
further cleaning and processing.
2 - Summarizing Calibration Data
# Separate calibration data
Calibration = subset(LMD, treatment == "Calibration")
# Calibration summary
Calibration_summary = data.frame(
Mean = mean(Calibration$ppm.m, na.rm = TRUE),
SD = sd(Calibration$ppm.m, na.rm = TRUE),
Min = min(Calibration$ppm.m, na.rm = TRUE),
Max = max(Calibration$ppm.m, na.rm = TRUE))
head(Calibration_summary)
writexl::write_xlsx(Calibration, "1 - Calibration Data.xlsx")
This chunk separates the calibration records and calculates the mean,
standard deviation, minimum, and maximum ppm values.
3 - Removing Calibration Records
LMD = subset(LMD, treatment != "Calibration" | is.na(treatment))
print(LMD)
## # A tibble: 621,871 × 9
## SerialNo SessionName treatment DateTime ppm.m `Distance(m)`
## <dbl> <dbl> <chr> <dttm> <dbl> <dbl>
## 1 4647 865 G2 2026-04-06 11:00:35 0 1
## 2 4647 865 G2 2026-04-06 11:00:35 0 1
## 3 4647 865 G2 2026-04-06 11:00:35 0 1
## 4 4647 865 G2 2026-04-06 11:00:35 0 1
## 5 4647 865 G2 2026-04-06 11:00:35 0 1
## 6 4647 865 G2 2026-04-06 11:00:35 0 1
## 7 4647 865 G2 2026-04-06 11:00:35 0 1
## 8 4647 865 G2 2026-04-06 11:00:35 0 1
## 9 4647 865 G2 2026-04-06 11:00:35 0 1
## 10 4647 865 G2 2026-04-06 11:00:34 0 1
## # ℹ 621,861 more rows
## # ℹ 3 more variables: Latitude <dbl>, Longitude <dbl>, Media <chr>
writexl::write_xlsx(LMD, "2 - Main data without Calibration.xlsx")
This chunk removes all rows identified as Calibration, retaining only
the measurement data.
4.2 - Background: Identifying Values Outside the Central 95%
Range
# Define the central 95% range
Lower_limit = quantile(Background$ppm.m, 0.025, na.rm = TRUE)
Upper_limit = quantile(Background$ppm.m, 0.975, na.rm = TRUE)
Lower_limit
## 2.5%
## 0
Upper_limit
## 97.5%
## 34.65
Outliers = subset(Background, ppm.m < Lower_limit | ppm.m > Upper_limit)
nrow(Outliers)
## [1] 151
head(Outliers)
Background_clean = subset(Background,ppm.m >= Lower_limit & ppm.m <= Upper_limit)
print(Background_clean)
## # A tibble: 5,864 × 9
## SerialNo SessionName treatment DateTime ppm.m `Distance(m)`
## <dbl> <dbl> <chr> <dttm> <dbl> <dbl>
## 1 4647 865 G2 2026-04-06 10:58:43 0 20
## 2 4647 865 G2 2026-04-06 10:58:43 0 20
## 3 4647 865 G2 2026-04-06 10:58:43 0 20
## 4 4647 865 G2 2026-04-06 10:58:43 0 20
## 5 4647 865 G2 2026-04-06 10:58:42 0 20
## 6 4647 865 G2 2026-04-06 10:58:42 0 20
## 7 4647 865 G2 2026-04-06 10:58:42 0 20
## 8 4647 865 G2 2026-04-06 10:58:42 0 20
## 9 4647 865 G2 2026-04-06 10:58:42 0 20
## 10 4647 865 G2 2026-04-06 10:58:42 0 20
## # ℹ 5,854 more rows
## # ℹ 3 more variables: Latitude <dbl>, Longitude <dbl>, Media <chr>
writexl::write_xlsx(Background_clean, "4 - Background_clean.xlsx")
This chunk identifies ppm measurements below the 2.5th percentile or
above the 97.5th percentile as potential outliers.
4.3 - Background: Averaging ppm Measurements per
Second
# Background summary
Background_summary = data.frame(
Mean = mean(Background_clean$ppm.m, na.rm = TRUE),
SD = sd(Background_clean$ppm.m, na.rm = TRUE),
Min = min(Background_clean$ppm.m, na.rm = TRUE),
Max = max(Background_clean$ppm.m, na.rm = TRUE))
Background_summary
This chunk summarizes their ppm values.
5.1 - Main data - Identifying Values Outside the Central 95%
Range
# Define the central 95% range
Lower_limit = quantile(LMD$ppm.m, 0.025, na.rm = TRUE)
Upper_limit = quantile(LMD$ppm.m, 0.975, na.rm = TRUE)
Lower_limit
## 2.5%
## 0
Upper_limit
## 97.5%
## 24
Outliers = subset(LMD, ppm.m < Lower_limit | ppm.m > Upper_limit)
nrow(Outliers)
## [1] 15173
head(Outliers)
LMD_clean = subset(LMD,ppm.m >= Lower_limit & ppm.m <= Upper_limit)
head(LMD_clean)
writexl::write_xlsx(LMD_clean, "5 - LMD_clean.xlsx")
This chunk identifies ppm measurements below the 2.5th percentile or
above the 97.5th percentile as potential outliers.
5.2 - Main data - Measurement Frequency per Second
# Count the number of measurements per second
Measurements_per_second = as.data.frame(table(LMD$DateTime))
Measurements_per_second
names(Measurements_per_second) = c("DateTime", "Measurements")
# Summary of measurements per second
Measurement_rate_summary = data.frame(
Mean = mean(Measurements_per_second$Measurements),
SD = sd(Measurements_per_second$Measurements),
Min = min(Measurements_per_second$Measurements),
Max = max(Measurements_per_second$Measurements))
Measurements_per_second[Measurements_per_second$Measurements == max(Measurements_per_second$Measurements),]
Measurement_rate_summary
This chunk counts the number of LMD measurements recorded each second
and calculates the mean, standard deviation, minimum, and maximum
measurement frequency.The obtained average can also be interpreted
approximately as the sampling frequency in Hz.
5.3 - Main data - Averaging ppm Measurements per
Second
names(LMD)
## [1] "SerialNo" "SessionName" "treatment" "DateTime" "ppm.m"
## [6] "Distance(m)" "Latitude" "Longitude" "Media"
LMD_second = aggregate(ppm.m ~ SerialNo + SessionName + treatment + DateTime + `Distance(m)`,
data = LMD,FUN = mean,na.rm = TRUE)
head(LMD_second)
writexl::write_xlsx(LMD_second, "6 - LMD_clean_second.xlsx")
This chunk averages all ppm measurements recorded within each second,
resulting in one ppm value per second.
6 - Background correction: Subtracting mean background from ppm
values
# Subtract the mean background value
LMD_second$ppm.m = LMD_second$ppm.m - Background_summary$Mean
# Remove negative values
LMD_second_corr = subset(LMD_second, ppm.m >= 0)
LMD_second_corr$ppm.m = round(LMD_second_corr$ppm.m, 2)
head(LMD_second_corr)
writexl::write_xlsx(LMD_second_corr, "7 - LMD_clean_second_background_correction.xlsx")
This chunk corrects the ppm measurements by subtracting the mean
background concentration from each observation. Negative corrected
values are removed, and the remaining ppm values are rounded to two
decimal places.