usda-moisture-analysis/analysis.ipynb

629 lines
26 KiB
Plaintext
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

{
"cells": [
{
"cell_type": "code",
"execution_count": 9,
"metadata": {},
"outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Excel file 'all_data_with_delta.xlsx' created with 570 rows.\n",
" Trial SoakingTime Condition Bag Measurement Sample \\\n",
"0 1 0 Initial Moisture (Trial1) 1 1 1 \n",
"1 1 0 Initial Moisture (Trial1) 1 1 2 \n",
"2 1 0 Initial Moisture (Trial1) 1 2 1 \n",
"3 1 0 Initial Moisture (Trial1) 1 2 2 \n",
"4 1 0 Initial Moisture (Trial1) 1 3 1 \n",
"5 1 0 Initial Moisture (Trial1) 1 3 2 \n",
"6 1 0 Initial Moisture (Trial1) 1 4 1 \n",
"7 1 0 Initial Moisture (Trial1) 1 4 2 \n",
"8 1 0 Initial Moisture (Trial1) 1 5 1 \n",
"9 1 0 Initial Moisture (Trial1) 1 5 2 \n",
"10 1 0 Initial Moisture (Trial1) 2 1 1 \n",
"11 1 0 Initial Moisture (Trial1) 2 1 2 \n",
"12 1 0 Initial Moisture (Trial1) 2 2 1 \n",
"13 1 0 Initial Moisture (Trial1) 2 2 2 \n",
"14 1 0 Initial Moisture (Trial1) 2 3 1 \n",
"15 1 0 Initial Moisture (Trial1) 2 3 2 \n",
"16 1 0 Initial Moisture (Trial1) 2 4 1 \n",
"17 1 0 Initial Moisture (Trial1) 2 4 2 \n",
"18 1 0 Initial Moisture (Trial1) 2 5 1 \n",
"19 1 0 Initial Moisture (Trial1) 2 5 2 \n",
"\n",
" InitialTemp Temp DeltaTemp InitialMC MC% DeltaMC \n",
"0 65.2 65 -0.2 3.28 3.3 0.02 \n",
"1 65.2 66 0.8 3.28 3.3 0.02 \n",
"2 65.2 65 -0.2 3.28 3.1 -0.18 \n",
"3 65.2 65 -0.2 3.28 3.3 0.02 \n",
"4 65.2 65 -0.2 3.28 3.3 0.02 \n",
"5 65.2 64 -1.2 3.28 3.4 0.12 \n",
"6 65.2 66 0.8 3.28 3.3 0.02 \n",
"7 65.2 64 -1.2 3.28 3.5 0.22 \n",
"8 65.2 67 1.8 3.28 3.0 -0.28 \n",
"9 65.2 65 -0.2 3.28 3.3 0.02 \n",
"10 65.7 67 1.3 3.27 3.2 -0.07 \n",
"11 65.7 66 0.3 3.27 3.1 -0.17 \n",
"12 65.7 67 1.3 3.27 3.3 0.03 \n",
"13 65.7 63 -2.7 3.27 3.4 0.13 \n",
"14 65.7 66 0.3 3.27 3.2 -0.07 \n",
"15 65.7 63 -2.7 3.27 3.3 0.03 \n",
"16 65.7 67 1.3 3.27 3.3 0.03 \n",
"17 65.7 66 0.3 3.27 3.3 0.03 \n",
"18 65.7 65 -0.7 3.27 3.4 0.13 \n",
"19 65.7 67 1.3 3.27 3.2 -0.07 \n"
]
}
],
"source": [
"import pandas as pd\n",
"\n",
"# ------------------------------------------------------------------\n",
"# 1. Manually define the data in a nested dictionary.\n",
"# Each key is a condition block.\n",
"# For each block, we have data for each bag (keys 1, 2, 3).\n",
"# Each bags value is a list of 5 measurement rows.\n",
"# In each measurement row, there are 2 sample readings as tuples: (Temp, MC%).\n",
"# ------------------------------------------------------------------\n",
"data = {\n",
" \"Initial Moisture (Trial1)\": {\n",
" 1: [\n",
" [(65, 3.30), (66, 3.30)],\n",
" [(65, 3.10), (65, 3.30)],\n",
" [(65, 3.30), (64, 3.40)],\n",
" [(66, 3.30), (64, 3.50)],\n",
" [(67, 3.00), (65, 3.30)],\n",
" ],\n",
" 2: [\n",
" [(67, 3.20), (66, 3.10)],\n",
" [(67, 3.30), (63, 3.40)],\n",
" [(66, 3.20), (63, 3.30)],\n",
" [(67, 3.30), (66, 3.30)],\n",
" [(65, 3.40), (67, 3.20)],\n",
" ],\n",
" 3: [\n",
" [(71, 3.00), (68, 3.40)],\n",
" [(68, 3.20), (69, 3.20)],\n",
" [(68, 3.30), (70, 3.20)],\n",
" [(69, 3.20), (70, 3.40)],\n",
" [(68, 3.20), (70, 3.20)],\n",
" ],\n",
" },\n",
" \"6 hours\": {\n",
" 1: [\n",
" [(69, 4.30), (68, 4.40)],\n",
" [(69, 4.20), (67, 4.70)],\n",
" [(69, 4.20), (67, 4.50)],\n",
" [(68, 4.30), (68, 4.40)],\n",
" [(68, 4.20), (67, 4.30)],\n",
" ],\n",
" 2: [\n",
" [(71, 4.30), (69, 4.20)],\n",
" [(69, 4.60), (69, 4.30)],\n",
" [(69, 4.30), (69, 4.50)],\n",
" [(68, 4.50), (69, 4.40)],\n",
" [(68, 4.60), (68, 4.40)],\n",
" ],\n",
" 3: [\n",
" [(69, 4.40), (69, 4.60)],\n",
" [(69, 4.50), (69, 4.70)],\n",
" [(70, 4.30), (69, 5.00)],\n",
" [(69, 4.40), (69, 4.50)],\n",
" [(68, 4.50), (69, 4.50)],\n",
" ],\n",
" },\n",
" \"7 hours\": {\n",
" 1: [\n",
" [(69, 4.50), (69, 4.50)],\n",
" [(68, 4.60), (69, 4.60)],\n",
" [(68, 4.50), (69, 4.50)],\n",
" [(68, 4.60), (68, 4.80)],\n",
" [(69, 4.40), (68, 4.60)],\n",
" ],\n",
" 2: [\n",
" [(69, 4.70), (69, 4.90)],\n",
" [(69, 4.70), (69, 5.10)],\n",
" [(68, 4.70), (69, 4.80)],\n",
" [(68, 4.70), (69, 5.00)],\n",
" [(68, 4.80), (68, 4.60)],\n",
" ],\n",
" 3: [\n",
" [(70, 4.50), (70, 4.80)],\n",
" [(69, 4.50), (68, 4.80)],\n",
" [(69, 4.60), (67, 4.90)],\n",
" [(69, 4.50), (69, 4.80)],\n",
" [(69, 4.90), (68, 4.80)],\n",
" ],\n",
" },\n",
" \"8 hours\": {\n",
" 1: [\n",
" [(68, 5.20), (67, 4.80)],\n",
" [(69, 4.90), (67, 4.60)],\n",
" [(69, 5.00), (68, 4.60)],\n",
" [(68, 5.20), (68, 4.70)],\n",
" [(68, 5.00), (68, 4.80)],\n",
" ],\n",
" 2: [\n",
" [(69, 4.90), (68, 4.70)],\n",
" [(68, 5.00), (68, 4.80)],\n",
" [(68, 5.10), (68, 5.10)],\n",
" [(67, 5.00), (68, 4.60)],\n",
" [(68, 5.10), (68, 5.00)],\n",
" ],\n",
" 3: [\n",
" [(70, 5.30), (69, 5.20)],\n",
" [(69, 5.40), (67, 5.20)],\n",
" [(69, 5.00), (69, 4.80)],\n",
" [(69, 4.90), (69, 4.90)],\n",
" [(68, 5.10), (68, 4.90)],\n",
" ],\n",
" },\n",
" \"9 hours\": {\n",
" 1: [\n",
" [(68, 5.30), (68, 5.00)],\n",
" [(68, 5.60), (68, 5.30)],\n",
" [(68, 5.20), (68, 5.10)],\n",
" [(68, 5.30), (68, 4.90)],\n",
" [(68, 5.10), (68, 5.00)],\n",
" ],\n",
" 2: [\n",
" [(71, 5.20), (69, 5.30)],\n",
" [(70, 5.40), (69, 5.10)],\n",
" [(70, 5.30), (69, 5.00)],\n",
" [(70, 5.10), (69, 5.10)],\n",
" [(69, 5.20), (68, 5.00)],\n",
" ],\n",
" 3: [\n",
" [(71, 5.30), (68, 5.30)],\n",
" [(71, 5.40), (69, 5.20)],\n",
" [(70, 5.50), (68, 5.40)],\n",
" [(68, 5.70), (68, 5.20)],\n",
" [(68, 5.40), (68, 5.40)],\n",
" ],\n",
" },\n",
" \"10 hours\": {\n",
" 1: [\n",
" [(68, 5.30), (68, 5.00)],\n",
" [(68, 5.60), (68, 5.30)],\n",
" [(68, 5.20), (68, 5.10)],\n",
" [(68, 5.30), (68, 4.90)],\n",
" [(68, 5.10), (68, 5.00)],\n",
" ],\n",
" 2: [\n",
" [(71, 5.20), (69, 5.30)],\n",
" [(70, 5.40), (69, 5.10)],\n",
" [(70, 5.30), (69, 5.00)],\n",
" [(70, 5.10), (69, 5.10)],\n",
" [(69, 5.20), (68, 5.00)],\n",
" ],\n",
" 3: [\n",
" [(71, 5.30), (68, 5.30)],\n",
" [(71, 5.40), (69, 5.20)],\n",
" [(70, 5.50), (68, 5.40)],\n",
" [(68, 5.70), (68, 5.20)],\n",
" [(68, 5.40), (68, 5.40)],\n",
" ],\n",
" },\n",
" \"Initial Moisture (Trial2)\": {\n",
" 1: [\n",
" [(67, 3.20), (66, 3.50)],\n",
" [(65, 3.30), (63, 3.50)],\n",
" [(67, 3.10), (63, 3.50)],\n",
" [(67, 3.20), (65, 3.50)],\n",
" [(68, 3.30), (64, 3.40)],\n",
" ],\n",
" 2: [\n",
" [(68, 3.20), (68, 3.30)],\n",
" [(69, 3.30), (68, 3.30)],\n",
" [(68, 3.40), (68, 3.30)],\n",
" [(68, 3.30), (68, 3.30)],\n",
" [(67, 3.30), (67, 3.30)],\n",
" ],\n",
" 3: [\n",
" [(67, 3.30), (68, 3.30)],\n",
" [(66, 3.40), (68, 3.30)],\n",
" [(67, 3.40), (69, 3.30)],\n",
" [(67, 3.50), (69, 3.40)],\n",
" [(68, 3.30), (68, 3.00)],\n",
" ],\n",
" },\n",
" \"14 hours\": {\n",
" 1: [\n",
" [(69, 6.80), (68, 6.70)],\n",
" [(67, 7.00), (68, 6.60)],\n",
" [(68, 6.80), (68, 6.70)],\n",
" [(67, 6.70), (68, 6.40)],\n",
" [(67, 6.90), (67, 6.60)],\n",
" ],\n",
" 2: [\n",
" [(68, 6.10), (68, 6.60)],\n",
" [(67, 6.00), (67, 6.70)],\n",
" [(66, 6.40), (67, 6.90)],\n",
" [(67, 6.30), (67, 6.70)],\n",
" [(67, 6.00), (68, 6.40)],\n",
" ],\n",
" 3: [\n",
" [(70, 5.70), (70, 6.50)],\n",
" [(70, 6.00), (69, 6.30)],\n",
" [(70, 5.90), (68, 6.40)],\n",
" [(70, 5.60), (68, 6.70)],\n",
" [(69, 5.80), (68, 6.60)],\n",
" ],\n",
" },\n",
" \"15 hours\": {\n",
" 1: [\n",
" [(68, 7.20), (69, 7.30)],\n",
" [(68, 7.20), (69, 6.80)],\n",
" [(67, 7.10), (68, 7.00)],\n",
" [(68, 7.50), (68, 6.90)],\n",
" [(68, 7.10), (68, 7.20)],\n",
" ],\n",
" 2: [\n",
" [(70, 6.60), (68, 6.60)],\n",
" [(68, 6.70), (67, 6.60)],\n",
" [(67, 6.70), (67, 6.80)],\n",
" [(68, 6.50), (68, 6.70)],\n",
" [(68, 6.80), (68, 6.60)],\n",
" ],\n",
" 3: [\n",
" [(69, 5.90), (69, 6.30)],\n",
" [(67, 6.10), (69, 6.20)],\n",
" [(68, 6.10), (68, 6.40)],\n",
" [(68, 5.90), (69, 6.40)],\n",
" [(68, 6.20), (69, 6.30)],\n",
" ],\n",
" },\n",
" \"16 hours\": {\n",
" 1: [\n",
" [(68, 6.90), (69, 6.90)],\n",
" [(68, 6.70), (69, 6.90)],\n",
" [(68, 7.00), (68, 6.70)],\n",
" [(68, 6.80), (68, 7.00)],\n",
" [(68, 6.80), (67, 7.20)],\n",
" ],\n",
" 2: [\n",
" [(67, 6.60), (68, 7.00)],\n",
" [(67, 6.80), (68, 6.90)],\n",
" [(69, 6.40), (68, 7.30)],\n",
" [(68, 6.60), (68, 7.50)],\n",
" [(68, 6.60), (67, 7.40)],\n",
" ],\n",
" 3: [\n",
" [(67, 6.30), (68, 6.70)],\n",
" [(68, 6.20), (68, 6.80)],\n",
" [(67, 6.30), (68, 6.90)],\n",
" [(68, 6.20), (68, 6.80)],\n",
" [(68, 6.20), (68, 6.70)],\n",
" ],\n",
" },\n",
" \"17 hours\": {\n",
" 1: [\n",
" [(70, 6.90), (68, 7.00)],\n",
" [(68, 7.20), (68, 7.10)],\n",
" [(67, 6.90), (68, 7.00)],\n",
" [(68, 7.30), (68, 7.00)],\n",
" [(67, 6.90), (68, 7.00)],\n",
" ],\n",
" 2: [\n",
" [(70, 7.00), (69, 7.00)],\n",
" [(69, 6.90), (69, 6.90)],\n",
" [(69, 7.10), (68, 7.00)],\n",
" [(69, 7.00), (69, 7.00)],\n",
" [(68, 7.00), (68, 7.00)],\n",
" ],\n",
" 3: [\n",
" [(71, 6.70), (70, 6.50)],\n",
" [(70, 7.00), (68, 6.50)],\n",
" [(68, 7.00), (67, 6.60)],\n",
" [(67, 7.10), (68, 6.60)],\n",
" [(68, 7.00), (67, 6.60)],\n",
" ],\n",
" },\n",
" \"18 hours\": {\n",
" 1: [\n",
" [(69, 7.40), (68, 7.10)],\n",
" [(69, 7.10), (68, 7.10)],\n",
" [(68, 7.20), (68, 7.20)],\n",
" [(67, 7.40), (67, 7.10)],\n",
" [(68, 7.30), (67, 7.20)],\n",
" ],\n",
" 2: [\n",
" [(70, 7.40), (71, 7.20)],\n",
" [(70, 7.10), (70, 7.70)],\n",
" [(70, 7.10), (68, 7.80)],\n",
" [(69, 7.30), (68, 7.50)],\n",
" [(69, 7.20), (68, 7.40)],\n",
" ],\n",
" 3: [\n",
" [(67, 7.00), (68, 7.00)],\n",
" [(67, 6.80), (68, 6.90)],\n",
" [(67, 6.70), (67, 7.10)],\n",
" [(68, 6.60), (67, 6.90)],\n",
" [(68, 6.70), (67, 6.90)],\n",
" ],\n",
" },\n",
" \"Initial Moisture (Trial3)\": {\n",
" 1: [\n",
" [(66, 2.90), (68, 2.90)],\n",
" [(66, 3.00), (68, 2.90)],\n",
" [(64, 3.10), (69, 2.90)],\n",
" [(65, 2.90), (69, 3.00)],\n",
" [(65, 3.00), (69, 2.80)],\n",
" ],\n",
" 2: [\n",
" [(70, 2.90), (70, 2.90)],\n",
" [(70, 3.00), (70, 3.00)],\n",
" [(68, 2.90), (69, 2.90)],\n",
" [(69, 2.90), (70, 3.00)],\n",
" [(68, 3.00), (70, 3.00)],\n",
" ],\n",
" 3: [\n",
" [(69, 2.80), (70, 2.90)],\n",
" [(70, 2.90), (68, 3.00)],\n",
" [(70, 2.90), (70, 3.00)],\n",
" [(67, 3.00), (68, 3.00)],\n",
" [(67, 3.00), (69, 3.00)],\n",
" ],\n",
" },\n",
" \"26 hours\": {\n",
" 1: [\n",
" [(69, 7.80), (68, 8.70)],\n",
" [(68, 8.00), (67, 8.80)],\n",
" [(68, 7.70), (67, 8.40)],\n",
" [(68, 7.80), (67, 8.80)],\n",
" [(68, 7.80), (67, 8.40)],\n",
" ],\n",
" 2: [\n",
" [(77, 7.80), (70, 8.10)],\n",
" [(77, 7.80), (69, 8.00)],\n",
" [(69, 7.70), (69, 8.30)],\n",
" [(68, 7.70), (69, 8.00)],\n",
" [(68, 7.90), (68, 8.00)],\n",
" ],\n",
" 3: [\n",
" [(69, 8.40), (68, 8.30)],\n",
" [(68, 8.10), (68, 8.00)],\n",
" [(68, 8.60), (69, 8.10)],\n",
" [(68, 8.20), (69, 8.10)],\n",
" [(68, 8.40), (69, 8.00)],\n",
" ],\n",
" },\n",
" \"27 hours\": {\n",
" 1: [\n",
" [(69, 8.10), (69, 8.80)],\n",
" [(68, 8.10), (68, 8.30)],\n",
" [(67, 8.60), (68, 8.60)],\n",
" [(68, 8.50), (68, 8.40)],\n",
" [(68, 8.10), (67, 8.70)],\n",
" ],\n",
" 2: [\n",
" [(70, 8.10), (68, 8.30)],\n",
" [(68, 8.00), (68, 8.60)],\n",
" [(69, 8.30), (68, 8.60)],\n",
" [(68, 8.20), (69, 8.50)],\n",
" [(68, 8.60), (68, 8.50)],\n",
" ],\n",
" 3: [\n",
" [(70, 8.20), (69, 8.50)],\n",
" [(70, 8.20), (69, 8.50)],\n",
" [(70, 8.20), (69, 8.60)],\n",
" [(70, 8.20), (69, 8.50)],\n",
" [(70, 8.30), (69, 8.10)],\n",
" ],\n",
" },\n",
" \"28 hours\": {\n",
" 1: [\n",
" [(69, 8.60), (68, 8.80)],\n",
" [(68, 8.50), (68, 9.20)],\n",
" [(68, 8.50), (69, 8.90)],\n",
" [(68, 8.70), (69, 8.90)],\n",
" [(69, 8.30), (69, 8.90)],\n",
" ],\n",
" 2: [\n",
" [(70, 8.00), (68, 9.40)],\n",
" [(69, 8.90), (69, 8.50)],\n",
" [(69, 8.00), (69, 9.30)],\n",
" [(69, 9.20), (68, 8.30)],\n",
" [(68, 8.30), (69, 9.20)],\n",
" ],\n",
" 3: [\n",
" [(68, 8.40), (68, 8.70)],\n",
" [(69, 8.50), (68, 8.80)],\n",
" [(69, 8.00), (68, 8.20)],\n",
" [(69, 8.30), (67, 8.80)],\n",
" [(68, 8.20), (68, 8.70)],\n",
" ],\n",
" },\n",
" \"29 hours\": {\n",
" 1: [\n",
" [(70, 8.40), (69, 8.80)],\n",
" [(68, 8.50), (68, 9.00)],\n",
" [(68, 8.60), (68, 8.50)],\n",
" [(68, 8.30), (68, 8.70)],\n",
" [(69, 8.60), (68, 8.80)],\n",
" ],\n",
" 2: [\n",
" [(70, 8.70), (67, 9.10)],\n",
" [(69, 8.90), (68, 8.70)],\n",
" [(69, 8.10), (68, 8.60)],\n",
" [(70, 8.10), (68, 8.70)],\n",
" [(69, 8.10), (68, 8.60)],\n",
" ],\n",
" 3: [\n",
" [(70, 8.70), (67, 9.00)],\n",
" [(69, 8.90), (68, 8.80)],\n",
" [(68, 8.10), (69, 8.80)],\n",
" [(67, 8.80), (68, 8.80)],\n",
" [(68, 8.10), (69, 8.80)],\n",
" ],\n",
" },\n",
" \"30 hours\": {\n",
" 1: [\n",
" [(68, 9.20), (68, 8.90)],\n",
" [(68, 9.40), (68, 9.30)],\n",
" [(67, 9.30), (68, 8.80)],\n",
" [(68, 9.40), (67, 8.50)],\n",
" [(68, 9.40), (66, 8.90)],\n",
" ],\n",
" 2: [\n",
" [(69, 9.80), (68, 9.60)],\n",
" [(68, 9.40), (67, 9.50)],\n",
" [(68, 9.60), (68, 9.30)],\n",
" [(68, 9.60), (67, 9.40)],\n",
" [(68, 9.30), (68, 9.50)],\n",
" ],\n",
" 3: [\n",
" [(69, 8.50), (68, 8.70)],\n",
" [(69, 8.50), (68, 8.60)],\n",
" [(68, 9.80), (68, 9.60)],\n",
" [(69, 8.50), (68, 8.60)],\n",
" [(67, 8.20), (67, 8.50)],\n",
" ],\n",
" },\n",
" \"31 hours\": {\n",
" 1: [\n",
" [(69, 9.30), (67, 9.30)],\n",
" [(66, 9.50), (66, 9.30)],\n",
" [(67, 9.30), (66, 9.10)],\n",
" [(67, 9.50), (67, 9.30)],\n",
" [(67, 9.50), (67, 9.30)],\n",
" ],\n",
" 2: [\n",
" [(67, 8.50), (68, 9.00)],\n",
" [(67, 8.70), (67, 9.00)],\n",
" [(67, 9.20), (67, 9.20)],\n",
" [(68, 9.10), (68, 8.60)],\n",
" [(67, 8.90), (67, 8.90)],\n",
" ],\n",
" 3: [\n",
" [(68, 8.90), (69, 8.80)],\n",
" [(68, 8.80), (67, 8.90)],\n",
" [(68, 8.60), (67, 8.90)],\n",
" [(68, 8.60), (66, 8.70)],\n",
" [(67, 8.90), (67, 8.70)],\n",
" ],\n",
" },\n",
"}\n",
"\n",
"# ------------------------------------------------------------------\n",
"# 2. Convert the nested dictionary into a list of tidy rows.\n",
"# Here each row will contain:\n",
"# Condition, SoakingTime, Trial, Bag, Measurement, Sample, Temp, MC%\n",
"# ------------------------------------------------------------------\n",
"rows = []\n",
"\n",
"\n",
"def get_trial(condition):\n",
" # Determine trial based on the condition key\n",
" if \"Trial1\" in condition or condition in [\"6 hours\", \"7 hours\", \"8 hours\", \"9 hours\", \"10 hours\"]:\n",
" return 1\n",
" elif \"Trial2\" in condition or condition in [\"14 hours\", \"15 hours\", \"16 hours\", \"17 hours\", \"18 hours\"]:\n",
" return 2\n",
" elif \"Trial3\" in condition or condition in [\"26 hours\", \"27 hours\", \"28 hours\", \"29 hours\", \"30 hours\", \"31 hours\"] or \"Initial Moisture (Trial3)\" in condition:\n",
" return 3\n",
" else:\n",
" return None\n",
"\n",
"\n",
"def get_soaking_time(condition):\n",
" # For initial measurements, use 0; otherwise, extract the first token as the numeric time\n",
" if \"Initial Moisture\" in condition:\n",
" return 0\n",
" try:\n",
" return int(condition.split()[0])\n",
" except:\n",
" return None\n",
"\n",
"\n",
"for condition, bags in data.items():\n",
" trial = get_trial(condition)\n",
" soaking_time = get_soaking_time(condition)\n",
" for bag, meas_list in bags.items():\n",
" for m_idx, meas in enumerate(meas_list, start=1):\n",
" # We assume each measurement row has 2 sample readings (for that bag)\n",
" for s_idx, (temp, mc) in enumerate(meas, start=1):\n",
" rows.append({\"Condition\": condition, \"Trial\": trial, \"SoakingTime\": soaking_time, \"Bag\": bag, \"Measurement\": m_idx, \"Sample\": s_idx, \"Temp\": temp, \"MC%\": mc})\n",
"\n",
"# Create a DataFrame from the collected rows.\n",
"df = pd.DataFrame(rows)\n",
"\n",
"# ------------------------------------------------------------------\n",
"# 3. Compute baseline values (initial measurements) for each trial and bag.\n",
"# For each trial, use the rows where Condition contains \"Initial Moisture\" to get the baseline.\n",
"# ------------------------------------------------------------------\n",
"baseline = {} # structure: { trial: { bag: { \"InitialTemp\": value, \"InitialMC\": value } } }\n",
"\n",
"for trial in df[\"Trial\"].unique():\n",
" trial = int(trial)\n",
" # Filter for initial measurements for this trial.\n",
" init_df = df[df[\"Condition\"].str.contains(\"Initial Moisture\") & (df[\"Trial\"] == trial)]\n",
" # Compute the average baseline for each bag.\n",
" for bag in sorted(init_df[\"Bag\"].unique()):\n",
" bag_df = init_df[init_df[\"Bag\"] == bag]\n",
" baseline.setdefault(trial, {})[bag] = {\"InitialTemp\": bag_df[\"Temp\"].mean(), \"InitialMC\": bag_df[\"MC%\"].mean()}\n",
"\n",
"\n",
"# ------------------------------------------------------------------\n",
"# 4. For each non-initial measurement row, add the baseline values and compute deltas.\n",
"# (For initial rows, delta will be zero.)\n",
"# ------------------------------------------------------------------\n",
"def assign_baseline(row):\n",
" trial = int(row[\"Trial\"])\n",
" bag = row[\"Bag\"]\n",
" base = baseline.get(trial, {}).get(bag, {\"InitialTemp\": None, \"InitialMC\": None})\n",
" return pd.Series({\"InitialTemp\": base[\"InitialTemp\"], \"InitialMC\": base[\"InitialMC\"]})\n",
"\n",
"\n",
"df_baseline = df.apply(assign_baseline, axis=1)\n",
"df = pd.concat([df, df_baseline], axis=1)\n",
"\n",
"# Compute delta columns.\n",
"df[\"DeltaTemp\"] = df[\"Temp\"] - df[\"InitialTemp\"]\n",
"df[\"DeltaMC\"] = df[\"MC%\"] - df[\"InitialMC\"]\n",
"\n",
"# ------------------------------------------------------------------\n",
"# 5. Rearrange columns for clarity.\n",
"# ------------------------------------------------------------------\n",
"df = df[[\"Trial\", \"SoakingTime\", \"Condition\", \"Bag\", \"Measurement\", \"Sample\", \"InitialTemp\", \"Temp\", \"DeltaTemp\", \"InitialMC\", \"MC%\", \"DeltaMC\"]]\n",
"\n",
"# ------------------------------------------------------------------\n",
"# 6. Save the tidy data to an Excel file.\n",
"# ------------------------------------------------------------------\n",
"output_filename = \"all_data_with_delta.xlsx\"\n",
"df.to_excel(output_filename, index=False)\n",
"print(f\"Excel file '{output_filename}' created with {len(df)} rows.\")\n",
"print(df.head(20))"
]
},
{
"cell_type": "code",
"execution_count": null,
"metadata": {},
"outputs": [],
"source": []
}
],
"metadata": {
"kernelspec": {
"display_name": "pecan",
"language": "python",
"name": "python3"
},
"language_info": {
"codemirror_mode": {
"name": "ipython",
"version": 3
},
"file_extension": ".py",
"mimetype": "text/x-python",
"name": "python",
"nbconvert_exporter": "python",
"pygments_lexer": "ipython3",
"version": "3.12.4"
}
},
"nbformat": 4,
"nbformat_minor": 2
}