If you have your own data, import the data frame into R having set the variable names as follows:
- pH measurements in the first column as “pH”
- Anion exchange measurements in the second column as “Anion”
- Cation exchange measurements in the third (and last) column as “Cation”
Or if you want to use the R code only, just input your PZC data manually into the respective strings (ph, anion, and cation). Make sure to fill out the strings in order of the observations, starting with the first PZC measurement. For this all to work, I might add, your cation exchange values will be positive when recorded, but it’ll be treated as negative during the calculation.
# packages library(tidyverse)
data <- tibble(pH = c(3.2, 3.4, 3.75, 4.1, 4.85, 6.4, 6.7), Anion = c(2.6, 2.3, 1.7, 1.4, 0.7, 0.055, 0.052), Cation = -c(0.76, 0.81, 0.64, 0.71, 1.34, 2.42, 3.31))
The net charge is the difference between the anion and cation charges. Anion exchange capacity has positive net charge. Cation exchange capacity has negative net charge. Once net charge is calculated, arrange the data frames and sort by the net charge in descending order.
data <- mutate(data, Net = Anion + Cation) %>% arrange(desc(Net))
This code finds the exact point of zero charge, so that 1) it can be known exactly rather than eye-balling the plot, and 2) it can be plotted.
# find pzc by calculating slope of line between last positive (AEC) point pos <- filter(data, Net > 0) %>% select(pH, Net) %>% tail(n = 1) # and first negative (CEC) point neg <- filter(data, Net < 0) %>% select(pH, Net) %>% head(n = 1) # and finding point of x-intercept pzc <- ((0 - pos$Net) / ((neg$Net - pos$Net) / (neg$pH - pos$pH))) + pos$pH pzc_label <- round(pzc, digits = 2)
Then, plot PZC.
data %>% pivot_longer(names_to = "Measure", values_to = "Value", cols = 2:4) %>% mutate(Measure = factor(Measure, levels = c('Anion', 'Net', 'Cation'))) %>% ggplot(aes(x = pH, y = Value, linetype = Measure)) + geom_line() + geom_point() + # zero line geom_hline(yintercept = 0, alpha = 0.4) + # PZC point geom_point(aes(x = pzc, y = 0), color = "#CC0000", size = 3, pch = 1) + # annotations for labels annotate(geom = 'text', label = pzc_label, x = pzc + 0.1, y = 0.3, family = rc) + annotate(geom = 'text', label = "AEC +", x = min(data$pH), y = 0.2, family = rc) + annotate(geom = 'text', label = "CEC -", x = min(data$pH), y = -0.2, family = rc) + scale_x_continuous(breaks = seq(0, 14, 0.5)) + scale_linetype_manual(values = c(2, 1, 3)) + labs(title = "Point of Zero Charge", x = "pH", y = "Net Charge", linetype = NULL, caption = "source: gradcylinder")
To make your life easier, below is a link to the R code so that you do not have to copy and paste code chunks from this page.