Data Loading
Xpectrass includes built-in FTIR plastic datasets and utilities for loading your own data.
Bundled Datasets
The library comes with 6 pre-loaded FTIR plastic datasets from published studies, perfect for testing, tutorials, and reproducible research.
Available Datasets
from xpectrass.data import get_data_info
# View all available datasets
info = get_data_info()
print(info)
Dataset |
Study |
Samples |
Polymer Types |
Year |
|---|---|---|---|---|
|
Jung et al. |
~500 |
PE, PP, PS, PET, PVC, etc. |
2018 |
|
Kedzierski et al. |
~300 |
Various plastics |
2019 |
|
Kedzierski et al. (unprocessed) |
~300 |
Various plastics |
2019 |
|
Frond et al. |
~400 |
Common polymers |
2021 |
|
Villegas-Camacho et al. (C4) |
~600 |
Microplastics |
2024 |
|
Villegas-Camacho et al. (C8) |
~600 |
Microplastics |
2024 |
Loading Individual Datasets
from xpectrass.data import (
load_jung_2018,
load_kedzierski_2019,
load_frond_2021,
load_villegas_camacho_2024_c4
)
# Load Jung 2018 dataset
df = load_jung_2018()
print(f"Loaded {len(df)} spectra")
print(f"Columns: {df.columns[:10]}...")
print(f"Unique types: {df['type'].unique()}")
# Load Villegas-Camacho 2024 (C4 fraction)
df_c4 = load_villegas_camacho_2024_c4()
print(f"C4 fraction: {len(df_c4)} spectra")
Loading All Datasets
from xpectrass.data import load_all_datasets
# Load all datasets as a dictionary
all_data = load_all_datasets()
for name, df in all_data.items():
print(f"{name}: {len(df)} spectra, {len(df.columns)-1} wavenumbers")
Loading Specific Datasets
from xpectrass.data import load_datasets
# Load only specific datasets
selected_data = load_datasets([
'jung_2018',
'frond_2021',
'villegas_camacho_2024_c4'
])
print(f"Loaded {len(selected_data)} datasets")
Dataset Information
Each dataset includes:
type column: Polymer type (HDPE, LDPE, PP, PS, PET, PVC, etc.)
Wavenumber columns: Typically 400-4000 cm⁻¹ range
Index: Sample identifiers
df = load_jung_2018()
# Inspect dataset
print(f"Shape: {df.shape}")
print(f"Label column: 'type'")
spectral_cols = [c for c in df.columns if c not in ["study", "sample_id", "type", "environmental", "resolution"]]
wn = sorted(float(c) for c in spectral_cols)
print(f"Wavenumber range: {wn[0]} to {wn[-1]}")
print(f"Polymer types: {df['type'].value_counts()}")
Loading Your Own Data
From Single CSV File
import pandas as pd
from xpectrass import FTIRdataprocessing
# Load single file
df = pd.read_csv("my_ftir_data.csv", index_col=0)
# Start processing
ftir = FTIRdataprocessing(df, label_column="polymer_type")
Expected CSV format:
,type,400.0,401.0,402.0,...,4000.0
Sample_1,HDPE,0.123,0.125,0.128,...,0.045
Sample_2,PP,0.098,0.102,0.105,...,0.038
Sample_3,PE,0.115,0.118,0.121,...,0.041
From Multiple CSV Files (Batch Loading)
from xpectrass.utils import process_batch_files
import glob
# Load all CSV files in a directory
files = glob.glob('data/plastics/*.csv')
df = process_batch_files(files)
print(f"Loaded {len(df)} spectra from {len(files)} files")
process_batch_files() parameters:
df = process_batch_files(
file_list, # List of file paths
skiprows=0, # Skip header rows (e.g., skiprows=15 for Opus files)
label_from='filename', # 'filename' or 'column'
label_column=None, # Column name if label_from='column'
sep=',', # CSV separator
decimal='.', # Decimal separator
)
From Directory Structure
If your files are organized by polymer type:
data/
HDPE/
sample_001.csv
sample_002.csv
PP/
sample_001.csv
sample_002.csv
PET/
sample_001.csv
import os
import glob
import pandas as pd
def load_from_directory_structure(base_path):
"""Load FTIR files organized by type in subdirectories."""
data_list = []
# Iterate through subdirectories
for polymer_type in os.listdir(base_path):
type_path = os.path.join(base_path, polymer_type)
if os.path.isdir(type_path):
# Load all CSV files in this subdirectory
files = glob.glob(os.path.join(type_path, '*.csv'))
for file in files:
df_temp = pd.read_csv(file, index_col=0)
df_temp['type'] = polymer_type
data_list.append(df_temp)
# Combine all data
df = pd.concat(data_list, ignore_index=True)
return df
# Load data
df = load_from_directory_structure('data')
print(f"Loaded {len(df)} spectra")
From Excel Files
import pandas as pd
# Load from Excel
df = pd.read_excel("ftir_data.xlsx", sheet_name="Spectra", index_col=0)
# Process as usual
from xpectrass import FTIRdataprocessing
ftir = FTIRdataprocessing(df, label_column="type")
Data Format Requirements
Required Format
DataFrame structure: Samples as rows, wavenumbers as columns
Label column: One column containing sample labels/types
Wavenumber columns: Numeric column names (400.0, 401.0, …) or convertible to float
Index: Sample identifiers (optional but recommended)
Valid Wavenumber Column Formats
The library automatically handles various column name formats:
# All of these work:
# Format 1: Pure numeric
"400.0", "401.0", "402.0"
# Format 2: With units
"400.0cm", "401.0cm", "402.0cm"
# Format 3: Scientific notation
"4.00e2", "4.01e2", "4.02e2"
# Format 4: String numbers (will be converted)
"400", "401", "402"
The library uses robust wavenumber detection to handle edge cases automatically.
Data Validation
Always validate your data after loading:
import polars as pl
from xpectrass.data import load_jung_2018
from xpectrass.utils import validate_spectra
# validate_spectra expects a Polars dataframe with 'sample' and 'label' columns
df = load_jung_2018()
df_val = pl.from_pandas(
df.rename(columns={"sample_id": "sample", "type": "label"})
)
report = validate_spectra(df_val, verbose=True)
if report['valid']:
print("✓ Data is valid!")
else:
print("✗ Data validation failed:")
for issue in report['issues']:
print(f" - {issue}")
Validation Checks
The validation function checks for:
Missing values (NaN, inf)
Negative intensity values (for absorbance)
Out-of-range values
Sufficient samples per class
Wavenumber continuity
Data type consistency
Combining Datasets
Combine Bundled Datasets
from xpectrass.data import load_jung_2018, load_frond_2021
import pandas as pd
# Load individual datasets
df1 = load_jung_2018()
df2 = load_frond_2021()
# Simple concatenation (if wavenumber ranges match)
df_combined = pd.concat([df1, df2], ignore_index=True)
print(f"Combined: {len(df_combined)} spectra")
Combine with Interpolation
If datasets have different wavenumber ranges, use combine_datasets:
from xpectrass.utils import combine_datasets, convert_spectra
# Convert to absorbance before combining
df1_abs = convert_spectra(
df1,
mode="to_absorbance",
label_column="type",
exclude_columns=["study", "sample_id", "environmental", "resolution"],
)
df2_abs = convert_spectra(
df2,
mode="to_absorbance",
label_column="type",
exclude_columns=["study", "sample_id", "environmental", "resolution"],
)
df_combined, common_grid = combine_datasets(
datasets=[df1_abs, df2_abs],
wn_min=680,
wn_max=3000,
resolution=2.0,
method="pchip",
label_column="type",
exclude_columns=["study", "sample_id", "environmental", "resolution"],
add_study_column=False,
)
Data Preprocessing Before Analysis
After loading, typical workflow:
from xpectrass import FTIRdataprocessing
from xpectrass.data import load_jung_2018
# 1. Load data
df = load_jung_2018()
# 2. Initialize preprocessing
ftir = FTIRdataprocessing(
df,
label_column="type",
wn_min=400,
wn_max=4000
)
# 3. Apply preprocessing pipeline
df_norm, *_ = ftir.run(plot=False)
# 4. Get processed data
processed_df = df_norm
Exporting Processed Data
Save your processed data for later use:
# Save to CSV
processed_df.to_csv("processed_ftir_data.csv")
# Save to Excel
processed_df.to_excel("processed_ftir_data.xlsx", sheet_name="Processed")
# Save to Parquet (efficient for large datasets)
processed_df.to_parquet("processed_ftir_data.parquet")
# Load processed data later
import pandas as pd
df = pd.read_csv("processed_ftir_data.csv", index_col=0)
Tips and Best Practices
Use bundled datasets for testing: Perfect for learning and validating workflows
Validate after loading: Always run
validate_spectra()on your dataCheck wavenumber ranges: Ensure your data covers the spectral region of interest
Inspect class distribution: Check for class imbalance before machine learning
Save intermediate results: Save preprocessed data to avoid reprocessing
Document data sources: Keep track of where your data came from
Example: Complete Data Loading Workflow
from xpectrass import FTIRdataprocessing, FTIRdataanalysis
from xpectrass.data import load_jung_2018, get_data_info
from xpectrass.utils import validate_spectra
import polars as pl
# 1. Explore available datasets
print("Available datasets:")
print(get_data_info())
# 2. Load a dataset
df = load_jung_2018()
print(f"\nLoaded Jung 2018 dataset:")
print(f" - Samples: {len(df)}")
print(f" - Wavenumbers: {len(df.columns)-1}")
print(f" - Polymer types: {df['type'].nunique()}")
# 3. Check class distribution
print(f"\nClass distribution:")
print(df['type'].value_counts())
# 4. Validate data
df_val = pl.from_pandas(df.rename(columns={"sample_id": "sample", "type": "label"}))
report = validate_spectra(df_val, verbose=False)
print(f"\nValidation: {'✓ Passed' if report['valid'] else '✗ Failed'}")
# 5. Preprocess
print("\nPreprocessing...")
ftir = FTIRdataprocessing(df, label_column="type")
ftir.run() # Quick run with defaults
# 6. Analyze
print("\nAnalyzing...")
analysis = FTIRdataanalysis(ftir.df_norm, label_column="type")
analysis.plot_pca()
# 7. Save processed data
ftir.df_norm.to_csv("jung_2018_processed.csv")
print("\n✓ Processing complete! Saved to jung_2018_processed.csv")
Common Data Loading Patterns
Pattern 1: Load and Preprocess Bundled Data
from xpectrass import FTIRdataprocessing
from xpectrass.data import load_jung_2018
df = load_jung_2018()
ftir = FTIRdataprocessing(df, label_column="type")
ftir.run()
Pattern 2: Load Multiple Files from Directory
from xpectrass.utils import process_batch_files
import glob
files = glob.glob('data/**/*.csv', recursive=True)
df = process_batch_files(files)
Pattern 3: Load and Combine Multiple Datasets
from xpectrass.data import load_datasets
import pandas as pd
datasets = load_datasets(['jung_2018', 'frond_2021'])
df = pd.concat(datasets.values(), ignore_index=True)
Next Steps
See Preprocessing Pipeline for data processing
See Data Validation for quality checks
See Analysis for visualization and statistics
See Machine Learning for classification workflows