diff --git a/all_data_with_delta.xlsx b/all_data_with_delta.xlsx new file mode 100644 index 0000000..7010fe8 Binary files /dev/null and b/all_data_with_delta.xlsx differ diff --git a/analysis.ipynb b/analysis.ipynb index 79262ef..2bc4e1a 100644 --- a/analysis.ipynb +++ b/analysis.ipynb @@ -1,5 +1,601 @@ { "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 bag’s 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, @@ -15,7 +611,15 @@ "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" } }, diff --git a/data/large.xlsx b/data/large.xlsx index d957e69..aa9bb96 100644 Binary files a/data/large.xlsx and b/data/large.xlsx differ