amfora.core.statistics#
Cross-sherd statistical analysis: PCA, clustering, hierarchical dendrograms, group comparisons. Operates on the DataFrame produced by amfora.full_analysis.
Source: src/amfora/core/statistics.py.
Convenience entry points#
- amfora.core.statistics.quick_ceramic_analysis(data: DataFrame | dict, scaling_method: str = 'standard') dict[source]#
One-liner convenience wrapper: prepare data and run
generate_report().- Parameters:
data (pd.DataFrame or dict) – Ceramic analysis data (e.g. output of
full_analysis()).scaling_method (str, default 'standard') – Scaling method passed to
prepare_data()— see that method for options ('standard','robust','none').
- Returns:
Complete analysis report (same as
generate_report()).- Return type:
dict
- amfora.core.statistics.compare_assemblages(data: DataFrame, group_column: str, analysis_type: str = 'comprehensive') dict[source]#
Compare ceramic assemblages between different archaeological contexts.
Note
Not yet implemented — raises
NotImplementedError.- Parameters:
data (pd.DataFrame) – Ceramic data with group identifiers
group_column (str) – Column containing group/context identifiers
analysis_type (str, default 'comprehensive') – Type of analysis:
'basic','comprehensive', or'advanced'
- Returns:
Assemblage comparison results
- Return type:
dict
Classes#
- class amfora.core.statistics.CeramicStatisticalAnalyzer[source]#
Bases:
objectComprehensive statistical analysis class for ceramic fabric data.
This class provides all the statistical methods used in the streamlit application in a standalone, reusable format suitable for batch analysis and research.
Typical workflow:
analyzer = CeramicStatisticalAnalyzer() analyzer.prepare_data(df, scaling_method='standard') pca_results = analyzer.perform_pca(variance_threshold=0.90) cluster_results = analyzer.perform_clustering(method='hierarchical') corr_results = analyzer.correlation_analysis(method='pearson') # Or run everything at once: report = analyzer.generate_report()
Use CeramicVisualization to plot results (biplots, dendrograms, etc.).
- assemblage_comparison(group_column: str, comparison_type: str = 'all') dict[source]#
Compare ceramic assemblages between different groups.
Note
Not yet implemented — raises
NotImplementedError.- Parameters:
group_column (str) – Column name containing group identifiers
comparison_type (str, default 'all') – Type of comparison:
'all','pairwise', or'one_vs_rest'
- Returns:
Comprehensive assemblage comparison results
- Return type:
dict
- correlation_analysis(method: str = 'pearson', significance_level: float = 0.05) dict[source]#
Perform pairwise correlation analysis on ceramic features.
Computes the full correlation matrix, tests each pair for statistical significance, and returns significant pairs sorted by absolute strength.
- Parameters:
method (str, default 'pearson') –
Correlation coefficient to compute:
'pearson'— linear correlation (parametric). Assumes approximately normal distributions.'spearman'— rank correlation (non-parametric). Robust to non-linearity and outliers; recommended when data are ordinal or heavily skewed.'kendall'— Kendall’s tau (non-parametric). More robust than Spearman for small sample sizes but slower to compute.
significance_level (float, default 0.05) – Alpha threshold for identifying significant correlations. Pairs with p < significance_level are included in the
significant_correlationslist.
- Returns:
'correlation_matrix'— DataFrame (features x features).'p_values'— DataFrame of p-values for each pair.'significant_correlations'— list of dicts sorted by|correlation|, each withfeature1,feature2,correlation,p_value, andstrength(Strong/Moderate/Weak/Very weak).'method','significance_level'— echo of inputs.
- Return type:
dict
- generate_report(include_plots: bool = True) dict[source]#
Run PCA, hierarchical clustering, and correlation analysis in one call and bundle results into a single report dict.
Each analysis is run with default parameters (see
perform_pca,perform_clustering,correlation_analysisfor details). If any individual analysis fails, its entry will contain{'error': '<message>'}rather than raising.- Parameters:
include_plots (bool, default True) – Whether to include visualization plots in the report (currently unused — reserved for future HTML export).
- Returns:
'data_summary'— sample/feature counts and names.'pca_analysis'— output ofperform_pca().'cluster_analysis'— output ofperform_clustering().'correlation_analysis'— output ofcorrelation_analysis().'archaeological_interpretation'— auto-generated summary of main findings and technological insights.
- Return type:
dict
- perform_clustering(method: str = 'hierarchical', n_clusters: int | None = None, linkage_method: str = 'ward', distance_metric: str = 'euclidean') dict[source]#
Perform clustering analysis on ceramic data.
Requires
prepare_data()to have been called first. When n_clusters isNone, the optimal count is estimated automatically (elbow method for hierarchical, silhouette scan for k-means).- Parameters:
method (str, default 'hierarchical') –
Clustering algorithm to use:
'hierarchical'— agglomerative hierarchical clustering. Produces a linkage matrix suitable for dendrogram plotting viaCeramicVisualization.plot_dendrogram().'kmeans'— K-means partitioning. Good when the number of groups is known or roughly estimated. Does not produce a dendrogram.'dbscan'— density-based clustering. Does not require n_clusters; discovers clusters of arbitrary shape and labels outliers as noise (cluster label-1). Parameters eps and min_samples are chosen automatically.
n_clusters (int, optional) – Number of clusters for hierarchical and k-means. Ignored by DBSCAN. If
None(default), determined automatically.linkage_method (str, default 'ward') –
Linkage criterion for hierarchical clustering (ignored by k-means/DBSCAN). Passed to
scipy.cluster.hierarchy.linkage():'ward'— minimizes within-cluster variance (requires Euclidean distance). Generally best for balanced clusters.'complete'— maximum inter-cluster distance. Tends to produce compact, equally-sized clusters.'average'— mean inter-cluster distance (UPGMA).'single'— minimum inter-cluster distance. Susceptible to chaining; useful for detecting elongated clusters.'centroid','median','weighted'— less common alternatives (see scipy docs).
distance_metric (str, default 'euclidean') –
Distance metric for hierarchical clustering (ignored by k-means/DBSCAN). Any metric accepted by
scipy.spatial.distance.pdist()is valid, including:'euclidean'— standard L2 distance. Required when linkage_method is'ward'.'mahalanobis'— accounts for feature correlations and unequal variances. The inverse covariance matrix is computed automatically from the data. Well-suited for compositional / provenance studies. Falls back to pseudo-inverse with a warning if the covariance matrix is singular (e.g. when n < number of features). Incompatible with'ward'linkage.'correlation'—1 - Pearson r. Useful when the shape of the feature profile matters more than magnitude.'cosine','cityblock'(Manhattan),'chebyshev', etc.
- Returns:
Clustering results. Keys common to all methods:
'method'— the method string used.'cluster_labels'— integer array of cluster assignments.'n_clusters'— number of clusters found.'silhouette_score'— mean silhouette coefficient (−1 to 1; higher is better).-1if only one cluster.'calinski_harabasz_score'— Calinski-Harabasz index.'cophenetic_correlation'— cophenetic correlation coefficient (0 to 1; higher means the dendrogram faithfully represents pairwise distances). Only set for hierarchical clustering;Nonefor k-means and DBSCAN.'cluster_summary'— per-cluster size and feature means.'sample_names'— list of sample labels (from filenames).
Additional keys by method:
hierarchical:
'linkage_matrix','linkage_method','distance_metric'.kmeans:
'cluster_centers','inertia'.dbscan:
'eps','min_samples','n_noise'.
- Return type:
dict
- perform_pca(n_components: int | None = None, variance_threshold: float = 0.95) dict[source]#
Perform Principal Component Analysis on ceramic data.
Requires
prepare_data()to have been called first. Whenn_componentsis not set, the number of components is chosen automatically as the fewest that cumulatively explain at leastvariance_thresholdof the total variance (minimum 2).- Parameters:
n_components (int, optional) – Exact number of principal components to retain. If
None(default), determined automatically from variance_threshold.variance_threshold (float, default 0.95) – Cumulative explained-variance ratio at which to stop adding components. Only used when n_components is
None. E.g.0.90keeps enough components to explain 90 % of variance — useful for reducing dimensionality while retaining most information.
- Returns:
PCA results with keys:
'scores'— DataFrame of sample scores (PC1, PC2, …) with aSamplecolumn (from filenames).'loadings'— DataFrame of feature loadings per component.'explained_variance'— array of per-component variance ratios.'cumulative_variance'— cumulative sum of the above.'interpretations'— auto-generated archaeological interpretation of each component based on top loadings.'model'— fittedsklearn.decomposition.PCAobject.'n_components'— number of components retained.
- Return type:
dict
- prepare_data(data: DataFrame | dict, exclude_columns: list[str] = None, include_only: list[str] = None, scaling_method: str = 'standard') DataFrame[source]#
Prepare and preprocess ceramic analysis data for statistical analysis.
Must be called before any analysis method (
perform_pca,perform_clustering,correlation_analysis,generate_report).Non-numeric columns and constant columns (zero variance) are automatically removed. If the DataFrame contains a
filenamecolumn, those values are stored as sample labels and used in PCA score tables and dendrogram leaf labels.- Parameters:
data (pd.DataFrame or dict) – Raw ceramic analysis data. If a dict, it is converted to a DataFrame first. Each row is one sherd/sample; columns are numeric measurement features (e.g. from
full_analysis()).exclude_columns (list of str, optional) – Column names to drop before analysis. Useful for removing metadata columns that survived automatic filtering, e.g.
['notes', 'context'].include_only (list of str, optional) – If provided, only these columns are kept (after numeric filtering). Takes precedence —
exclude_columnsis applied first, theninclude_onlyfilters the remainder.scaling_method (str, default 'standard') –
How to scale features before multivariate analysis:
'standard'— zero-mean, unit-variance (scikit-learnStandardScaler). Best general-purpose choice.'robust'— median-centered, IQR-scaled (RobustScaler). Use when data contains outliers.'none'— no scaling. Only appropriate when all features share the same units and comparable ranges.
- Returns:
Preprocessed, scaled data stored internally (also accessible as
self.scaled_data).- Return type:
pd.DataFrame
Notes
Feature selection tips — AMFOrA
full_analysis()can produce ~80+ columns per sherd, many of which are redundant (e.g.blob_mean_diameter_mmandblob_mean_area_mm2measure essentially the same thing). Trimming redundant features improves clustering stability and is required for distance metrics like Mahalanobis (which need more samples than features for a well-conditioned covariance matrix).Strategies for reducing feature count:
Drop one from each highly-correlated pair. Run
correlation_analysis()first and inspectsignificant_correlations— pairs with |r| > 0.9 are near-duplicates. Keep whichever is more interpretable.Pick one detection method. Blob and contour columns (
blob_*vscontour_*) measure the same properties with different algorithms. Useinclude_onlywith one prefix, orexclude_columnsto drop the other.Separate concerns. Color features (
*_color_l/a/b), size features (*_diameter_*,*_area_*), and orientation features (*_orientation_*) capture different aspects of the fabric. For a focused analysis, include only the relevant group.Exclude summary statistics that overlap. Mean and median size, or count and density, often carry the same information. Keep one representative per concept.
- class amfora.core.statistics.CeramicVisualization[source]#
Bases:
objectStatic visualization methods for ceramic statistical analysis results.
All methods are
@staticmethod— no instantiation required:from core.statistics import CeramicVisualization as viz fig = viz.plot_pca_biplot(pca_results) fig = viz.plot_dendrogram(cluster_results) fig = viz.plot_correlation_heatmap(corr_results)
Every method returns a
plotly.graph_objects.Figurethat can be displayed withfig.show()or saved withfig.write_image().- static plot_archaeological_summary(report: dict) Figure[source]#
Create a 2x2 dashboard summarizing PCA variance, cluster quality, top correlations, and sample distribution.
- Parameters:
report (dict) – Output of
CeramicStatisticalAnalyzer.generate_report().- Returns:
Four-panel summary figure.
- Return type:
plotly.graph_objects.Figure
- static plot_cluster_comparison(cluster_results: dict, feature_data: DataFrame, features_to_plot: list[str] = None) Figure[source]#
Create box-plot grid comparing feature distributions across clusters.
- Parameters:
cluster_results (dict) – Output of
CeramicStatisticalAnalyzer.perform_clustering()(any method).feature_data (pd.DataFrame) – The (unscaled) feature data — typically
analyzer.scaled_dataor the original DataFrame subset.features_to_plot (list of str, optional) – Column names to include. If
None, the first 4 columns of feature_data are used.
- Returns:
Grid of box plots, one per feature, colored by cluster.
- Return type:
plotly.graph_objects.Figure
- static plot_correlation_heatmap(correlation_results: dict) Figure[source]#
Create interactive correlation-matrix heatmap.
- Parameters:
correlation_results (dict) – Output of
CeramicStatisticalAnalyzer.correlation_analysis().- Returns:
Heatmap colored by correlation coefficient (−1 to +1).
- Return type:
plotly.graph_objects.Figure
- static plot_dendrogram(cluster_results: dict, orientation: str = 'bottom', max_labels: int = 20, sample_names: list = None) Figure[source]#
Create hierarchical clustering dendrogram.
- Parameters:
cluster_results (dict) – Results from hierarchical clustering
orientation (str, default 'bottom') – Dendrogram orientation
max_labels (int, default 20) – Maximum number of labels to show
sample_names (list, optional) – Labels for leaf nodes. If None, uses cluster_results[‘sample_names’] if available, otherwise falls back to numeric indices.
- Returns:
Interactive dendrogram
- Return type:
plotly.graph_objects.Figure
- static plot_pca_3d(pca_results: dict, pc_x: str = 'PC1', pc_y: str = 'PC2', pc_z: str = 'PC3', cluster_labels: ndarray | None = None) Figure[source]#
Create interactive 3D PCA scatter plot.
- Parameters:
pca_results (dict) – Output of
CeramicStatisticalAnalyzer.perform_pca().pc_x (str, default 'PC1' / 'PC2' / 'PC3') – Principal components mapped to the x / y / z axes.
pc_y (str, default 'PC1' / 'PC2' / 'PC3') – Principal components mapped to the x / y / z axes.
pc_z (str, default 'PC1' / 'PC2' / 'PC3') – Principal components mapped to the x / y / z axes.
cluster_labels (array-like of int, optional) – Cluster assignment per sample (e.g. from
perform_clustering()['cluster_labels']). When provided, points are color-coded by cluster; noise samples (label-1from DBSCAN) appear as “Noise”.
- Returns:
Interactive 3D scatter (rotate/zoom with mouse).
- Return type:
plotly.graph_objects.Figure
- static plot_pca_biplot(pca_results: dict, pc_x: str = 'PC1', pc_y: str = 'PC2', show_loadings: bool = True, max_arrows: int = 10) Figure[source]#
Create PCA biplot with sample scores and feature-loading arrows.
- Parameters:
pca_results (dict) – Output of
CeramicStatisticalAnalyzer.perform_pca().pc_x (str, default 'PC1' / 'PC2') – Which principal components to plot on the x/y axes. Use
'PC3','PC4', etc. to explore higher components.pc_y (str, default 'PC1' / 'PC2') – Which principal components to plot on the x/y axes. Use
'PC3','PC4', etc. to explore higher components.show_loadings (bool, default True) – Overlay feature-loading vectors as arrows. Arrows point in the direction each feature contributes to the two plotted components; longer arrows indicate stronger influence.
max_arrows (int, default 10) – Cap on the number of loading arrows shown (top features by combined loading magnitude). Reduces clutter in high- dimensional datasets.
- Returns:
Interactive PCA biplot.
- Return type:
plotly.graph_objects.Figure
- static plot_scree_plot(pca_results: dict) Figure[source]#
Create scree plot showing per-component explained variance.
Displays both individual (bars) and cumulative (line) variance ratios, helping determine how many components to retain.
- Parameters:
pca_results (dict) – Output of
CeramicStatisticalAnalyzer.perform_pca().- Returns:
Scree / elbow plot.
- Return type:
plotly.graph_objects.Figure