Reputation: 11
I have a soil texture data set. I made a soil texture triangle representing soil texture from different projects.
I want to add a centroid to the texture triangle, but only for projects with different textures. I want to show on a plot that even with different textures in one single project they belong to the same project.
Is it possible to do this using ggplot2 or is there a specific package that can do it?
Here is what I tried with the ggplot2 code. I tried two versions of plotting the centroids on a soil texture triangle. I was able to add those centroids, but in my trial Version 1, not all projects with different textures have centroids. While in my trial Version 2, altogether different projects have centroids. I want all projects with different textures to have centroids and want all of them to be shown in the plot.
`# Plotting the soil texture triangle
theme_set(theme_bw())
p \<-filtered_soil_triangle %\>%
ggtern(aes(
x = SAND,
y = CLAY,
z = SILT,
color = Project )) +
geom_point(size = ifelse(is.na(filtered_soil_triangle $Project), 0, 6)) +
theme_showarrows() +
labs(yarrow = "Clay (%)",
zarrow = "Silt (%)",
xarrow = "Sand(%)",
color = "Project") +
scale_color_paletteer_d("rcartocolor::Safe") + # Use the Safe color palette
theme_clockwise()+
theme(
legend.title = element_text(size = 14), # Increase legend title size
legend.text = element_text(size = 12) # Increase legend text size
)`
`# Trial Version 1
## Add arrows connecting points with the same Project and different map_texture
### Create a new data frame for segments
segments_data \<- filtered_soil_triangle %\>%
group_by(Project, map_texture) %\>%
arrange(SAND, CLAY, SILT) %\>%
mutate(next_SAND = lead(SAND),
next_CLAY = lead(CLAY),
next_SILT = lead(SILT)) %\>%
filter(!is.na(next_SAND))
### Add segments to the plot
p + geom_segment(data = segments_data,
aes(x = SAND, y = CLAY, z = SILT,
xend = next_SAND, yend = next_CLAY, zend = next_SILT),
arrow = arrow(length = unit(0.01, "inches")),
color = "black",
linewidth = 0.5)`
`# Trial Version 2
## Add arrows connecting points with the same Project and different map_texture
### Create a new data frame for segments
segments_data \<- filtered_soil_triangle %\>%
group_by(Project) %\>%
arrange(SAND, CLAY, SILT) %\>%
mutate(next_SAND = lead(SAND),
next_CLAY = lead(CLAY),
next_SILT = lead(SILT),
next_map_texture = lead(map_texture)) %\>%
filter(!is.na(next_SAND) & map_texture != next_map_texture)
### Add segments to the plot
p + geom_segment(data = segments_data,
aes(x = SAND, y = CLAY, z = SILT,
xend = next_SAND, yend = next_CLAY, zend = next_SILT),
arrow = arrow(length = unit(0.01, "inches")),
color = "black",
linewidth = 0.5) # Use line width instead of size`
Upvotes: 1
Views: 56
Reputation: 834
The question need majors clarifications; I don't think that a "centroid" is required as a summary indicator. However, if the average per project is a valid indicator, here is a reprex to do it with ggplot
(tidyverse
) and ggtern
. You can group_by(Project)
, summarise()
, and filter()
-out the projects with a single site. With some aes
thetic ajustments, the average and site can be represented.
Edit: if a centroid is really needed, sf::st_centroid()
might be usefull. I think that an average do the work, let me know otherwise.
Edit: it seems doable to use st_centroid()
(see second example), however I removed the geometry before plotting in ggtern
,
library(tidyverse)
library(ggtern)
# Data per site
soil_texture_df <- data.frame(SAND=c(12, 20, 80),
SILT=c(50, 48, 5)) |>
mutate(CLAY = 100 - SAND - SILT) |>
mutate(Project = c("A","A","B"))
#Summarise per project
by_project <- soil_texture_df |> group_by(Project) |>
summarise( across(SAND:CLAY, mean), n = n()) |>
filter(n>1)
by_project |>
ggtern(aes(
x = SAND, y = CLAY, z = SILT, color = Project )) +
geom_point( alpha = 0.5, aes(size ="Project average"))+
geom_point( alpha = 1, data = soil_texture_df, aes(size ="Site")) +
scale_size_manual( values = c("Site"=2 ,"Project average" =6 ) )
Created on 2024-12-19 with reprex v2.1.0
(I didn't removed the project with a single site)
project_centroid = soil_texture_df %>%
st_as_sf(coords =c("SAND","SILT","CLAY"), dim ="XYZ", remove =FALSE) %>%
group_by(Project) %>%
summarise(do_union = FALSE) %>%
st_cast("MULTIPOINT") %>% st_centroid() %>%
mutate(SAND = sf::st_coordinates(.)[,1],
SILT = sf::st_coordinates(.)[,2]) %>%
mutate(CLAY = 100 - SAND - SILT) %>%
st_drop_geometry()
project_centroid %>%
ggtern(aes(
x = SAND, y = CLAY, z = SILT, color = Project )) +
geom_point( alpha = 0.5, aes(size ="Project average"))+
geom_point( alpha = 1, data = soil_texture_df, aes(size ="Site")) +
scale_size_manual( values = c("Site"=2 ,"Project average" =6 ) )
Created on 2024-12-19 with reprex v2.0.2
Upvotes: 1