Math Operations XR

Demonstrate splitting and math operations that preserve the mass balance of components.

import xarray as xr
import pandas as pd

from elphick.mass_composition import MassComposition
from elphick.mass_composition.datasets.sample_data import sample_data
# noinspection PyUnresolvedReferences
from elphick.mass_composition.mc_xarray import MassCompositionAccessor

Create a mass-composition (mc) enabled Xarray Dataset

We get some demo data in the form of a pandas DataFrame

df_data: pd.DataFrame = sample_data()
print(df_data.head())
       wet_mass  mass_dry    FE  SIO2  al2o3  LOI  group
index
0         100.0      90.0  57.0   5.2    3.0  5.0  grp_1
1          90.0      80.0  59.0   3.1    1.7  4.0  grp_1
2         110.0      90.0  61.0   2.2    0.9  3.0  grp_2

Construct a Xarray Dataset and standardise the chemistry variables

# noinspection PyProtectedMember
xr_ds: xr.Dataset = MassComposition(df_data)._data
print(xr_ds)
<xarray.Dataset> Size: 192B
Dimensions:   (index: 3)
Coordinates:
  * index     (index) int64 24B 0 1 2
Data variables:
    mass_wet  (index) float64 24B 100.0 90.0 110.0
    mass_dry  (index) float64 24B 90.0 80.0 90.0
    Fe        (index) float64 24B 57.0 59.0 61.0
    SiO2      (index) float64 24B 5.2 3.1 2.2
    Al2O3     (index) float64 24B 3.0 1.7 0.9
    LOI       (index) float64 24B 5.0 4.0 3.0
    group     (index) object 24B 'grp_1' 'grp_1' 'grp_2'
Attributes:
    mc_name:            unnamed
    mc_vars_mass:       ['mass_wet', 'mass_dry']
    mc_vars_chem:       ['Fe', 'SiO2', 'Al2O3', 'LOI']
    mc_vars_attrs:      ['group']
    mc_interval_edges:  {}

Split the original Dataset and return the complement of the split fraction. Splitting does not modify the absolute grade of the input.

xr_ds_split, xr_ds_comp = xr_ds.mc.split(fraction=0.1)
print(xr_ds_split)
<xarray.Dataset> Size: 192B
Dimensions:   (index: 3)
Coordinates:
  * index     (index) int64 24B 0 1 2
Data variables:
    mass_wet  (index) float64 24B 10.0 9.0 11.0
    mass_dry  (index) float64 24B 9.0 8.0 9.0
    Fe        (index) float64 24B 57.0 59.0 61.0
    SiO2      (index) float64 24B 5.2 3.1 2.2
    Al2O3     (index) float64 24B 3.0 1.7 0.9
    LOI       (index) float64 24B 5.0 4.0 3.0
    group     (index) object 24B 'grp_1' 'grp_1' 'grp_2'
Attributes:
    mc_name:            (0.1 * unnamed)
    mc_vars_mass:       ['mass_wet', 'mass_dry']
    mc_vars_chem:       ['Fe', 'SiO2', 'Al2O3', 'LOI']
    mc_vars_attrs:      ['group']
    mc_interval_edges:  {}
print(xr_ds_comp)
<xarray.Dataset> Size: 192B
Dimensions:   (index: 3)
Coordinates:
  * index     (index) int64 24B 0 1 2
Data variables:
    mass_wet  (index) float64 24B 90.0 81.0 99.0
    mass_dry  (index) float64 24B 81.0 72.0 81.0
    Fe        (index) float64 24B 57.0 59.0 61.0
    SiO2      (index) float64 24B 5.2 3.1 2.2
    Al2O3     (index) float64 24B 3.0 1.7 0.9
    LOI       (index) float64 24B 5.0 4.0 3.0
    group     (index) object 24B 'grp_1' 'grp_1' 'grp_2'
Attributes:
    mc_name:            (0.9 * unnamed)
    mc_vars_mass:       ['mass_wet', 'mass_dry']
    mc_vars_chem:       ['Fe', 'SiO2', 'Al2O3', 'LOI']
    mc_vars_attrs:      ['group']
    mc_interval_edges:  {}

Add the split and complement parts using the mc.add method

xr_ds_sum: xr.Dataset = xr_ds_split.mc.add(xr_ds_comp)
print(xr_ds_sum)
<xarray.Dataset> Size: 192B
Dimensions:   (index: 3)
Coordinates:
  * index     (index) int64 24B 0 1 2
Data variables:
    mass_wet  (index) float64 24B 100.0 90.0 110.0
    mass_dry  (index) float64 24B 90.0 80.0 90.0
    Fe        (index) float64 24B 57.0 59.0 61.0
    SiO2      (index) float64 24B 5.2 3.1 2.2
    Al2O3     (index) float64 24B 3.0 1.7 0.9
    LOI       (index) float64 24B 5.0 4.0 3.0
    group     (index) object 24B 'grp_1' 'grp_1' 'grp_2'
Attributes:
    mc_name:            ((0.1 * unnamed) + (0.9 * unnamed))
    mc_vars_mass:       ['mass_wet', 'mass_dry']
    mc_vars_chem:       ['Fe', 'SiO2', 'Al2O3', 'LOI']
    mc_vars_attrs:      ['group']
    mc_interval_edges:  {}

Confirm the sum of the splits is materially equivalent to the starting object.

pd.testing.assert_frame_equal(xr_ds.to_dataframe(), xr_ds_sum.to_dataframe())

Add finally add and then subtract the split portion to the original object, and check the output.

xr_ds_sum: xr.Dataset = xr_ds.mc.add(xr_ds_split)
xr_ds_minus: xr.Dataset = xr_ds_sum.mc.sub(xr_ds_split)
pd.testing.assert_frame_equal(xr_ds_minus.to_dataframe(), xr_ds.to_dataframe())
print(xr_ds_minus)
<xarray.Dataset> Size: 192B
Dimensions:   (index: 3)
Coordinates:
  * index     (index) int64 24B 0 1 2
Data variables:
    mass_wet  (index) float64 24B 100.0 90.0 110.0
    mass_dry  (index) float64 24B 90.0 80.0 90.0
    Fe        (index) float64 24B 57.0 59.0 61.0
    SiO2      (index) float64 24B 5.2 3.1 2.2
    Al2O3     (index) float64 24B 3.0 1.7 0.9
    LOI       (index) float64 24B 5.0 4.0 3.0
    group     (index) object 24B 'grp_1' 'grp_1' 'grp_2'
Attributes:
    mc_name:            ((unnamed + (0.1 * unnamed)) - (0.1 * unnamed))
    mc_vars_mass:       ['mass_wet', 'mass_dry']
    mc_vars_chem:       ['Fe', 'SiO2', 'Al2O3', 'LOI']
    mc_vars_attrs:      ['group']
    mc_interval_edges:  {}

Demonstrate division

xr_ds_div = xr_ds_split.mc.div(xr_ds)
print(xr_ds_div)
<xarray.Dataset> Size: 192B
Dimensions:   (index: 3)
Coordinates:
  * index     (index) int64 24B 0 1 2
Data variables:
    mass_wet  (index) float64 24B 0.1 0.1 0.1
    mass_dry  (index) float64 24B 0.1 0.1 0.1
    Fe        (index) float64 24B 0.1 0.1 0.1
    SiO2      (index) float64 24B 0.1 0.1 0.1
    Al2O3     (index) float64 24B 0.1 0.1 0.1
    LOI       (index) float64 24B 0.1 0.1 0.1
    group     (index) object 24B 'grp_1' 'grp_1' 'grp_2'
Attributes:
    mc_name:            ((0.1 * unnamed) / unnamed)
    mc_vars_mass:       ['mass_wet', 'mass_dry']
    mc_vars_chem:       ['Fe', 'SiO2', 'Al2O3', 'LOI']
    mc_vars_attrs:      ['group']
    mc_interval_edges:  {}

Total running time of the script: ( 0 minutes 0.104 seconds)

Gallery generated by Sphinx-Gallery