-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmain_v2.Rmd
1968 lines (1592 loc) · 87.5 KB
/
main_v2.Rmd
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
---
title: "Frontier Walls, Labour Energetics and Qin Imperial Collapse"
author:
- Zehao Li
- Giacomo Fontana
- Andrew Bevan
- Rujin Li
date: "2024-03-01"
keep_md: true
output:
html_document:
toc: true
toc_float: true
---
# Setup
```{r}
library(knitr) # For dynamic report generation
library(tidyverse) # Comprehensive suite for data manipulation and visualization
library(sf) # Handling of spatial data and geometries
library(units) # Support for measurement units, useful when dropping geometry for spatial data
library(shotGroups) # Analysis of shot groupings, including minimum bounding box calculation
library(cluster) # Various algorithms for clustering data
library(factoextra) # Visualization tools for clustering
library(ggplot2) # Core plotting system in the tidyverse
library(ggpubr) # Enhancements for ggplot2 to easily create publication-ready plots
library(compareGroups) # Facilitates comparison of groups, mainly through plots
library(ggspatial) # Adds spatial features like scale bars to ggplot2 plots
library(ggsci) # Provides scientific journal and sci-fi themed color palettes
library(kableExtra) # Enables creation and customization of HTML or LaTeX tables
library(scales) # For scaling functions for visualizations
library(ggstatsplot) # Extension of ggplot2 for creating statistical plots easily
library(statsExpressions) # Simplifies the process of creating expressions with statistical details
# Custom theme definition for ggplot2 plots
mytheme <- theme(line = element_blank(), # Remove line elements
panel.grid.major = element_blank(), # No major grid lines
panel.grid.minor = element_blank(), # No minor grid lines
panel.background = element_blank(), # Transparent background
axis.text.x = element_blank(), # Hide x-axis text
axis.text.y = element_blank(), # Hide y-axis text
axis.title.x = element_blank(), # Hide x-axis title
axis.title.y = element_blank(), # Hide y-axis title
plot.title = element_text(size = 8), # Small plot title
legend.key.height = unit(1, 'cm'), # Custom legend key height
legend.key.width = unit(5, 'cm'), # Custom legend key width
legend.title = element_text(size=10), # Custom size for legend title
legend.text = element_text(size = 10), # Custom size for legend text
legend.position="bottom", # Place legend at the bottom
legend.box = "horizontal", # Arrange legend items horizontally
plot.margin = margin(t = 0, # Top margin
r = 0, # Right margin
b = 0, # Bottom margin
l = 0)) # Left margin
# Custom scale annotation for adding to plots (like scale bars)
myscale <- annotation_scale(aes(width_hint=0.1, style="ticks", location='br'), # Aesthetic settings for the scale bar
line_width=1.5, # Line width of the scale bar
height=unit(0.6, "cm"), # Height of the scale bar
pad_y=unit(0.9, "cm"), # Vertical padding
pad_x=unit(2.1, "cm"), # Horizontal padding
text_cex = 1.5) # Text size multiplier
```
## Load data
```{r}
#| label: Load data
#| output: false
# Load the 'wall' shapefile into R as a spatial dataframe, and then perform a series of transformations:
wall <- st_read("Data/wall.shp") %>% # Use st_read to import the shapefile
rename(Site = Site_ID) %>% # Rename the 'Site_ID' column to 'Site' for consistency or clarity
mutate(ID = row_number()) # Add a new column 'ID' that contains a unique identifier for each row/feature
# After loading and transforming, replace any zero values in the 'Depth' column with NA (to handle missing or undefined depths)
wall$Depth[wall$Depth == 0] <- NA
# Load the 'wallgap' shapefile as a spatial dataframe. This dataset likely represents gaps in the wall.
# Similar to the first, it renames 'Site_ID' to 'Site' for consistency across datasets.
wallgap <- st_read("Data/gap.shp") %>%
rename(Site = Site_ID)
# Load the 'wallfilled' shapefile as a spatial dataframe. This file likely represents areas of the wall that have been filled in.
# It also renames 'Site_ID' to 'Site', maintaining consistency with the previous datasets.
wallfilled <- st_read("Data/filled.shp") %>%
rename(Site = Site_ID)
```
# Stone-built Wall Models Generation
```{r}
#| fig-width: 15 # This chunk option sets the default figure width to 15 inches for the output.
#| fig-height: 14 # This chunk option sets the default figure height to 14 inches for the output.
# Begin creating a plot using ggplot2 package, with 'wall' data.
fig.walls <- ggplot(wall) +
geom_sf(size = 0.1) + # Adds spatial data to the plot. 'geom_sf' is used for simple features objects, with a line size of 0.1.
mytheme + # Adds a custom ggplot2 theme, stored in the variable 'mytheme', to style the plot.
myscale + # Adds custom scales for the plot, stored in the variable 'myscale'. Could adjust colors, axes, etc.
# Annotates the plot with text at specified locations.
annotate("text", x = -14, y = 4, size=7.5, label = "Hayehutong") +
annotate("text", x = -14, y = -2, size=7.5, label = "Sichenggong") +
annotate("text", x = -14, y = -8, size=7.5, label = "Xiniwusu") +
annotate("text", x = -14, y = -14, size=7.5, label = "Yonghegong") +
annotate("text", x = -14, y = -20, size=7.5, label = "Bayinnuru") # Each 'annotate' function call adds a label at specified coordinates with a given text size and label.
fig.walls # This line actually generates and displays the plot stored in 'fig.walls'.
# Saves the 'fig.walls' plot to a PNG file in the specified path with given dimensions and resolution.
ggsave("fig.walls.png", path="images", width = 25, height = 15, units = "in", dpi=600)
```
## Models
```{r}
#| fig-width: 9 # Sets the default figure width to 9 inches for the output.
#| fig-height: 7 # Sets the default figure height to 7 inches for the output (corrected to fig-height).
# Set the site of interest for the visualization.
example <- "Hayehutong"
# Create a plot 'a' showing the original model for the specified site.
a <- ggplot(data = (subset(wall, wall$Site == example))) +
geom_sf(size = 0.1) + # Plot spatial features with a border size of 0.1.
mytheme + # Apply custom styling from the 'mytheme' variable.
ggtitle(paste(example, "model")) # Title the plot with the site name and "model".
# Create a plot 'b' showing the filled model for the specified site.
b <- ggplot(data = (subset(wallfilled, wallfilled$Site == example))) +
geom_sf(size = 0.1) + # Plot spatial features with a border size of 0.1.
mytheme + # Apply the same custom styling.
ggtitle(paste(example, "filled model")) # Title this plot with "filled model".
# Create a plot 'c' showing the gap model for the specified site.
c <- ggplot(data = (subset(wallgap, wallgap$Site == example))) +
geom_sf(size = 0.1) + # Plot spatial features with a border size of 0.1.
mytheme + # Apply the same custom styling.
ggtitle(paste(example, "gap model")) + # Title this plot with "gap model".
annotation_scale(aes(width_hint=0.11, style="ticks", location='br'), # Add a scale annotation to the plot.
line_width=1.5,
height=unit(0.45, "cm"),
pad_y=unit(0, "cm"),
pad_x=unit(0, "cm"),
text_cex = 1.5)
# Arrange the three plots vertically in a single figure.
fig.models <- ggarrange(a, b, c, nrow = 3, align = "v")
fig.models # Display the arranged figure.
# Save the arranged figure to a PNG file with specified dimensions and resolution.
ggsave("fig.models.png", path="images", width = 15, height = 7, units = "in", dpi=600)
```
## Area Calculation
```{r}
#| label: Area Calculation
#| output: false
wall$Area <- st_area(wall) # Calculates the area of each feature in the 'wall' spatial object and assigns these values to a new column 'Area' in the 'wall' dataset.
wall <- drop_units(wall) # Removes the units from the 'Area' values calculated above, making the 'wall' dataset easier to work with for further analysis or visualization.
```
### Area plot
```{r}
#| fig-width: 9
#| fig.height: 7
# Extract the 'Area' column from 'wall' dataset.
x <- wall$Area
# Create a vector containing the minimum and maximum values of 'Area'.
ls_val <- c(min(x), max(x))
# Define a gradient fill scale for visualization, from light gray to black, based on the 'Area' values.
myfill <- scale_fill_gradient(limits = c(min(x),max(x)), low = "gray80", high = "black",
na.value = "white", breaks = ls_val,
labels=c(round(min(x), digits=2),
round(max(x), digits=2)))
# Construct the plot using 'ggplot2' and 'sf' packages.
fig.area <- ggplot(wall, aes(fill = Area)) + # Set 'Area' as the fill aesthetic.
geom_sf(size = 0.06) + # Plot the spatial data with a border size of 0.06.
mytheme + # Apply custom theme settings.
myscale + # Apply custom scale settings.
myfill + # Apply the gradient fill defined earlier.
# Adjust the colorbar guide to match specified aesthetics.
guides(fill = guide_colourbar(barwidth = 0.5, barheight = 2, label.position = "left"), ticks = "none") +
theme(legend.position = c(0.935, 0.25)) + # Position the legend.
# Annotate specific locations with labels.
annotate("text", x = -14, y = 4, size=2.5, label = "Hayehutong") +
annotate("text", x = -14, y = -2, size=2.5, label = "Sichenggong") +
annotate("text", x = -14, y = -8, size=2.5, label = "Xiniwusu") +
annotate("text", x = -14, y = -14, size=2.5, label = "Yonghegong") +
annotate("text", x = -14, y = -20, size=2.5, label = "Bayinnuru")
# Display the plot.
fig.area
```
### Calculate rectangularity using minimum bounding box
```{r}
#| output: false
#| cache: true
# Add columns mbb_Area and index
# Initialize new columns in 'wall' with NA values
wall["mbb_Area"] <- NA
wall["Rectangularity"] <- NA
# Initialize a text progress bar to monitor the loop's progress
pb <- txtProgressBar(min=1, max=nrow(wall), style=3)
# Iterate over each row in 'wall'
for(i in 1:nrow(wall)) {
# Extract the matrix of coordinates for the i-th feature's geometry
mat <- wall[i, ][[3]][[1]][[1]]
# Calculate the minimum bounding box (mbb) for the feature
mbb <- getMinBBox(mat)
# Calculate the area of the mbb and store it in the 'mbb_Area' column
wall[i,]$mbb_Area <- mbb$width*mbb$height
# Calculate the Rectangularity index (Area of the shape / Area of the mbb) and store it
wall[i,]$Rectangularity <- wall[i,]$Area/wall[i,]$mbb_Area
# Update the progress bar
setTxtProgressBar(pb, i)
}
# Close the progress bar after the loop completes
close(pb)
```
### Extremes in rectangularity
```{r}
#| fig-width: 9
#| fig.height: 7
#|
# Identifies the index of the feature with the minimum rectangularity (worst fit).
n <- which.min(wall$Rectangularity)
# Extracts the coordinates matrix for this feature to plot its original geometry.
mat <- wall[n,][[3]][[1]][[1]]
# Calculates the oriented minimum bounding box (MBB) for this feature.
mbb <- getMinBBox(mat)
# Creates a plot 'a' visualizing this feature, its points, and its MBB.
a <- ggplot(data = wall[n,]) +
geom_sf() + # Plots the feature using simple features geometry.
geom_point(data=(as.data.frame(mat)), aes(x = V1, y = V2), size=0.6) + # Plots the original points of the feature.
geom_polygon(data=as.data.frame(mbb$pts), aes(x = V1, y = V2), color="black", size=0.8, fill="transparent") + # Plots the MBB as a transparent polygon.
mytheme + # Applies a custom theme for consistent styling.
labs(caption = c(paste("Worst rectangularity fit =", round(wall[n,]$Rectangularity, digits = 2)))) # Adds a caption with the rectangularity index.
# Identifies the index of the feature with the maximum rectangularity (best fit).
n <- which.max(wall$Rectangularity)
# The next few lines repeat the process for the best fit, similar to the worst fit.
mat <- wall[n,][[3]][[1]][[1]]
mbb <- getMinBBox(mat)
# Creates a plot 'b' for the best fit.
b <- ggplot(data = wall[n,]) +
geom_sf() +
geom_point(data=(as.data.frame(mat)), aes(x = V1, y = V2), size=0.6) +
geom_polygon(data=as.data.frame(mbb$pts), aes(x = V1, y = V2), color="black", size=0.8, fill="transparent") +
mytheme +
labs(caption = c(paste("Best rectangularity fit =", round(wall[n,]$Rectangularity, digits = 2))))
# Combines plots 'a' and 'b' side by side.
fig.extremes <- ggarrange(a, b, ncol = 2, align = "hv") +
theme(plot.margin = unit(c(1.5,1.5,1.5,1.5),"cm"))
fig.extremes
```
### Visualizing rectangularity
```{r}
#| fig-width: 9
#| fig.height: 7
# Extract the 'Rectangularity' column from the 'wall' dataset.
x <- wall$Rectangularity
# Determine the minimum and maximum values of rectangularity for setting the scale.
ls_val <- c(min(x), max(x))
# Create a gradient fill scale for coloring the features based on their rectangularity values.
myfill <- scale_fill_gradient(limits = c(min(x),max(x)), low = "gray90", high = "gray20",
na.value = "white", breaks = ls_val,
labels=c(round(min(x), digits=2),
round(max(x), digits=2)))
# Construct the plot
fig.rectangularity <- ggplot(wall, aes(fill = Rectangularity)) + # Base plot with 'Rectangularity' as fill
geom_sf(size = 0.06) + # Draw the features with a border size of 0.06
mytheme + # Apply custom theme settings
myscale + # Apply custom scale settings
myfill + # Apply the gradient fill defined earlier
# Adjust the colorbar guide to match specified aesthetics
guides(fill = guide_colourbar(barwidth = 0.5, barheight = 2, label.position = "left"), ticks = "none") +
theme(legend.position = c(0.935, 0.25)) + # Position the legend
# Annotate specific locations with labels
annotate("text", x = -14, y = 4, size=4.5, label = "Hayehutong") +
annotate("text", x = -14, y = -2, size=4.5, label = "Sichenggong") +
annotate("text", x = -14, y = -8, size=4.5, label = "Xiniwusu") +
annotate("text", x = -14, y = -14, size=4.5, label = "Yonghegong") +
annotate("text", x = -14, y = -20, size=4.5, label = "Bayinnuru")
# Display the plot
fig.rectangularity
```
## Gap Calculation
```{r}
#| label: Variable gap calculation
#| output: false
#| cache: true
# Create a temporary copy of the 'wall' dataset.
tmp <- wall
# Generate a buffer around each feature in 'wall' with a specified distance.
tmp$buffer <- st_buffer(wall, dist = 0.01)
# Determine which buffered features are entirely within the 'wallfilled' dataset.
# 'st_covered_by' checks if the buffer is within 'wallfilled'; 'lengths > 0' ensures there is an overlap.
tmp$covered <- st_covered_by(tmp$buffer, wallfilled) %>% lengths > 0
# Filter 'tmp' to keep only features not at the edge, i.e., those covered by 'wallfilled'.
tmp <- subset(tmp, tmp$covered[{TRUE}])
# Initialize a 'Gap' column in 'tmp' to store calculated gap areas.
tmp["Gap"] <- NA
# Initialize a text progress bar for loop monitoring.
pb <- txtProgressBar(min=1, max=nrow(wallgap), style=3)
# Loop through each feature in 'tmp'.
for(i in 1:nrow(tmp)) {
# Identify gaps touching the current feature using 'st_touches' and extract them.
tmp1 <- st_touches(tmp, wallgap)[[i]]
tmp2 <- st_sf(wallgap$geometry[tmp1])
# Calculate the area of each identified gap.
tmp2$area <- st_area(tmp2)
# Sum the areas of all gaps touching the current feature and store in 'Gap'.
tmp[i,]$Gap <- sum(tmp2$area)
# Update progress bar.
setTxtProgressBar(pb, i)
}
# Close the progress bar after completing the loop.
close(pb)
```
#Join gap area to data frame dataframe
```{r}
# Join the gap area information from 'tmp' back to the original 'wall' dataset.
wall <- left_join(wall,
# Remove the geometry column from 'tmp' to prepare for the join.
st_drop_geometry(tmp) %>%
# Select only the 'ID' and 'Gap' columns from 'tmp' for the join.
dplyr::select(ID, Gap),
# Specify the column ('ID') to use for matching rows between the two datasets.
by = "ID")
```
#Plot gap area
```{r}
#| fig-width: 7
#| fig.height: 3
# Subset the 'wall' dataset to include only rows where 'Gap' is not NA, then extract 'Gap' values.
x <- subset(wall, !is.na(Gap))$Gap
# Determine the minimum and maximum values of 'Gap' for use in the color gradient.
ls_val <- c(min(x), max(x))
# Define a color gradient for the 'Gap' values from light gray to dark gray.
myfill <- scale_fill_gradient(limits = c(min(x),max(x)), low = "gray90", high = "gray20",
na.value = "white", breaks = ls_val,
labels=c(round(min(x), digits=2),
round(max(x), digits=2)))
# Construct the plot.
fig.gap <- ggplot(wall, aes(fill = Gap)) + # Base plot with 'Gap' determining the fill color.
geom_sf(size = 0.06) + # Draw the spatial features with a border size of 0.06.
mytheme + # Apply custom theme settings for consistent styling.
myscale + # Apply custom scale settings for consistent scaling.
myfill + # Apply the defined color gradient to the plot.
# Define the appearance of the colorbar legend.
guides(fill = guide_colourbar(barwidth = 0.5, barheight = 2, label.position = "left"), ticks = "none") +
theme(legend.position = c(0.935, 0.25)) + # Position the legend.
# Annotate specific locations on the map for additional context.
annotate("text", x = -14, y = 4, size=2.5, label = "Hayehutong") +
annotate("text", x = -14, y = -2, size=2.5, label = "Sichenggong") +
annotate("text", x = -14, y = -8, size=2.5, label = "Xiniwusu") +
annotate("text", x = -14, y = -14, size=2.5, label = "Yonghegong") +
annotate("text", x = -14, y = -20, size=2.5, label = "Bayinnuru")
# Display the plot.
fig.gap
```
## General statistics
```{r}
#| label: General statistics
#| output: false
#| cache: true
# Prepare the dataset for total statistics by duplicating 'wall' and setting a uniform site label.
wallstats <- wall
wallstats$Site <- "Total sample" # Assign a common site label for aggregate statistics.
# Group the data by 'Site' after removing geometric data, then calculate various statistics.
wallstats <- group_by(st_drop_geometry(wallstats), Site) %>%
summarise(
count = n(), # Count of features.
"Area_mean" = mean(Area, na.rm = TRUE), # Mean of the Area column, excluding NA values.
"Area_sd" = sd(Area, na.rm = TRUE), # Standard deviation of the Area column, excluding NA values.
"Area_IQR" = IQR(Area, na.rm = TRUE), # Interquartile range of the Area column, excluding NA values.
"Rectangularity_mean" = mean(Rectangularity, na.rm = TRUE), # Mean of Rectangularity, excluding NA values.
"Rectangularity_sd" = sd(Rectangularity, na.rm = TRUE), # Standard deviation of Rectangularity, excluding NA values.
"Rectangularity_IQR" = IQR(Rectangularity, na.rm = TRUE), # Interquartile range of Rectangularity, excluding NA values.
"Gap_mean" = mean(Gap, na.rm = TRUE), # Mean of Gap areas, excluding NA values.
"Gap_sd" = sd(Gap, na.rm = TRUE), # Standard deviation of Gap areas, excluding NA values.
"Gap_IQR" = IQR(Gap, na.rm = TRUE), # Interquartile range of Gap areas, excluding NA values.
"Depth_mean" = mean(Depth, na.rm = TRUE), # Mean of Depth, excluding NA values.
"Depth_sd" = sd(Depth, na.rm = TRUE), # Standard deviation of Depth, excluding NA values.
"Depth_IQR" = IQR(Depth, na.rm = TRUE) # Interquartile range of Depth, excluding NA values.
)
# Calculate statistics for each site separately by grouping the data without geometries.
sitestats <- group_by(st_drop_geometry(wall), Site) %>%
summarise(
# Repeat the same set of statistical calculations for each site.
count = n(),
"Area_mean" = mean(Area, na.rm = TRUE),
"Area_sd" = sd(Area, na.rm = TRUE),
"Area_IQR" = IQR(Area, na.rm = TRUE),
"Rectangularity_mean" = mean(Rectangularity, na.rm = TRUE),
"Rectangularity_sd" = sd(Rectangularity, na.rm = TRUE),
"Rectangularity_IQR" = IQR(Rectangularity, na.rm = TRUE),
"Gap_mean" = mean(Gap, na.rm = TRUE),
"Gap_sd" = sd(Gap, na.rm = TRUE),
"Gap_IQR" = IQR(Gap, na.rm = TRUE),
"Depth_mean" = mean(Depth, na.rm = TRUE),
"Depth_sd" = sd(Depth, na.rm = TRUE),
"Depth_IQR" = IQR(Depth, na.rm = TRUE)
)
# Combine the site-specific statistics and the overall statistics into a single data frame.
statistics <- sitestats
statistics[nrow(statistics) + 1,] = wallstats # Append the total statistics row to the 'statistics' data frame.
```
## Figure of stone blocks variability across the different sites.
```{r}
#| label: fig-variablesDistribution
#| fig-cap: Stone blocks variability across the different sites.
#| fig-width: 14
#| fig.height: 10
# Create a density plot for the 'Area' variable, colored by 'Site'.
a <- ggplot(wall, aes(x=Area, color=Site)) +
geom_density() + # Adds a density plot
scale_color_simpsons() + # Applies a color scale based on 'The Simpsons' (assumes a custom scale or package)
theme_minimal() + # Uses a minimal theme for aesthetics
xlab("Area") + # Label for the x-axis
ylab("Density") # Label for the y-axis
# Create a density plot for the 'Rectangularity' variable, colored by 'Site'.
b <- ggplot(wall, aes(x=Rectangularity, color=Site)) +
geom_density() + # Adds a density plot
scale_color_simpsons() + # Applies the same Simpsons color scale
theme_minimal() + # Uses the same minimal theme
ylab(NULL) # Removes the y-axis label
# Create a density plot for the 'Gap' variable (excluding NA values), colored by 'Site'.
c <- ggplot(data=subset(wall, !is.na(Gap)), aes(x=Gap, color=Site)) +
geom_density() + # Adds a density plot
scale_color_simpsons() + # Applies the same Simpsons color scale
theme_minimal() + # Uses the same minimal theme
ylab(NULL) # Removes the y-axis label
# Arrange the three plots side by side with a common legend at the bottom.
fig.variablesDistribution <- ggarrange(a, b, c, ncol = 3, common.legend = TRUE, legend ="bottom")
# Display the arranged plots.
fig.variablesDistribution
```
## Results of the Shapiro-Wilk normality test
```{r}
#| label: tbl-normalDistribution
#| tbl-cap: Results of the Shapiro-Wilk normality test.
# Perform Shapiro-Wilk normality tests for 'Area' at each site.
a <- shapiro.test(wall$Area[wall$Site == "Hayehutong"])
b <- shapiro.test(wall$Area[wall$Site == "Sichenggong"])
c <- shapiro.test(wall$Area[wall$Site == "Yonghegong"])
d <- shapiro.test(wall$Area[wall$Site == "Xiniwusu"])
e <- shapiro.test(wall$Area[wall$Site == "Bayinnuru"])
# Extract and combine the test statistics (W) into a vector.
tmp1 <- unname(c(a$statistic,b$statistic,c$statistic,d$statistic,e$statistic))
# Extract and combine the p-values into a vector.
tmp2 <- unname(c(a$p.value,b$p.value,c$p.value,d$p.value,e$p.value))
# Create a data frame with the test statistics and p-values.
results <- data.frame(tmp1, tmp2)
colnames(results) <- c("w","p-value") # Rename columns for clarity.
# Set row names to correspond to the sites tested.
rownames(results) <- c("Hayehutong","Sichenggong","Yonghegong","Xiniwusu","Bayinnuru")
# Format the p-values for readability.
results$`p-value` <- format(results$`p-value`, digits = 3)
# Use 'kable' to create a formatted table and 'kable_styling' to apply styling options.
kable(results) %>%
kable_styling(bootstrap_options = c("condensed"),
full_width = T,
position = "left")
```
## Results of the Fligner-Killeen test of homogeneity of variances
```{r}
#| label: tbl-homogeneity
#| tbl-cap: Results of the Fligner-Killeen test of homogeneity of variances.
# Perform Fligner-Killeen test to check homogeneity of variances for 'Area' across 'Site'.
a <- fligner.test(Area ~ Site, data = wall)
# Perform Fligner-Killeen test for 'Rectangularity' across 'Site'.
b <- fligner.test(Rectangularity ~ Site, data = wall)
# Perform Fligner-Killeen test for 'Gap' across 'Site'.
c <- fligner.test(Gap ~ Site, data = wall)
# Combine the median chi-squared test statistics from each test into a vector.
tmp1 <- unname(c(a$statistic, b$statistic, c$statistic))
# Combine the degrees of freedom (df) from each test into a vector.
tmp2 <- unname(c(a$parameter, b$parameter, c$parameter))
# Combine the p-values from each test into a vector.
tmp3 <- unname(c(a$p.value, b$p.value, c$p.value))
# Create a data frame from the combined test statistics, degrees of freedom, and p-values.
results <- data.frame(tmp1, tmp2, tmp3)
# Rename the columns for better readability.
colnames(results) <- c("med chi-squared", "df", "p-value")
# Assign row names corresponding to the variables tested.
rownames(results) <- c("Area", "Rectangularity", "Gap")
# Format the p-values in the results for better readability.
results$`p-value` <- format(results$`p-value`, digits = 3)
# Create a formatted table of the results using 'kable' from 'knitr' and style it with 'kable_styling' from 'kableExtra'.
kable(results) %>%
kable_styling(bootstrap_options = c("condensed"),
full_width = T,
position = "left")
```
## Results of the Kruskal-Wallis test and Dunn pairwise comparison
```{r}
#| label: fig-statistics
#| fig-cap: Results of the Kruskal-Wallis test and Dunn pairwise comparison.
#| fig-width: 16
#| fig.height: 8
# Drop geometry information from 'wall' to work with statistical data only.
dat <- st_drop_geometry(wall)
# Generate a box plot for 'Area' across different 'Site', including statistical analysis.
dat_res <- ggbetweenstats(data = dat, x = Site, y = Area,
plot.type = "box",
type = "nonparametric",
pairwise.comparisons = TRUE, # Perform post-hoc tests if more than 2 groups
pairwise.display = "significant", # Display only significant differences
ggsignif.args = list(textsize = 4, tip_length = 0.01), # Customize significance labels
bf.message = FALSE, # Disable Bayes Factor message
centrality.plotting = FALSE, # Disable plotting of central measure
package = "ggsci", # Use 'ggsci' package for aesthetics
palette = "springfield_simpsons", # Simpsons theme palette
xlab = "") # Remove x-axis label
a <- dat_res +
labs(title = dat_res[["labels"]][["subtitle"]][[2]], # Use generated subtitle as title
subtitle = dat_res[["labels"]][["subtitle"]][[3]]) + # Use generated subtitle
theme_minimal() + # Use minimal theme for plot
theme(plot.title = element_text(size = 10), legend.position = "none") # Customize plot title and remove legend
# For 'Rectangularity'
dat_res <- ggbetweenstats(data = dat, x = Site, y = Rectangularity,
plot.type = "box",
type = "nonparametric",
pairwise.comparisons = TRUE, # Perform post-hoc tests if more than 2 groups
pairwise.display = "significant", # Display only significant differences
ggsignif.args = list(textsize = 4, tip_length = 0.01), # Customize significance labels
bf.message = FALSE, # Disable Bayes Factor message
centrality.plotting = FALSE, # Disable plotting of central measure
package = "ggsci", # Use 'ggsci' package for aesthetics
palette = "springfield_simpsons", # Simpsons theme palette
xlab = "") # Remove x-axis label
b <- dat_res +
labs(title = dat_res[["labels"]][["subtitle"]][[2]], # Use generated subtitle as title
subtitle = dat_res[["labels"]][["subtitle"]][[3]]) + # Use generated subtitle
theme_minimal() + # Use minimal theme for plot
theme(plot.title = element_text(size = 10), legend.position = "none") # Customize plot title and remove legend
# For 'Gap', making sure to handle any NAs in 'Gap' similarly
dat_res <- ggbetweenstats(data = dat, x = Site, y = Gap,
plot.type = "box",
type = "nonparametric",
pairwise.comparisons = TRUE, # Perform post-hoc tests if more than 2 groups
pairwise.display = "significant", # Display only significant differences
ggsignif.args = list(textsize = 4, tip_length = 0.01), # Customize significance labels
bf.message = FALSE, # Disable Bayes Factor message
centrality.plotting = FALSE, # Disable plotting of central measure
package = "ggsci", # Use 'ggsci' package for aesthetics
palette = "springfield_simpsons", # Simpsons theme palette
xlab = "") # Remove x-axis label
c <- dat_res +
labs(title = dat_res[["labels"]][["subtitle"]][[2]], # Use generated subtitle as title
subtitle = dat_res[["labels"]][["subtitle"]][[3]]) + # Use generated subtitle
theme_minimal() + # Use minimal theme for plot
theme(plot.title = element_text(size = 10), legend.position = "none") # Customize plot title and remove legend
```
## Cluster calculation
```{r}
#| label: cluster calculation
#| output: false
# Create a subset of 'wall' with only ID, Area, and Rectangularity columns.
subset_wall <- wall[c("ID", "Area", "Rectangularity")]
# Remove rows with missing values in any of the specified columns.
subset_wall <- na.omit(subset_wall)
# Remove spatial geometry and units from the subset for analysis.
subset_wall <- drop_units(st_drop_geometry(subset_wall))
# Scale 'Area' and 'Rectangularity' to have zero mean and unit variance.
subset_wall <- subset_wall %>%
mutate(Area = scale(Area)) %>%
mutate(Rectangularity = scale(Rectangularity))
# Determine the optimal number of clusters using the silhouette method.
clust <- fviz_nbclust(subset_wall[c('Area', 'Rectangularity')], kmeans, method = "silhouette", linecolor = "gray30")
# Extract the data from the fviz_nbclust result to find the maximum silhouette score.
n_clust <- clust$data
max_cluster <- as.numeric(n_clust$clusters[which.max(n_clust$y)])
# Perform k-means clustering with the optimal number of clusters found.
Cluster <- kmeans(subset_wall[c('Area', 'Rectangularity')], centers = max_cluster, nstart = 25)
# Append the cluster assignments to the subset.
subset_wall <- subset_wall %>%
mutate(Cluster = Cluster$cluster)
# Join the cluster assignments back to the original 'wall' dataset using 'ID' as the key.
wall <- left_join(wall, subset_wall %>%
dplyr::select(ID, Cluster), by = "ID")
# Convert the 'Cluster' column to a factor for potential categorical analysis.
wall$Cluster = as.factor(wall$Cluster)
```
### Optimal number of clusters (a) and scatter plot of the consequent division in clusters (b)
```{r}
#| label: fig-clusterGraph
#| fig-cap: Results of the silhouette method with indicated the optimal number of clusters (a) and scatter plot of the consequent division in clusters (b).
#| fig-width: 14
#| fig.height: 10
# Define custom colors for different clusters using a manual color scale.
myfill <- scale_color_manual(values = c("#D2af81ff", "#b7bbbfff", "#1a9993ff"))
# Assuming 'clust' is a ggplot object created earlier, apply a minimal theme and title.
a <- clust +
theme_minimal() +
ggtitle("a") # Note: Replace "a" with a more descriptive title if necessary.
# Create a scatter plot of 'Area' vs. 'Rectangularity', colored by 'Cluster'.
b <- ggplot(wall, aes(x=Area, y=Rectangularity, color=Cluster)) +
geom_point() + # Plot points
myfill + # Apply the defined custom colors for clusters
theme_minimal() + # Use a minimal theme for a clean look
ggtitle("b") # Note: Replace "b" with a more descriptive title if necessary.
# Arrange the two plots vertically in a single figure.
fig.clusterGraph <- ggarrange(a, b, nrow = 2)
# Display the arranged figure.
fig.clusterGraph
```
```{r}
#| label: cluster statistics
#| output: false
# Prepare the dataset for total statistics by copying 'wall' and assigning a uniform label "Total sample" to all observations.
wallstats <- wall
wallstats$Cluster <- "Total sample"
# Calculate overall statistics after dropping geometry data, grouping by the newly assigned label.
wallstats <- group_by(st_drop_geometry(wallstats), Cluster) %>%
summarise(
count = n(), # Calculate the total number of observations
"Area_mean" = mean(Area, na.rm = TRUE), # Calculate the mean of 'Area', excluding missing values
"rectangularity_mean" = mean(Rectangularity, na.rm = TRUE), # Calculate the mean of 'Rectangularity', excluding missing values
"Depth_mean" = mean(Depth, na.rm = TRUE) # Calculate the mean of 'Depth', excluding missing values
)
# Calculate statistics for each existing cluster within the dataset.
clusterstats <- group_by(st_drop_geometry(wall), Cluster) %>%
summarise(
count = n(), # Count of observations within each cluster
"Area_mean" = mean(Area, na.rm = TRUE), # Mean of 'Area' by cluster, excluding NA
"rectangularity_mean" = mean(Rectangularity, na.rm = TRUE), # Mean of 'Rectangularity' by cluster, excluding NA
"Depth_mean" = mean(Depth, na.rm = TRUE) # Mean of 'Depth' by cluster, excluding NA
)
# Ensure the 'Cluster' column in 'clusterstats' is treated as character for consistent data manipulation.
clusterstats$Cluster <- as.character(clusterstats$Cluster)
# Initialize 'clusterstatistics' with the cluster-specific stats.
clusterstatistics <- clusterstats
# Append the overall statistics to the end of 'clusterstatistics', creating a comprehensive summary.
clusterstatistics[nrow(clusterstatistics) + 1,] = wallstats
```
### Plots of the identified clusters on the wall stretches
```{r}
#| label: fig-clusterPlot
#| fig-cap: Plotting of the identified clusters on the wall stretches.
#| fig-width: 14
#| fig.height: 8
# Define custom fill colors for different clusters.
myfill <- scale_fill_manual(values = c("#D2af81ff", "#b7bbbfff", "#1a9993ff"))
# Create a spatial plot with 'Cluster' determining the fill color.
fig.clusterPlot <- ggplot(wall, aes(fill = Cluster)) +
geom_sf(size = 0.06) + # Add spatial data with specified border size.
mytheme + # Apply a custom theme for styling.
myscale + # Apply custom scaling settings.
myfill + # Apply the defined custom fill colors for clusters.
theme(legend.position = c(0.935, 0.25)) + # Set legend position.
# Add annotations for specific locations on the map for context.
annotate("text", x = -14, y = 4, size=7.5, label = "Hayehutong") +
annotate("text", x = -14, y = -2, size=7.5, label = "Sichenggong") +
annotate("text", x = -14, y = -8, size=7.5, label = "Xiniwusu") +
annotate("text", x = -14, y = -14, size=7.5, label = "Yonghegong") +
annotate("text", x = -14, y = -20, size=7.5, label = "Bayinnuru")
# Display the plot.
fig.clusterPlot
# Save the plot as a PNG file with specified dimensions and resolution.
ggsave("fig.clusterplot.png", path="images", width = 25, height = 15, units = "in", dpi=600)
```
### Scatter plot of depth and area distribution by site type (a) and depth distribution by cluster (b)
```{r}
#| label: fig-depth
#| fig-cap: Scatter plot of depth and area distribution by site type (a) and depth distribution by cluster (b).
#| fig-width: 10
#| fig.height: 4.5
# Remove 'Gap' column from the dataset to avoid analysis on this variable.
wall_noNull <- wall
wall_noNull$Gap <- NULL
# Define custom fill colors for clusters and custom color scales for sites.
myfill <- scale_fill_manual(values = c("#D2af81ff", "#b7bbbfff", "#1a9993ff", "#c6fe39", "#3963fe"))
mycol <- scale_color_manual(values = c("#FED439FF", "#709AE1FF", "#8A9197FF", "#ff9993", "#9993ff"))
# Plot 'a': Scatter plot of Area vs. Depth, colored by 'Site'.
a <- ggplot(na.omit(wall_noNull), aes(x=Area, y=Depth)) +
geom_point(aes(color=Site)) + # Points colored by 'Site'.
geom_smooth(method=lm, color="black") + # Linear regression line across the scatter plot.
theme(legend.position = "none") + # Remove legend for cleaner presentation.
mycol + # Apply custom color scale for sites.
theme_minimal() + # Use a minimal theme for a clean look.
ggtitle("Area vs. Depth by Site") # Title for the plot.
# Plot 'b': Boxplot of Depth by 'Cluster'.
b <- ggplot(na.omit(wall_noNull), aes(x=Cluster, y=Depth, fill=Cluster)) +
geom_boxplot() + # Boxplot showing distribution of 'Depth' by 'Cluster'.
theme(legend.position = "none") + # Remove legend.
myfill + # Apply custom fill colors for clusters.
theme_minimal() + # Use a minimal theme.
ylab(NULL) + # Remove y-axis label for a cleaner look.
ggtitle("Depth Distribution by Cluster") + # Title for the plot.
annotate("text",
x = 1:length(table(na.omit(wall_noNull)$Cluster)), # X positions for annotations.
y = aggregate(Depth ~ Cluster, na.omit(wall_noNull), median)[ , 2], # Y positions for annotations.
label = paste("n=", table(na.omit(wall_noNull)$Cluster)), # Annotation text showing counts per cluster.
vjust = -0.5, cex = 2.5) # Adjust vertical position and size of annotation text.
# Combine the two plots side by side.
fig.depth <- ggarrange(a, b, ncol = 2)
# Display the combined figure.
fig.depth
```
### Volume by cluster
```{r}
#| label: tbl-sideSize
#| tbl-cap: Properties of the average stone block by cluster.
# Calculate volumes using cluster-specific depth means.
wall <- wall %>%
mutate(clustdepth = case_when(
Cluster == 1 ~ clusterstatistics$Depth_mean[1], # Assign mean depth for Cluster 1.
Cluster == 2 ~ clusterstatistics$Depth_mean[2], # Assign mean depth for Cluster 2.
Cluster == 3 ~ clusterstatistics$Depth_mean[3] # Assign mean depth for Cluster 3.
))
wall$volume <- wall$Area * wall$clustdepth # Compute volume as Area * depth.
# Define a function to calculate the cuberoot, considering negative values.
cuberoot = function(x) {
if(x < 0) { - (-x)^(1/3) } # Correct cuberoot for negative numbers.
else { x^(1/3) } # Standard cuberoot for positive numbers.
}
# Calculate overall statistics, treating the dataset as a single "cluster".
wallstats <- wall
wallstats$Cluster <- "Total sample"
wallstats <- group_by(st_drop_geometry(wallstats), Cluster) %>%
summarise(
Count = n(),
"Mean volume (m^3)" = mean(volume, na.rm = TRUE),
"SD volume (m^3)" = sd(volume, na.rm = TRUE),
"IQR volume (m^3)" = IQR(volume, na.rm = TRUE),
"Average stone Side (m)" = cuberoot(mean(volume, na.rm = TRUE)) # Calculate average side length from volume.
)
# Calculate statistics for each cluster separately.
clusterstats <- group_by(st_drop_geometry(wall), Cluster) %>%
summarise(
Count = n(),
"Mean volume (m^3)" = mean(volume, na.rm = TRUE),
"SD volume (m^3)" = sd(volume, na.rm = TRUE),
"IQR volume (m^3)" = IQR(volume, na.rm = TRUE),
"Average stone side (m)" = cuberoot(mean(volume, na.rm = TRUE)) # Calculate average side length from volume.
)
# Combine the statistics for individual clusters with the overall statistics.
clusterstats$Cluster <- as.character(clusterstats$Cluster) # Ensure 'Cluster' is character for consistency.
clusterstatistics_volume <- clusterstats
clusterstatistics_volume[nrow(clusterstatistics_volume) + 1,] = wallstats # Append overall stats to cluster-specific stats.
# Display the combined statistics in a table with custom formatting.
kable(clusterstatistics_volume, digits = 4) %>%
kable_styling(bootstrap_options = c("condensed"),
full_width = T,
position = "left")
```
## Facade volume analysis and composition by wall type
```{r}
#| label: tbl-percentage
#| tbl-cap: Percentage of facade composition divided by blocks below x, between x and y, above y and gap area of walls of Type-A, Type-B and Type-C.
# Calculate the area of wallgap and wallfilled using sf functions and remove the units for simplicity
wallgap$Area_wallgap <- drop_units(st_area(wallgap))
wallfilled$Area_wallfilled <- drop_units(st_area(wallfilled))
# Calculate volumes for different types of wall sections, excluding specific sites for Type A
## Type-A: Exclude 'Hayehutong' and 'Yonghegong' sites
tA_wall <- subset(wall, wall$Site != "Hayehutong" & wall$Site != "Yonghegong")
tA_wallgap <- subset(wallgap, wallgap$Site != "Hayehutong" & wallgap$Site != "Yonghegong")
tA_wallfilled <- subset(wallfilled, wallfilled$Site != "Hayehutong" & wallfilled$Site != "Yonghegong")
# Calculate the percentage of gap area relative to the filled area and total volume for type A
tA_volperc_gap <- sum(tA_wallgap$Area_wallgap) * 100 / (sum(tA_wallfilled$Area_wallfilled))
tA_volgap <- sum(tA_wall$volume) * tA_volperc_gap / 100
tA_voltotal <- sum(tA_wall$volume) + tA_volgap
## Type-B: Specific calculations for 'Hayehutong' site
tB_wall <- subset(wall, wall$Site == "Hayehutong")
tB_wallgap <- subset(wallgap, wallgap$Site == "Hayehutong")
tB_wallfilled <- subset(wallfilled, wallfilled$Site == "Hayehutong")
# Calculate the percentage of gap area and total volume for type B
tB_volperc_gap <- sum(tB_wallgap$Area_wallgap) * 100 / (sum(tB_wallfilled$Area_wallfilled))
tB_volgap <- sum(tB_wall$volume) * tB_volperc_gap / 100
tB_voltotal <- sum(tB_wall$volume) + tB_volgap
## Type-C: Specific calculations for 'Yonghegong' site
tC_wall <- subset(wall, wall$Site == "Yonghegong")
tC_wallgap <- subset(wallgap, wallgap$Site == "Yonghegong")
tC_wallfilled <- subset(wallfilled, wallfilled$Site == "Yonghegong")
# Calculate the percentage of gap area and total volume for type C
tC_volperc_gap <- sum(tC_wallgap$Area_wallgap) * 100 / (sum(tC_wallfilled$Area_wallfilled))
tC_volgap <- sum(tC_wall$volume) * tC_volperc_gap / 100
tC_voltotal <- sum(tC_wall$volume) + tC_volgap
##Calculation by linear m
### type-A
tA_volperc_upto0.02 <- sum(tA_wall$volume[tA_wall$volume<=0.02])*100/tA_voltotal
tA_volperc_0.02to0.05 <- sum(tA_wall$volume[tA_wall$volume>0.02 & tA_wall$volume<=0.05])*100/tA_voltotal
tA_volperc_over0.05 <- sum(tA_wall$volume[tA_wall$volume>0.05])*100/tA_voltotal
### type-B
tB_volperc_upto0.02 <- sum(tB_wall$volume[tB_wall$volume<=0.02])*100/tB_voltotal
tB_volperc_0.02to0.05 <- sum(tB_wall$volume[tB_wall$volume>0.02 & tB_wall$volume<=0.05])*100/tB_voltotal
tB_volperc_over0.05 <- sum(tB_wall$volume[tB_wall$volume>0.05])*100/tB_voltotal
### type-C
tC_volperc_upto0.02 <- sum(tC_wall$volume[tC_wall$volume<=0.02])*100/tC_voltotal
tC_volperc_0.02to0.05 <- sum(tC_wall$volume[tC_wall$volume>0.02 & tC_wall$volume<=0.05])*100/tC_voltotal
tC_volperc_over0.05 <- sum(tC_wall$volume[tC_wall$volume>0.05])*100/tC_voltotal
### fa?ade composition matrix
composition <- matrix(1:12, nrow = 4, ncol = 3)
composition <- rbind(c(tA_volperc_upto0.02,tB_volperc_upto0.02,tC_volperc_upto0.02),
c(tA_volperc_0.02to0.05,tB_volperc_0.02to0.05,tC_volperc_0.02to0.05),
c(tA_volperc_over0.05,tB_volperc_over0.05,tC_volperc_over0.05),
c(tA_volperc_gap,tB_volperc_gap,tC_volperc_gap))
rownames(composition) <- c("upto0.02","0.02to0.05","over0.05", "gap")
colnames(composition) <- c("tA","tB","tC")
### facade composition table
compositiontab <- composition
rownames(compositiontab) <- c("Percentage of blocks up to 0.02m^3","Percentage of blocks between 0.02 and 0.05m^3", "Percentage of blocks over 0.05m^3","Gaps")
colnames(compositiontab) <- c("Type-A","Type-B","Type-C")
kable(compositiontab, digits = 4) %>%
kable_styling(bootstrap_options = c("condensed"),
full_width = T,
position = "left")
```
### Wall volumes by block
```{r}
#| label: tbl-volume
#| tbl-cap: Type-A, Type-B and Type-C wall volumes divided by block composition.
# For Type-A: Calculate average volumes and total facade volume based on block size categories and overall area
tA_avervol_upto0.02 <- tA_voltotal / sum(tA_wallfilled$Area) * composition["upto0.02", "tA"] / 100
tA_avervol_0.02to0.05 <- tA_voltotal / sum(tA_wallfilled$Area) * composition["0.02to0.05", "tA"] / 100
tA_avervol_over0.05 <- tA_voltotal / sum(tA_wallfilled$Area) * composition["over0.05", "tA"] / 100
tA_facadevol <- tA_avervol_upto0.02 + tA_avervol_0.02to0.05 + tA_avervol_over0.05
# For Type-B: Repeat the calculation for blocks and total facade volume
tB_avervol_upto0.02 <- tB_voltotal / sum(tB_wallfilled$Area) * composition["upto0.02", "tB"] / 100
tB_avervol_0.02to0.05 <- tB_voltotal / sum(tB_wallfilled$Area) * composition["0.02to0.05", "tB"] / 100
tB_avervol_over0.05 <- tB_voltotal / sum(tB_wallfilled$Area) * composition["over0.05", "tB"] / 100
tB_facadevol <- tB_avervol_upto0.02 + tB_avervol_0.02to0.05 + tB_avervol_over0.05
# For Type-C: Repeat the calculation for blocks and total facade volume
tC_avervol_upto0.02 <- tC_voltotal / sum(tC_wallfilled$Area) * composition["upto0.02", "tC"] / 100
tC_avervol_0.02to0.05 <- tC_voltotal / sum(tC_wallfilled$Area) * composition["0.02to0.05", "tC"] / 100
tC_avervol_over0.05 <- tC_voltotal / sum(tC_wallfilled$Area) * composition["over0.05", "tC"] / 100
tC_facadevol <- tC_avervol_upto0.02 + tC_avervol_0.02to0.05 + tC_avervol_over0.05
# Create a matrix to store the calculated volumes for each type and category
stonevolume <- rbind(
c(tA_avervol_upto0.02, tB_avervol_upto0.02, tC_avervol_upto0.02),
c(tA_avervol_0.02to0.05, tB_avervol_0.02to0.05, tC_avervol_0.02to0.05),
c(tA_avervol_over0.05, tB_avervol_over0.05, tC_avervol_over0.05),
c(tA_facadevol, tB_facadevol, tC_facadevol)
)
rownames(stonevolume) <- c("upto0.02", "0.01to0.05", "over0.05", "total")
colnames(stonevolume) <- c("tA", "tB", "tC")
# Convert the matrix into a table and format it for presentation
stonevolumetab <- stonevolume
rownames(stonevolumetab) <- c("Volume of blocks up to 0.02 (m^3)", "Volume of blocks between 0.02 and 0.05 (m^3)", "Volume of blocks over 0.05 (m^3)", "Total (m^3)")
colnames(stonevolumetab) <- c("Type-A", "Type-B", "Type-C")
kable(stonevolumetab, digits = 4) %>%
kable_styling(bootstrap_options = c("condensed"), full_width = T, position = "left")