Layer Subaccessor#

In geotech-pandas, a layer reperesents a soil or rock layer of a point. These layers are usually implied as the elements or rows inside a DataFrame.

In this guide, the basics of the layer subaccessor methods are presented. The layer subaccessor is a collection of depth-related calculations for each point in the DataFrame.

First, we import the necessary libraries,

In [1]: import pandas as pd

In [2]: import geotech_pandas

Next, we create a simple DataFrame with point_id and bottom columns present. An additional soil_type column is also added to show how this column is transformed when Splitting layers.

In [3]: df = pd.DataFrame(
   ...:     {
   ...:         "point_id": ["BH-1", "BH-1", "BH-1"],
   ...:         "bottom": [1.0, 2.0, 3.0],
   ...:         "soil_type": ["sand", "clay", "sand"],
   ...:     }
   ...: )
   ...: 

In [4]: df
Out[4]: 
  point_id  bottom soil_type
0     BH-1     1.0      sand
1     BH-1     2.0      clay
2     BH-1     3.0      sand

Getting layer top depth data#

One of the methods under layer is the ability to get the top depths of each layer based on their bottom depths. The get_top() method returns a Series that represents the top depths based on the bottom depths of each layer.

In [5]: df.geotech.layer.get_top()
Out[5]: 
0    0.0
1    1.0
2    2.0
Name: top, dtype: float64

Assign the results of get_top() to a column in the DataFrame to store the results. It is recommended to assign the results in a column with the same name as the Series name returned by the get_top() method.

In [6]: df["top"] = df.geotech.layer.get_top()

In [7]: df
Out[7]: 
  point_id  bottom soil_type  top
0     BH-1     1.0      sand  0.0
1     BH-1     2.0      clay  1.0
2     BH-1     3.0      sand  2.0

To avoid manually setting the column name, we can utilize the concat() method since this method sets the Series name as the column name when concatenating a DataFrame with a Series.

To demonstrate this, we must delete the column we created earlier first,

In [8]: del df["top"]

In [9]: df
Out[9]: 
  point_id  bottom soil_type
0     BH-1     1.0      sand
1     BH-1     2.0      clay
2     BH-1     3.0      sand

Then proceed with the following command to concatenate df with the results of get_top(),

In [10]: df = pd.concat((df, df.geotech.layer.get_top()), axis=1)

In [11]: df
Out[11]: 
  point_id  bottom soil_type  top
0     BH-1     1.0      sand  0.0
1     BH-1     2.0      clay  1.0
2     BH-1     3.0      sand  2.0

As you can see, it results to the same DataFrame as before.

It is recommended to use the concat() method since geotech-pandas relies heavily in consistent column names. For more information, see General Columns.

If you want the output to be much cleaner, you can always override the arrangement of columns like so,

In [12]: df = df[["point_id", "top", "bottom", "soil_type"]]

In [13]: df
Out[13]: 
  point_id  top  bottom soil_type
0     BH-1  0.0     1.0      sand
1     BH-1  1.0     2.0      clay
2     BH-1  2.0     3.0      sand

Getting layer center data#

The get_center() method returns the center depth of each layer based on the average of the top and bottom columns.

In [14]: df.geotech.layer.get_center()
Out[14]: 
0    0.5
1    1.5
2    2.5
Name: center, dtype: float64

Similar to before, we can store the results using concat(),

In [15]: df = pd.concat((df, df.geotech.layer.get_center()), axis=1)

In [16]: df
Out[16]: 
  point_id  top  bottom soil_type  center
0     BH-1  0.0     1.0      sand     0.5
1     BH-1  1.0     2.0      clay     1.5
2     BH-1  2.0     3.0      sand     2.5

Moving soil_type to the end,

In [17]: col = df.pop("soil_type")

In [18]: df.insert(len(df.columns), col.name, col)

In [19]: df
Out[19]: 
  point_id  top  bottom  center soil_type
0     BH-1  0.0     1.0     0.5      sand
1     BH-1  1.0     2.0     1.5      clay
2     BH-1  2.0     3.0     2.5      sand

Getting layer thickness data#

The get_thickness() method returns the thickness of each layer in terms of depth of each layer by getting the absolute difference between the top and bottom columns.

In [20]: df.geotech.layer.get_thickness()
Out[20]: 
0    1.0
1    1.0
2    1.0
Name: thickness, dtype: float64

Similar to before, we can store the results using concat(),

In [21]: df = pd.concat((df, df.geotech.layer.get_thickness()), axis=1)

In [22]: df
Out[22]: 
  point_id  top  bottom  center soil_type  thickness
0     BH-1  0.0     1.0     0.5      sand        1.0
1     BH-1  1.0     2.0     1.5      clay        1.0
2     BH-1  2.0     3.0     2.5      sand        1.0

Since we already stored soil_type in col earlier and no changes occurred to soil_type since then, we can simply delete soil_type from df and re-insert col at the end of df like so,

In [23]: del df[col.name]

In [24]: df.insert(len(df.columns), col.name, col)

In [25]: df
Out[25]: 
  point_id  top  bottom  center  thickness soil_type
0     BH-1  0.0     1.0     0.5        1.0      sand
1     BH-1  1.0     2.0     1.5        1.0      clay
2     BH-1  2.0     3.0     2.5        1.0      sand

Splitting layers#

The split_at() method returns a DataFrame where each layer is split into two if the provided depth is found within its top and bottom depths.

For example, if wish to split BH-1 at 1.5 m, we call split_at() with the depth argument as 1.5 like so,

In [26]: df = df.geotech.layer.split_at(depth=1.5)

In [27]: df
Out[27]: 
  point_id  top  bottom  center  thickness soil_type
0     BH-1  0.0     1.0     0.5        1.0      sand
1     BH-1  1.0     1.5     1.5        1.0      clay
2     BH-1  1.5     2.0     1.5        1.0      clay
3     BH-1  2.0     3.0     2.5        1.0      sand

As you can see, the DataFrame has been split and the top and bottom columns have been updated correctly. However, the other depth-related data remain the same when they should also be different. At the moment, this is the limitation of split_at() as it only updates the top and bottom columns. There are workarounds to this issue though. You can either reassign the other depth-related columns or split the DataFrame first before performing depth-related calculations.

Fortunately, pandas offers the update() method for DataFrame objects. As such, we can update and correct the DataFrame using the following commands,

In [28]: df.update(df.geotech.layer.get_center())

In [29]: df.update(df.geotech.layer.get_thickness())

In [30]: df
Out[30]: 
  point_id  top  bottom  center  thickness soil_type
0     BH-1  0.0     1.0    0.50        1.0      sand
1     BH-1  1.0     1.5    1.25        0.5      clay
2     BH-1  1.5     2.0    1.75        0.5      clay
3     BH-1  2.0     3.0    2.50        1.0      sand

Note

update() transforms the DataFrame inplace.