[R package] Log Response Ratio and Effect Size Calculation (feat. lrr)

[R package] Log Response Ratio and Effect Size Calculation (feat. lrr)

When conducting a meta-analysis, results from multiple studies must be synthesized despite differences in measurement scales, experimental designs, and reported units. To enable meaningful comparisons across studies, effect sizes are commonly used. One of the most widely applied effect size metrics in ecological and agricultural research is the Log Response Ratio (LRR).

The Log Response Ratio is calculated as:

LRR = ln(Xt / Xc)

where Xt represents the mean response of the treatment group and Xc represents the mean response of the control group.

This metric expresses the proportional change caused by a treatment on a logarithmic scale, making it dimensionless and comparable across studies.

The LRR offers an intuitive interpretation: positive values indicate an increase in the response variable due to treatment, negative values indicate a decrease, and a value of zero indicates no treatment effect.

Because it standardizes treatment effects relative to controls, LRR is particularly useful for assessing how response variables such as crop yield, biomass, or nutrient uptake respond to experimental treatments across diverse experimental contexts.

In addition to reporting the Log Response Ratio (LRR), it is essential to present its 95% confidence interval (CI). While the LRR provides a point estimate of the magnitude and direction of a treatment effect, the confidence interval quantifies the uncertainty and precision associated with that estimate. The 95% confidence interval represents the range within which the true effect size is expected to lie with 95% confidence, given the sampling variability of the data. In meta-analysis, where effect sizes are synthesized across studies with differing sample sizes and variances, this information is critical for proper interpretation. Moreover, the width of the confidence interval reflects the precision of the estimated effect size. Narrow confidence intervals indicate high precision, often resulting from large sample sizes or low variability, whereas wide intervals indicate greater uncertainty. This distinction is particularly important in meta-analysis, where studies with more precise estimates are typically given greater weight in the overall analysis through inverse-variance weighting.

To easily calculate LRR with CI, I developed a new R function named, lrr().

1. Install lrr() package

Before installing, please download Rtools (https://cran.r-project.org/bin/windows/Rtools)

if(!require(remotes)) install.packages("remotes")
if (!requireNamespace("lrr", quietly= TRUE)) {
 remotes::install_github("agronomy4future/lrr", force= TRUE)
}
library(remotes)
library(lrr)

2. Data example

df= data.frame(Cultivar= rep(c("CV1", "CV2", "CV3", "CV4", "CV5", "CV6", "CV7", "CV8"), each = 4L), Block= rep(c("I", "II", "III", "IV"), 8), N0= c(608.9, 464.7, 199.3, 930, 623.7, 43.1, 200.3, 207.7, 1243.7, 776.7, 1424.5, 1556.4, 352.2, 1316.7, 377.7, 980.8, 660.9, 1535.5, 1009.2, 1490.8, 692.6, 1273.9, 1010.7, 1105.8, 695, 869, 396, 1147, 883.9, 786.6, 416.2, 1512.6),N1= c(697.6, 601.9, 1063.4, 440.6, 313, 109.9, 119.9, 281.3, 3463.1, 1364.8, 1991.9, 1264, 1837.9, 1382.5, 1160.5, 248.9, 1679.7, 1704.4, 1631.7, 1065.9, 2466.4, 1324.5, 3790.1, NA, 1735, 872.3, 2314, NA, 2001.4, 1700.4, 2521.4, NA))
print(head (df, 5))
  Cultivar Block    N0     N1
1      CV1     I 608.9  697.6
2      CV1    II 464.7  601.9
3      CV1   III 199.3 1063.4
4      CV1    IV 930.0  440.6
5      CV2     I 623.7  313.0
.
.
.

3. Run code

output= lrr(data= df, trt= N0, ctrl= N1, group = c("Cultivar"))

print(output)
  Cultivar n_T n_C n_LRR          LRR     LRR_L     LRR_U    Cohen_d   Hedges_g
1      CV1   4   4     4 -0.330514832 -1.924442 1.2634125 -0.5269730 -0.4582374
2      CV2   4   4     4 -0.009187594 -1.209322 1.1909472  0.3279905  0.2852091
3      CV3   4   4     4 -0.428739063 -1.243705 0.3862267 -1.0188530 -0.8859592
4      CV4   4   4     4 -0.363033297 -2.487070 1.7610031 -0.6920945 -0.6018213
5      CV5   4   4     4 -0.295524032 -1.154888 0.5638399 -0.9486484 -0.8249117
6      CV6   3   3     3 -0.876921152 -2.680809 0.9269668 -1.7118456 -1.3694765
7      CV7   3   3     3 -0.894653273 -3.083024 1.2937177 -1.8273893 -1.4619115
8      CV8   3   3     3 -1.129853628 -2.575724 0.3160167 -4.0361639 -3.2289311

If the Block is included, the CI is not calculated because there are no replicates, but this LRR values can be used for geom_jitter.

output1= lrr(data= df, trt= N0, ctrl= N1, group = c("Cultivar", "Block"))

print(output1)  
   Cultivar Block n_T n_C n_LRR          LRR LRR_L LRR_U Cohen_d Hedges_g
1       CV1     I   1   1     1 -0.135991822    NA    NA      NA       NA
2       CV2     I   1   1     1  0.689466293    NA    NA      NA       NA
3       CV3     I   1   1     1 -1.024073334    NA    NA      NA       NA
4       CV4     I   1   1     1 -1.652179698    NA    NA      NA       NA
5       CV5     I   1   1     1 -0.932767943    NA    NA      NA       NA
6       CV6     I   1   1     1 -1.270062245    NA    NA      NA       NA
7       CV7     I   1   1     1 -0.914850847    NA    NA      NA       NA
8       CV8     I   1   1     1 -0.817258281    NA    NA      NA       NA
9       CV1    II   1   1     1 -0.258699282    NA    NA      NA       NA
10      CV2    II   1   1     1 -0.936047864    NA    NA      NA       NA
11      CV3    II   1   1     1 -0.563709001    NA    NA      NA       NA
12      CV4    II   1   1     1 -0.048764848    NA    NA      NA       NA
13      CV5    II   1   1     1 -0.104357082    NA    NA      NA       NA
14      CV6    II   1   1     1 -0.038951969    NA    NA      NA       NA
15      CV7    II   1   1     1 -0.003790276    NA    NA      NA       NA
16      CV8    II   1   1     1 -0.770898936    NA    NA      NA       NA
17      CV1   III   1   1     1 -1.674415374    NA    NA      NA       NA
18      CV2   III   1   1     1  0.513158181    NA    NA      NA       NA
19      CV3   III   1   1     1 -0.335268082    NA    NA      NA       NA
20      CV4   III   1   1     1 -1.122505996    NA    NA      NA       NA
21      CV5   III   1   1     1 -0.480464478    NA    NA      NA       NA
22      CV6   III   1   1     1 -1.321749244    NA    NA      NA       NA
23      CV7   III   1   1     1 -1.765318696    NA    NA      NA       NA
24      CV8   III   1   1     1 -1.801403668    NA    NA      NA       NA
25      CV1    IV   1   1     1  0.747047152    NA    NA      NA       NA
26      CV2    IV   1   1     1 -0.303326985    NA    NA      NA       NA
27      CV3    IV   1   1     1  0.208094166    NA    NA      NA       NA
28      CV4    IV   1   1     1  1.371317356    NA    NA      NA       NA
29      CV5    IV   1   1     1  0.335493376    NA    NA      NA       NA

4. Visualization

ggplot() +
  geom_jitter(data= output1, aes(x= Cultivar, y= LRR, fill= Cultivar, shape= Cultivar),
              width=0.2, alpha=0.5, size=2, color="grey75") +               
  geom_point(data=output, aes(x=Cultivar, y=LRR, fill=Cultivar, shape=Cultivar), 
                            color= "black", size= 3) +
  geom_errorbar(data=output, aes(x=Cultivar, ymin= LRR_L, ymax= LRR_U),
               width=0.2, linewidth=0.5, color="black") +
  geom_hline(yintercept=0, linetype="dashed", color= "red") +
  scale_fill_manual(values = c("cadetblue", "darkred", "orange", "darkblue", "grey35", 
                               "purple", "darkolivegreen", "coral3")) +
  scale_shape_manual(values = rep(22, 8)) +
  scale_y_continuous(breaks = seq(-4, 4, 1), limits = c(-4, 4)) +
  coord_flip () +
  labs(x="Cultivar", y="Effect size (Log Response Ratio)") +
  theme_classic(base_size= 18, base_family = "serif") +
  theme(legend.position="none",
        legend.title=element_blank(),
        legend.key=element_rect(color="white", fill=alpha(0.5)),
        legend.text=element_text(family="serif", face="plain",
                                 size=15, color="black"),
        legend.background= element_rect(fill=alpha(0.5)),
        strip.background=element_rect(color="white",
                                      linewidth=0.5,linetype="solid"),
        panel.border= element_rect(color="black", fill=NA, linewidth=0.5),
        axis.line= element_line(linewidth= 0.5, colour= "black"))
Code summary: https://github.com/agronomy4future/r_code/blob/main/Log__Response_Ratio_and_Effect_Size_Calculation.ipynb

We aim to develop open-source code for agronomy ([email protected])

© 2022 – 2025 https://agronomy4future.com – All Rights Reserved.

Last Updated: 12/15/2025

Comments are closed.