1

I have measured soil organic matter (SOM) content for different soil horizons (i.e. different soil layers). Now I would like to plot the SOM content for the different horizons in a horizontal way, for each soil profile (i.e. each spot where I dug a hole and took soil samples) individually. I'll just add a sketch to describe what kind of plot I'd like to have:

enter image description here

I'd like to have the bars representing the SOM content, and want their left and right border to represent the top and bottom end of each horizon, respectively - so the bar width would illustrate the thickness of each horizon (soil layer). Basically, this would give me a soil profile, just in a horizontal instead of a vertical order.

Now, as I have a total of 24 profiles with different soil types, I would probably use facet_grid or facet_wrap to plot each soil profile individually. However, I'm quite lost how to do the rest. Does anybody have suggestions? I got stuck after a first trial with a subset of my data:

barplot <- ggplot(TSM1, aes(x=top, y=SOM)) + geom_col()

I'll attach a data subset with data of 3 soil profiles here below:

    structure(list(tmp_id = 1:19, Profil = structure(c(10L, 10L, 
10L, 10L, 10L, 10L, 10L, 11L, 11L, 11L, 11L, 11L, 12L, 12L, 12L, 
12L, 12L, 12L, 12L), .Label = c("TNH1", "TNH2", "TNH3", "TNM1", 
"TNM2", "TNM3", "TSH1", "TSH2", "TSH3", "TSM1", "TSM2", "TSM3", 
"VNH1", "VNH2", "VNH3", "VNM1", "VNM2", "VNM3", "VSH1", "VSH2", 
"VSH3", "VSM1", "VSM2", "VSM3"), class = "factor"), site = structure(c(4L, 
4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 4L, 
4L, 4L), .Label = c("TNH", "TNM", "TSH", "TSM", "VNH", "VNM", 
"VSH", "VSM"), class = "factor"), elevation = structure(c(2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L), .Label = c("high", "mid"), class = "factor"), exposition = structure(c(2L, 
2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
2L, 2L), .Label = c("north", "south"), class = "factor"), region = structure(c(1L, 
1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
1L, 1L), .Label = c("ticino", "valais"), class = "factor"), Horizon = structure(c(42L, 
24L, 18L, 19L, 41L, 11L, 12L, 42L, 24L, 26L, 40L, 20L, 42L, 24L, 
18L, 19L, 44L, 1L, 17L), .Label = c("[IICsi]", "[nOL-vOL]", "[nOL]-vOL-S*", 
"[OF]", "[vOL-S*]", "A", "A-S1", "Acaho", "bryOF", "bryOH", "Csi", 
"Dsi", "g", "IIA", "IICsi", "IICsi&Dsi", "IIDsi", "ligOF", "ligOH", 
"Msi", "nOL-[vOL]-[S*]", "nOL-vOL", "nOL-vOL-[S*]", "OF", "OF-[OH]", 
"OH", "rhiA", "rhiA-S1", "rhiA1", "rhiA2", "rhiAho", "rhiAho-Csi", 
"rhiOF", "rhiOH", "S", "S1", "S2", "Sal", "Sal-Csi", "sgA", "sgAho", 
"vOL", "Xp", "Xp&[Aho]", "Xpcaho", "Xpcaho "), class = "factor"), 
    Horizon_order = c(0L, 0L, 0L, 0L, 1L, 2L, 3L, 0L, 0L, 0L, 
    1L, 2L, 0L, 0L, 0L, 0L, 1L, 2L, 3L), Horizon_type = structure(c(1L, 
    2L, 4L, 8L, 10L, 15L, 16L, 1L, 2L, 6L, 10L, 16L, 1L, 2L, 
    4L, 8L, 12L, 15L, 16L), .Label = c("H1", "H2", "H2a", "H2b", 
    "H2c", "H3", "H3a", "H3b", "H3c", "H4", "H4a", "H4b", "H5", 
    "H5b", "H6", "H7", "H7b", "H8"), class = "factor"), Sol_ref = structure(c(7L, 
    7L, 7L, 7L, 7L, 7L, 7L, 13L, 13L, 13L, 13L, 13L, 8L, 8L, 
    8L, 8L, 8L, 8L, 8L), .Label = c("ALOCRISOL TYPIQUE", "BRUNISOL DYSTRIQUE", 
    "BRUNISOL DYSTRIQUE à horizon rédoxique de profondeur", "COLLUVIOSOL", 
    "COLLUVIOSOL brunifié", "COLLUVIOSOL leptique", "ORGANOSOL", 
    "ORGANOSOL (holorganique)", "ORGANOSOL holorganique", "ORGANOSOL INSATURE à COLLUVIOSOL", 
    "ORGANOSOL SATURE à COLLUVIOSOL", "PEYROSOL pierrique humifère calcaire", 
    "REGOSOL d'apport"), class = "factor"), Type_sol = structure(c(4L, 
    4L, 4L, 4L, 4L, 4L, 4L, 6L, 6L, 6L, 6L, 6L, 4L, 4L, 4L, 4L, 
    4L, 4L, 4L), .Label = c("ALOCRISOL", "BRUNISOL", "COLLUVIOSOL", 
    "ORGANOSOL", "PEYROSOL", "REGOSOL"), class = "factor"), Type_humus = structure(c(3L, 
    3L, 3L, 3L, 3L, 3L, 3L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L), .Label = c("Dysmull", "Humimor", "ligno", "ligno Humimor", 
    "ligno/bryo", "Mésomull", "Oligomull", "rhizo Dysmoder", 
    "rhizo Eumoder", "rhizo Hémimoder", "rhizo Mésomull", "rhizo Oligomull"
    ), class = "factor"), N_deca = c(NA_real_, NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_), C_deca = c(NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, 
    NA_real_, NA_real_, NA_real_, NA_real_, NA_real_, NA_real_
    ), N = c(NA, NA, NA, NA, 0.33, 0.16, NA, NA, NA, NA, 0.25, 
    0.09, NA, NA, NA, NA, 0.56, 0.21, NA), C = c(NA, NA, NA, 
    NA, 9.95, 3.16, NA, NA, NA, NA, 6.29, 2.23, NA, NA, NA, NA, 
    11.65, 4.93, NA), C.N = c(NA, NA, NA, NA, 30.56, 20.26, NA, 
    NA, NA, NA, 24.87, 23.97, NA, NA, NA, NA, 20.82, 23.43, NA
    ), HR = c(NA, NA, NA, NA, 2.6, 1.79, NA, NA, NA, NA, 2.58, 
    1.91, NA, NA, NA, NA, 4.28, 4.42, NA), PAF = c(NA, NA, NA, 
    NA, 16.97, 6.71, NA, NA, NA, NA, 13.34, 5.44, NA, NA, NA, 
    NA, 22.11, 10.06, NA), SOM = c(NA, NA, NA, NA, 8.49, 3.35, 
    NA, NA, NA, NA, 6.67, 2.72, NA, NA, NA, NA, 11.06, 5.03, 
    NA), Argile = c(NA, NA, NA, NA, 3.78, 3.75, NA, NA, NA, NA, 
    3.05, 5.33, NA, NA, NA, NA, 3.78, 7.08, NA), Limon = c(NA, 
    NA, NA, NA, 32.76, 27.26, NA, NA, NA, NA, 28.44, 40.9, NA, 
    NA, NA, NA, 33.2, 47.65, NA), Sable = c(NA, NA, NA, NA, 63.47, 
    68.99, NA, NA, NA, NA, 68.51, 53.77, NA, NA, NA, NA, 63.02, 
    45.26, NA), pH = c(NA, NA, NA, NA, 3.76, 4.11, NA, NA, NA, 
    NA, 4.29, 4.94, NA, NA, NA, NA, 3.94, 4.8, NA), CEC_tot = c(NA, 
    NA, NA, NA, 8.43, 4.21, NA, NA, NA, NA, 7.83, 1.24, NA, NA, 
    NA, NA, 11.87, 6.1, NA), CO3 = c(NA, NA, NA, NA, 0.8, 0.89, 
    NA, NA, NA, NA, 0.88, 0.96, NA, NA, NA, NA, 0.82, 0.91, NA
    ), K = c(NA, NA, NA, NA, 0.02, 0.02, NA, NA, NA, NA, 0.02, 
    0.02, NA, NA, NA, NA, 0.03, 0.02, NA), Mg = c(NA, NA, NA, 
    NA, 0, 0, NA, NA, NA, NA, 0.01, 0.01, NA, NA, NA, NA, 0.01, 
    0.01, NA), Ca = c(NA, NA, NA, NA, 0, 0, NA, NA, NA, NA, 0, 
    0, NA, NA, NA, NA, 0, 0, NA), Na = c(NA, NA, NA, NA, 0.01, 
    0.01, NA, NA, NA, NA, 0.02, 0.02, NA, NA, NA, NA, 0.02, 0.02, 
    NA), CEC.T = c(NA, NA, NA, NA, 4.84, 1.14, NA, NA, NA, NA, 
    21.51, 29.74, NA, NA, NA, NA, 19.09, 19.55, NA), Munsell = structure(c(NA, 
    NA, 24L, 22L, 8L, 11L, NA, NA, NA, 5L, 9L, 14L, NA, NA, NA, 
    22L, 9L, 11L, NA), .Label = c("10YR", "10YR2/1", "10YR2/2", 
    "10YR2/2 foncé", "10YR3/3", "10YR3/4", "10YR3/6", "10YR4/2", 
    "10YR4/3", "10YR4/4", "10YR4/6", "10YR5/4", "10YR5/6", "10YR5/8", 
    "2.5Y3/2", "2.5Y4/1", "2.5YR4/1", "5YR2.5/1", "5YR3/3", "7.5YR", 
    "7.5YR2.5/2", "7.5YR2.5/3", "7.5YR3/1", "7.5YR3/3", "7.5YR4/2", 
    "7.5YR5/6"), class = "factor"), hue = structure(c(NA, NA, 
    5L, 5L, 1L, 1L, NA, NA, NA, 1L, 1L, 1L, NA, NA, NA, 5L, 1L, 
    1L, NA), .Label = c("10YR", "2.5Y", "2.5YR", "5YR", "7.5YR"
    ), class = "factor"), value = c(NA, NA, 3L, 3L, 4L, 4L, NA, 
    NA, NA, 3L, 4L, 5L, NA, NA, NA, 3L, 4L, 4L, NA), chroma = c(NA, 
    NA, 3L, 3L, 2L, 6L, NA, NA, NA, 3L, 3L, 8L, NA, NA, NA, 3L, 
    3L, 6L, NA), top = c(1.25, 0, 1, 5, 19, 23, 33, 2.5, 0, 3.5, 
    6, 8.5, 2.5, 0, 2, 6, 13, 31, 38.5), bottom = c(0, 1, 5, 
    19, 23, 33, NA, 0, 3.5, 6, 8.5, NA, 0, 2, 6, 13, 31, 38.5, 
    NA), Classe = structure(c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("Caricetea curvulae", 
    "Fraxino-Fagetea", "Vaccinio-Picetea"), class = "factor"), 
    Alliance = structure(c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("Abieti-Piceion", 
    "Caricion curvulae", "Dicrano-Pinion", "Fagion", "Nardion strictae", 
    "Rhododendro-Vaccinion", "Vaccinio-Piceion"), class = "factor"), 
    Association = structure(c(3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L, 3L), .Label = c("Abieti-Fagetum", 
    "Adenostylo-Abietetum", "Calluno-Pinetum", "Carici curvulae-Nardetum", 
    "Geo montani-Nardetum", "Homogyno-Piceetum", "Hypochoerido-Nardetum", 
    "Larici-Piceetum", "Rhododendro ferruginei-Vaccinietum"), class = "factor"), 
    Localite = structure(c(5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 
    5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L, 5L), .Label = c("Campo_tencia", 
    "Dalpe", "La Forcle", "La Tourche", "Osco", "Predelp", "Valassier", 
    "Valerette"), class = "factor"), Canton = structure(c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 1L, 
    1L, 1L, 1L), .Label = c("Tessin", "Valais-Vaud"), class = "factor"), 
    Exposition = structure(c(2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L), .Label = c("North", 
    "South"), class = "factor"), Altitude = structure(c(2L, 2L, 
    2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 2L, 
    2L, 2L), .Label = c("High", "Mid"), class = "factor"), Profil.1 = c(1L, 
    1L, 1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 
    3L, 3L, 3L), Latitude = c(702521L, 702521L, 702521L, 702521L, 
    702521L, 702521L, 702521L, 702762L, 702762L, 702762L, 702762L, 
    702762L, 702929L, 702929L, 702929L, 702929L, 702929L, 702929L, 
    702929L), Longitude = c(150999L, 150999L, 150999L, 150999L, 
    150999L, 150999L, 150999L, 150835L, 150835L, 150835L, 150835L, 
    150835L, 150630L, 150630L, 150630L, 150630L, 150630L, 150630L, 
    150630L), Slope = c(20L, 20L, 20L, 20L, 20L, 20L, 20L, 35L, 
    35L, 35L, 35L, 35L, 20L, 20L, 20L, 20L, 20L, 20L, 20L)), row.names = c(NA, 
19L), class = "data.frame")

Relevant variables/factors:

  • Profil = unique name/identifier for each profile
  • SOM = soil organic matter (in %)
  • top = top margin of each soil horizon (soil layer)
  • bottom = bottom margin of each soil horizon
paki
  • 21
  • 2
  • veeeeery related https://stackoverflow.com/questions/20688376/how-to-make-variable-bar-widths-in-ggplot2-not-overlap-or-gap and https://stackoverflow.com/questions/66197720/overlapping-barplot-histogram-with-variable-widths?noredirect=1&lq=1 and https://stackoverflow.com/questions/11345943/bar-graph-in-ggplot2-with-width-as-a-variable-and-even-spacing-between-bars?noredirect=1&lq=1 – tjebo Jan 31 '22 at 18:03
  • Thanks for the post links - I'm still at the very beginning of learning R language, and sometimes I struggle to find accurate terms/descriptions for my problems, being a non-native speaker and not very trained in using rather technical terms... I'll try to use the search function in more accurate ways :) – paki Feb 01 '22 at 08:47
  • paki - this was a good first question. I'm voting to close this as a duplicate, don't worry if the question has been asked before, it helps making other answers more visible. – tjebo Feb 01 '22 at 08:59
  • Does this answer your question? [Overlapping barplot/histogram with variable widths](https://stackoverflow.com/questions/66197720/overlapping-barplot-histogram-with-variable-widths) – tjebo Feb 01 '22 at 09:00

1 Answers1

1

It seems to me that what you're describing isn't a typical bar plot, but what you describe can be done with geom_rect().

library(ggplot2)

# df <- structure(...) # omitted for brevity

ggplot(df, aes(x = top, y = SOM)) +
  geom_rect(
    aes(xmin = bottom, xmax = top, ymin = 0, ymax = SOM)
  ) +
  facet_wrap(~ Profil)
#> Warning: Removed 14 rows containing missing values (geom_rect).

teunbrand
  • 33,645
  • 4
  • 37
  • 63
  • Thanks a lot! I didn't know this geom type, now it seems like a "silly" question to me, seeing this easy way...Still have to get more into all the terms of R language. – paki Feb 01 '22 at 08:45
  • I have one additional question. I'd like to add also the other horizons so I can see the full sequence of each soil profile, even though I do not have SOM results for the remaining horizons. So I made a subset where I only have the rows with SOM = NA, I changed the "NA" to have a constant value of 2.5 for all ( I would color it differently so one can distinguish between measured and not-measured horizons), and tried to add those by just using two geom_rect. However, this does not work. Do you have an idea how to make it function? – paki Feb 01 '22 at 10:36