Data Cleaning#
The GeoLime Python Library allows advanced geostatistical analysis and modelling of mining data. Basic data processing and cleaning can be performed using open source python libraries to produce suitable datasets for work in GeoLime. This notebook intends to show the user how tabular drillhole data can be cleaned using a variety of libraries before being handled by GeoLime.
Here, the Rocklea Dome dataset from CSIRO is used. The Rocklea Dome dataset has been packaged within the GeoLime library to eliminate the need for the user to download the data.
import pandas as pd
import geolime as geo
Format Pandas display for clarity and readability#
For clarity and readability, Pandas display can be updated to show only 10 rows and display all the columns. By default, Pandas displays DataFrame with 20 columns and 60 rows. For this dataset this would mean hiding some columns and displaying too many rows, hence polluting the notebook.
pd.set_option("display.max_rows", 10)
pd.set_option("display.max_columns", 500)
Import Data#
Rocklea Dome open dataset is included in GeoLime in order to facilitate the startup. Avalaibles dataset can be listed using the command geo.datasets.list_datasets and availables data in the Rocklea Dome datasets can be listed using the command geo.datasets.list_data("rocklea_dome").
hs_assay = geo.datasets.load("rocklea_dome/RC_data_tsgexport.csv")
hs_assay
| Sample | Sample Name | Borehole ID | Depth from | Easting | Northing | Fe % | Al2O3 | SiO2 % | K2O % | CaO % | MgO % | TiO2 % | P % | S % | Mn % | LOI | Fe ox ai | hem/goe | kaolin abundance | kaolin composition | wmAlsmai | wmAlsmci | carbai3pfit | carbci3pfit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 10001-10059_0001_1 | T=1 L=1 P=1 D=0.500000 H=10001-10059 | Rkc278 | 0.0 | 548001.3 | 7474002.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1290 | 891.13 | 0.0374 | 0.999 | NaN | NaN | NaN | NaN |
| 1 | 10001-10059_0001_2 | T=1 L=1 P=2 D=1.500000 H=10001-10059 | Rkc278 | 1.0 | 548001.3 | 7474002.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1460 | 892.68 | 0.0269 | 1.006 | NaN | NaN | NaN | NaN |
| 2 | 10001-10059_0001_3 | T=1 L=1 P=3 D=2.500000 H=10001-10059 | Rkc278 | 2.0 | 548001.3 | 7474002.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1650 | 895.24 | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | 10001-10059_0001_4 | T=1 L=1 P=4 D=3.500000 H=10001-10059 | Rkc278 | 3.0 | 548001.3 | 7474002.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1000 | 893.34 | NaN | NaN | 0.0545 | 2211.83 | NaN | NaN |
| 4 | 10001-10059_0001_5 | T=1 L=1 P=5 D=4.500000 H=10001-10059 | Rkc278 | 4.0 | 548001.3 | 7474002.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.0445 | 910.32 | NaN | NaN | NaN | NaN | 0.111 | 2312.89 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 7515 | 17202-17248_0128_56 | T=128 L=376 P=16 D=55.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7516 | 17202-17248_0128_57 | T=128 L=376 P=17 D=56.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7517 | 17202-17248_0128_58 | T=128 L=376 P=18 D=57.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7518 | 17202-17248_0128_59 | T=128 L=376 P=19 D=58.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7519 | 17202-17248_0128_60 | T=128 L=376 P=20 D=59.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
7520 rows × 25 columns
To ensure values from a same hole follows each other in the table, we sort the values by their Borehole ID, we use the inplace parameter in order to modify the original DataFrame directly.
hs_assay.sort_values(by="Borehole ID", inplace=True)
Otherwise we would need to do something of the like
hs_assay = hs_assay.sort_values(by="Borehole ID")
Check for invalid composites#
Invalid composite are composite that either have :
no hole identifier
no depth from information
We first check if they are rows with no Borehole ID. To do so we access the DataFrame at the rows where the DataFrame does not have a value in the given column.
hs_assay[hs_assay["Borehole ID"].isna()]
| Sample | Sample Name | Borehole ID | Depth from | Easting | Northing | Fe % | Al2O3 | SiO2 % | K2O % | CaO % | MgO % | TiO2 % | P % | S % | Mn % | LOI | Fe ox ai | hem/goe | kaolin abundance | kaolin composition | wmAlsmai | wmAlsmci | carbai3pfit | carbci3pfit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 47 | 10001-10059_0001_48 | T=1 L=3 P=8 D=47.500000 H=10001-10059 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 144 | 10121-10180_0003_25 | T=3 L=8 P=5 D=24.500000 H=10121-10180 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 182 | 10181-10239_0004_3 | T=4 L=10 P=3 D=2.500000 H=10181-10239 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.148 | 908.1 | 0.208 | 1.087 | NaN | NaN | NaN | NaN |
| 190 | 10181-10239_0004_11 | T=4 L=10 P=11 D=10.500000 H=10181-10239 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 246 | 10240-10298_0005_7 | T=5 L=13 P=7 D=6.500000 H=10240-10298 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 7515 | 17202-17248_0128_56 | T=128 L=376 P=16 D=55.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7516 | 17202-17248_0128_57 | T=128 L=376 P=17 D=56.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7517 | 17202-17248_0128_58 | T=128 L=376 P=18 D=57.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7518 | 17202-17248_0128_59 | T=128 L=376 P=19 D=58.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 7519 | 17202-17248_0128_60 | T=128 L=376 P=20 D=59.500000 H=17202-17248 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
378 rows × 25 columns
378 composites do not have any hole identifiant Borehole ID, they cannot be used and are then dropped.
hs_assay.dropna(subset=["Borehole ID"], inplace=True)
We then check if they are rows with no Depth from. To do so we access the DataFrame at the rows where the DataFrame does not have a value in the given column.
hs_assay[hs_assay["Depth from"].isna()]
| Sample | Sample Name | Borehole ID | Depth from | Easting | Northing | Fe % | Al2O3 | SiO2 % | K2O % | CaO % | MgO % | TiO2 % | P % | S % | Mn % | LOI | Fe ox ai | hem/goe | kaolin abundance | kaolin composition | wmAlsmai | wmAlsmci | carbai3pfit | carbci3pfit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 525 | 10480-10539_0009_46 | T=9 L=27 P=6 D=45.500000 H=10480-10539 | Rkc289 | NaN | 548198.7 | 7475193.5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 2837 | 12755-12809_0050_58 | T=50 L=142 P=18 D=57.500000 H=12755-12809 | Rkc359 | NaN | 547795.0 | 7477207.5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.0470 | 918.22 | NaN | NaN | 0.0307 | 2219.17 | NaN | NaN |
| 2838 | 12755-12809_0050_59 | T=50 L=142 P=19 D=58.500000 H=12755-12809 | Rkc359 | NaN | 547795.0 | 7477207.5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.0664 | 920.82 | NaN | NaN | 0.0460 | 2219.26 | NaN | NaN |
| 2840 | 12810-12869_0051_1 | T=51 L=143 P=1 D=0.500000 H=12810-12869 | Rkc359 | NaN | 547795.0 | 7477207.5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1300 | 919.12 | 0.203 | 0.982 | NaN | NaN | NaN | NaN |
| 2839 | 12755-12809_0050_60 | T=50 L=142 P=20 D=59.500000 H=12755-12809 | Rkc359 | NaN | 547795.0 | 7477207.5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1070 | 920.63 | NaN | NaN | 0.0405 | 2218.72 | NaN | NaN |
| 7037 | 16791-16832_0120_58 | T=120 L=352 P=18 D=57.500000 H=16791-16832 | Rkc478 | NaN | 548153.6 | 7475996.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.0795 | 902.29 | 0.217 | 1.091 | NaN | NaN | NaN | NaN |
| 7039 | 16791-16832_0120_60 | T=120 L=352 P=20 D=59.500000 H=16791-16832 | Rkc478 | NaN | 548153.6 | 7475996.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1480 | 891.38 | 0.213 | 1.090 | NaN | NaN | NaN | NaN |
| 7038 | 16791-16832_0120_59 | T=120 L=352 P=19 D=58.500000 H=16791-16832 | Rkc478 | NaN | 548153.6 | 7475996.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1400 | 889.42 | 0.144 | 1.055 | NaN | NaN | NaN | NaN |
8 composites do not have a given Depth From, making them unusable. It seems the Sample Name column contains some depth information, but there is no information about this column, we prefer to discard any sample with doubts.
hs_assay.dropna(subset=["Depth from"], inplace=True)
Check for duplicate composites#
Duplicated composite cannot be kept as this would mean we have two information at the same location. To do so we use the duplicated pandas method, which will return a boolean series where rows are duplicated. By default the method check the values of all columns, here we juste need to check the spatial duplicated using Borehole ID and Depth from.
hs_assay[hs_assay.duplicated(subset=["Borehole ID", "Depth from"],keep=False)]
| Sample | Sample Name | Borehole ID | Depth from | Easting | Northing | Fe % | Al2O3 | SiO2 % | K2O % | CaO % | MgO % | TiO2 % | P % | S % | Mn % | LOI | Fe ox ai | hem/goe | kaolin abundance | kaolin composition | wmAlsmai | wmAlsmci | carbai3pfit | carbci3pfit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 656 | 10600-10659_0011_57 | T=11 L=33 P=17 D=56.500000 H=10600-10659 | Rkc292 | 29.0 | 547895.7 | 7475196.5 | 47.0 | 8.97 | 10.15 | 0.068 | 0.12 | 0.37 | 0.685 | 0.033 | 0.009 | 0.41 | 12.04 | 0.2320 | 917.02 | 0.0378 | 0.991 | NaN | NaN | NaN | NaN |
| 655 | 10600-10659_0011_56 | T=11 L=33 P=16 D=55.500000 H=10600-10659 | Rkc292 | 29.0 | 547895.7 | 7475196.5 | 47.0 | 7.66 | 12.10 | 0.058 | 0.24 | 0.45 | 0.448 | 0.024 | 0.026 | 0.33 | 11.50 | 0.2430 | 908.84 | NaN | NaN | NaN | NaN | NaN | NaN |
| 5076 | 14992-15051_0088_17 | T=88 L=254 P=17 D=16.500000 H=14992-15051 | Rkc427 | 45.0 | 548048.5 | 7475600.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1240 | 911.21 | 0.1090 | 1.032 | NaN | NaN | NaN | NaN |
| 5075 | 14992-15051_0088_16 | T=88 L=254 P=16 D=15.500000 H=14992-15051 | Rkc427 | 45.0 | 548048.5 | 7475600.0 | 22.0 | 20.55 | 34.00 | 0.235 | 0.10 | 0.32 | 1.367 | 0.015 | 0.004 | 0.13 | 11.10 | 0.1960 | 912.05 | 0.1200 | 1.027 | NaN | NaN | NaN | NaN |
| 5273 | 15169-15225_0091_34 | T=91 L=264 P=14 D=33.500000 H=15169-15225 | Rkc431 | 43.0 | 547648.3 | 7475604.5 | 5.0 | 28.44 | 51.15 | 0.025 | 0.16 | 0.40 | 0.660 | 0.006 | 0.001 | NaN | 10.64 | 0.0821 | 920.68 | 0.2910 | 1.117 | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 6897 | 16690-16739_0118_38 | T=118 L=345 P=18 D=37.500000 H=16690-16739 | Rkc475 | 17.0 | 547649.4 | 7475801.5 | 52.0 | 5.48 | 8.18 | 0.019 | 0.12 | 0.36 | 0.148 | 0.031 | 0.016 | 0.07 | 11.70 | 0.2960 | 908.30 | NaN | NaN | 0.0303 | 2206.11 | NaN | NaN |
| 6898 | 16690-16739_0118_39 | T=118 L=345 P=19 D=38.500000 H=16690-16739 | Rkc475 | 17.0 | 547649.4 | 7475801.5 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.2780 | 908.06 | NaN | NaN | 0.0296 | 2205.96 | NaN | NaN |
| 5047 | 14932-14991_0087_48 | T=87 L=253 P=8 D=47.500000 H=14932-14991 | Rkd015 | 0.0 | 547993.0 | 7473995.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 6254 | 16077-16135_0107_55 | T=107 L=313 P=15 D=54.500000 H=16077-16135 | Rkd015 | 0.0 | 547993.0 | 7473995.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 6255 | 16077-16135_0107_56 | T=107 L=313 P=16 D=55.500000 H=16077-16135 | Rkd015 | 0.0 | 547993.0 | 7473995.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
51 rows × 25 columns
51 composites appear to be defined at the same depth, we will remove the column with the most number of NaN values.
Discard based on other criterion
Other rules could be implemented, for example regarding the value in Iron and remove the possible outlier.
We first compute the number of NaN values per row:
hs_assay["number_of_NaNs"] = hs_assay[hs_assay.columns].isna().sum(1)
Then we sort the DataFrame by Borehole ID, Depth from and number of NaN, and first row is kept.
hs_assay.sort_values(by=["Borehole ID", "Depth from", "number_of_NaNs"], ascending=[True, True, False], inplace=True)
hs_assay.drop_duplicates(subset=["Borehole ID", "Depth from"], keep="first", inplace=True)
Remove unneeded columns#
We can delete the first two columns and rename the third one into Hole_ID in order to matchv the other files nomenclature. We will need identical names to be able to make comparisons between the files. We also delete location information as they are given in the collar file. The created column used for filtering duplicates is also removed.
hs_assay = hs_assay.drop(columns=["Sample", "Sample Name", "Easting", "Northing", "number_of_NaNs"])
Spaces and special characters are not recommended as they can be source of error and conflicts depending on the operating systems. The ambiguity of special characters in programmation can also be a source of errors.
User can specify property unit in GeoLime, see it section 2 - Drillholes creation and quick visualization
hs_assay.columns = hs_assay.columns.str.replace(" ", "_")
hs_assay.columns = hs_assay.columns.str.replace("_%", "_pct")
hs_assay.columns = hs_assay.columns.str.replace("/", "_over_")
We rename columns using shorter names
hs_assay.rename(columns={"Borehole_ID": "Hole_ID", "Depth_from": "From"}, inplace=True)
hs_assay
| Hole_ID | From | Fe_pct | Al2O3 | SiO2_pct | K2O_pct | CaO_pct | MgO_pct | TiO2_pct | P_pct | S_pct | Mn_pct | LOI | Fe_ox_ai | hem_over_goe | kaolin_abundance | kaolin_composition | wmAlsmai | wmAlsmci | carbai3pfit | carbci3pfit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | Rkc278 | 0.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1290 | 891.13 | 0.0374 | 0.999 | NaN | NaN | NaN | NaN |
| 1 | Rkc278 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1460 | 892.68 | 0.0269 | 1.006 | NaN | NaN | NaN | NaN |
| 2 | Rkc278 | 2.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1650 | 895.24 | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | Rkc278 | 3.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1000 | 893.34 | NaN | NaN | 0.0545 | 2211.83 | NaN | NaN |
| 4 | Rkc278 | 4.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.0445 | 910.32 | NaN | NaN | NaN | NaN | 0.111 | 2312.89 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 7501 | Rkc485 | 41.0 | 28.0 | 9.80 | 39.05 | 0.037 | 0.08 | 0.22 | 1.078 | 0.027 | 0.006 | 0.12 | 9.00 | 0.2210 | 912.17 | 0.0322 | 1.004 | NaN | NaN | NaN | NaN |
| 7502 | Rkc485 | 42.0 | 39.0 | 7.67 | 25.15 | 0.029 | 0.09 | 0.25 | 0.689 | 0.046 | 0.008 | 0.11 | 10.11 | 0.1200 | 912.43 | 0.1140 | 1.027 | NaN | NaN | NaN | NaN |
| 7503 | Rkc485 | 43.0 | 16.0 | 20.23 | 43.41 | 0.177 | 0.17 | 0.34 | 1.617 | 0.020 | 0.018 | 0.05 | 10.80 | 0.0956 | 888.81 | 0.0306 | 1.012 | NaN | NaN | NaN | NaN |
| 7504 | Rkc485 | 44.0 | 12.0 | 12.53 | 50.24 | 0.060 | 0.26 | 0.25 | 1.473 | 0.006 | 0.779 | 0.03 | 16.18 | 0.0378 | 958.21 | 0.1100 | 1.025 | NaN | NaN | NaN | NaN |
| 5047 | Rkd015 | 0.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
7108 rows × 21 columns
The following modification is very situational, but in our case the Hole_IDs are lowercase, while in the Collar and Survey files this is not the case, and since the names must match between the files, we will apply this function to the Hole_ID column:
hs_assay["Hole_ID"] = hs_assay["Hole_ID"].apply(str.upper)
hs_assay
| Hole_ID | From | Fe_pct | Al2O3 | SiO2_pct | K2O_pct | CaO_pct | MgO_pct | TiO2_pct | P_pct | S_pct | Mn_pct | LOI | Fe_ox_ai | hem_over_goe | kaolin_abundance | kaolin_composition | wmAlsmai | wmAlsmci | carbai3pfit | carbci3pfit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | RKC278 | 0.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1290 | 891.13 | 0.0374 | 0.999 | NaN | NaN | NaN | NaN |
| 1 | RKC278 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1460 | 892.68 | 0.0269 | 1.006 | NaN | NaN | NaN | NaN |
| 2 | RKC278 | 2.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1650 | 895.24 | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | RKC278 | 3.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1000 | 893.34 | NaN | NaN | 0.0545 | 2211.83 | NaN | NaN |
| 4 | RKC278 | 4.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.0445 | 910.32 | NaN | NaN | NaN | NaN | 0.111 | 2312.89 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 7501 | RKC485 | 41.0 | 28.0 | 9.80 | 39.05 | 0.037 | 0.08 | 0.22 | 1.078 | 0.027 | 0.006 | 0.12 | 9.00 | 0.2210 | 912.17 | 0.0322 | 1.004 | NaN | NaN | NaN | NaN |
| 7502 | RKC485 | 42.0 | 39.0 | 7.67 | 25.15 | 0.029 | 0.09 | 0.25 | 0.689 | 0.046 | 0.008 | 0.11 | 10.11 | 0.1200 | 912.43 | 0.1140 | 1.027 | NaN | NaN | NaN | NaN |
| 7503 | RKC485 | 43.0 | 16.0 | 20.23 | 43.41 | 0.177 | 0.17 | 0.34 | 1.617 | 0.020 | 0.018 | 0.05 | 10.80 | 0.0956 | 888.81 | 0.0306 | 1.012 | NaN | NaN | NaN | NaN |
| 7504 | RKC485 | 44.0 | 12.0 | 12.53 | 50.24 | 0.060 | 0.26 | 0.25 | 1.473 | 0.006 | 0.779 | 0.03 | 16.18 | 0.0378 | 958.21 | 0.1100 | 1.025 | NaN | NaN | NaN | NaN |
| 5047 | RKD015 | 0.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
7108 rows × 21 columns
Add To Column#
To complete the file we need to add a new column that indicates the depth where each sample stops, the column To. Here composite all have the same length of 1m.
First we ensure the DataFrame is sorted by Hole_ID and in each Hole_ID values are sorted by the From values.
hs_assay.sort_values(by=["Hole_ID", "From"], inplace=True)
hs_assay
| Hole_ID | From | Fe_pct | Al2O3 | SiO2_pct | K2O_pct | CaO_pct | MgO_pct | TiO2_pct | P_pct | S_pct | Mn_pct | LOI | Fe_ox_ai | hem_over_goe | kaolin_abundance | kaolin_composition | wmAlsmai | wmAlsmci | carbai3pfit | carbci3pfit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | RKC278 | 0.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1290 | 891.13 | 0.0374 | 0.999 | NaN | NaN | NaN | NaN |
| 1 | RKC278 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1460 | 892.68 | 0.0269 | 1.006 | NaN | NaN | NaN | NaN |
| 2 | RKC278 | 2.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1650 | 895.24 | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | RKC278 | 3.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1000 | 893.34 | NaN | NaN | 0.0545 | 2211.83 | NaN | NaN |
| 4 | RKC278 | 4.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.0445 | 910.32 | NaN | NaN | NaN | NaN | 0.111 | 2312.89 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 7501 | RKC485 | 41.0 | 28.0 | 9.80 | 39.05 | 0.037 | 0.08 | 0.22 | 1.078 | 0.027 | 0.006 | 0.12 | 9.00 | 0.2210 | 912.17 | 0.0322 | 1.004 | NaN | NaN | NaN | NaN |
| 7502 | RKC485 | 42.0 | 39.0 | 7.67 | 25.15 | 0.029 | 0.09 | 0.25 | 0.689 | 0.046 | 0.008 | 0.11 | 10.11 | 0.1200 | 912.43 | 0.1140 | 1.027 | NaN | NaN | NaN | NaN |
| 7503 | RKC485 | 43.0 | 16.0 | 20.23 | 43.41 | 0.177 | 0.17 | 0.34 | 1.617 | 0.020 | 0.018 | 0.05 | 10.80 | 0.0956 | 888.81 | 0.0306 | 1.012 | NaN | NaN | NaN | NaN |
| 7504 | RKC485 | 44.0 | 12.0 | 12.53 | 50.24 | 0.060 | 0.26 | 0.25 | 1.473 | 0.006 | 0.779 | 0.03 | 16.18 | 0.0378 | 958.21 | 0.1100 | 1.025 | NaN | NaN | NaN | NaN |
| 5047 | RKD015 | 0.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
7108 rows × 21 columns
We create a new column To consisting of the From values plus one. We use the insert method as we want this column to be in third position (recall in python things beginn at index 0).
hs_assay.insert(2, "To", hs_assay["From"] + 1)
hs_assay
| Hole_ID | From | To | Fe_pct | Al2O3 | SiO2_pct | K2O_pct | CaO_pct | MgO_pct | TiO2_pct | P_pct | S_pct | Mn_pct | LOI | Fe_ox_ai | hem_over_goe | kaolin_abundance | kaolin_composition | wmAlsmai | wmAlsmci | carbai3pfit | carbci3pfit | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | RKC278 | 0.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1290 | 891.13 | 0.0374 | 0.999 | NaN | NaN | NaN | NaN |
| 1 | RKC278 | 1.0 | 2.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1460 | 892.68 | 0.0269 | 1.006 | NaN | NaN | NaN | NaN |
| 2 | RKC278 | 2.0 | 3.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1650 | 895.24 | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | RKC278 | 3.0 | 4.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.1000 | 893.34 | NaN | NaN | 0.0545 | 2211.83 | NaN | NaN |
| 4 | RKC278 | 4.0 | 5.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 0.0445 | 910.32 | NaN | NaN | NaN | NaN | 0.111 | 2312.89 |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 7501 | RKC485 | 41.0 | 42.0 | 28.0 | 9.80 | 39.05 | 0.037 | 0.08 | 0.22 | 1.078 | 0.027 | 0.006 | 0.12 | 9.00 | 0.2210 | 912.17 | 0.0322 | 1.004 | NaN | NaN | NaN | NaN |
| 7502 | RKC485 | 42.0 | 43.0 | 39.0 | 7.67 | 25.15 | 0.029 | 0.09 | 0.25 | 0.689 | 0.046 | 0.008 | 0.11 | 10.11 | 0.1200 | 912.43 | 0.1140 | 1.027 | NaN | NaN | NaN | NaN |
| 7503 | RKC485 | 43.0 | 44.0 | 16.0 | 20.23 | 43.41 | 0.177 | 0.17 | 0.34 | 1.617 | 0.020 | 0.018 | 0.05 | 10.80 | 0.0956 | 888.81 | 0.0306 | 1.012 | NaN | NaN | NaN | NaN |
| 7504 | RKC485 | 44.0 | 45.0 | 12.0 | 12.53 | 50.24 | 0.060 | 0.26 | 0.25 | 1.473 | 0.006 | 0.779 | 0.03 | 16.18 | 0.0378 | 958.21 | 0.1100 | 1.025 | NaN | NaN | NaN | NaN |
| 5047 | RKD015 | 0.0 | 1.0 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
7108 rows × 22 columns
To organize these datas we can group them in ascendant Hole_ID and ascendant From so we will have every borehole in alphabetic order and for every borehole its samples from the most superficial to the deepest.
This last correction is again very situational, but in our case we had to create on the spreadsheet the column “To” on the basis of the column “From”. The problem is that this kind of manipulation sometimes results in a wrong type of value in these boxes, so we will apply a function to put everything in float.
hs_assay["To"] = pd.to_numeric(hs_assay["To"], downcast="float")
hs_assay.to_csv("../data/hyperspec.csv", index=False)