Lab Example#

Pymeasurement’s Measurement type can be used to perform precision-based calculations with uncertainty propagation in standard Python data structures such as Pandas DataFrames. This example shows how to use the Measurement type to evaluate the data from a calorimetry experiment.

Problem#

Calculate the relationship between the molar enthalpy of combustion and the carbon chain length of primary alcohol fuels.

Data Table throughout Calorimetry Lab

Alcohol tested

# of carbons

Trial

Mass of water (+/- 0.001 g)

Initial mass of spirit burner (+/- 0.001 g)

Final mass of spirit burner (+/- 0.001 g)

Ethanol

2

1

78.701

110.759

109.689

Ethanol

2

2

78.866

102.941

101.53

Ethanol

2

3

72.259

99.972

98.642

Ethanol

2

4

76.301

98.581

97.084

Ethanol

2

5

75.239

115.399

113.309

Ethanol

2

6

70.421

106.816

104.597

Propan-1-ol

3

1

71.624

107.374

106.277

Propan-1-ol

3

2

64.813

111.018

109.724

Propan-1-ol

3

3

68.053

114.814

113.206

Propan-1-ol

3

4

69.118

106.248

104.547

Propan-1-ol

3

5

68.542

83.423

80.625

Propan-1-ol

3

6

68.721

89.714

86.186

Butan-1-ol

4

1

67.828

110.054

108.84

Butan-1-ol

4

2

67.57

105.246

104.014

Butan-1-ol

4

3

74.844

116.084

114.649

Butan-1-ol

4

4

61.214

103.961

102.606

Butan-1-ol

4

5

70.545

112.693

111.043

Pentan-1-ol

5

1

70.119

113.027

112.175

Pentan-1-ol

5

2

141.762

110.779

109.117

Pentan-1-ol

5

3

64.175

113.924

113.019

Pentan-1-ol

5

4

62.989

112.782

111.609

Pentan-1-ol

5

5

70.469

112.166

110.767

Pentan-1-ol

5

6

70.168

103.432

102.25

Solution#

The data from the lab is imported into a Pandas DataFrame.

>>> import pandas as pd
>>> df = pd.read_excel('Combustion_Lab_1920_Student_Data.xlsx')

The DataFrame columns are converted into pymeasurement Measurements.

>>> from pymeasurement import Measurement as M
>>> decimals = [3, 3, 3, 1, 1]
>>> units = ['g', 'g', 'g', 'ºC', 'ºC']
>>> for i in range(5):
...     df.iloc[:, i + 3] = M.importColumn(df.iloc[:, i + 3], d=True, un=units[i], decimals=decimals[i])

Now using the below formulas, the enthalpy of combustion can be calculated for each trial.

\[Q = m c \Delta T = m c (T_f - T_i)\]
\[n = m / M\]
\[\Delta H = -\frac{Q}{n}\]
>>> heat_capacity = M.fromStr('4.18c J/g*ºC')
>>> j_to_kj = M.fromStr('0.001c kJ/J')
>>> results_df_1 = df.iloc[:, 0:3]
>>> results_df_1['Q of H2O (kJ)'] = df['Mass of water (+/- 0.001 g)'] * heat_capacity * (df['Final temperature (+/- 0.1 ºC)'] - df['Initial temperature (+/- 0.1 ºC)']) * j_to_kj
>>> results_df_1['Mass of Alcohol (g)'] = df['Initial mass of spirit burner (+/- 0.001 g)'] - df['Final mass of spirit burner (+/- 0.001 g)']
>>> molar_masses = {'Ethanol': M.fromStr('46.08c g/mol'), 'Propan-1-ol': M.fromStr('60.11c g/mol'), 'Butan-1-ol': M.fromStr('74.14c g/mol'), 'Pentan-1-ol': M.fromStr('88.17c g/mol')}
>>> results_df_1['Molar Mass of Alcohol (g/mol)'] = results_df_1.apply(lambda x: x['Mass of Alcohol (g)'] / molar_masses[x['Alcohol tested']], axis=1)
>>> results_df_1['Molar Enthalpy of Combustion (kJ/mol)'] = - results_df_1['Q of H2O (kJ)'] / results_df_1['Molar Mass of Alcohol (g/mol)']

Results Table 1: Individual Molar Enthalpy of Combustion

Alcohol tested

# of carbons

Trial

Q of H2O (kJ)

Mass of Alcohol (g)

Molar Mass of Alcohol (g/mol)

Molar Enthalpy of Combustion (kJ/mol)

Ethanol

2

1

16.2 +/- 0.41% kJ

1.070 +/- 0.002 g

0.02322 +/- 0.19% mol

-697 +/- 0.59% kJ/mol

Ethanol

2

2

17.3 +/- 0.38% kJ

1.411 +/- 0.002 g

0.03062 +/- 0.14% mol

-565 +/- 0.52% kJ/mol

Ethanol

2

3

16.2 +/- 0.37% kJ

1.330 +/- 0.002 g

0.02886 +/- 0.15% mol

-562 +/- 0.52% kJ/mol

Ethanol

2

4

15.7 +/- 0.41% kJ

1.497 +/- 0.002 g

0.03249 +/- 0.13% mol

-483 +/- 0.54% kJ/mol

Ethanol

2

5

16.2 +/- 0.39% kJ

2.090 +/- 0.002 g

0.04536 +/- 0.096% mol

-358 +/- 0.48% kJ/mol

Ethanol

2

6

15.5 +/- 0.38% kJ

2.219 +/- 0.002 g

0.04816 +/- 0.090% mol

-323 +/- 0.47% kJ/mol

Propan-1-ol

3

1

14.8 +/- 0.41% kJ

1.097 +/- 0.002 g

0.01825 +/- 0.18% mol

-809 +/- 0.59% kJ/mol

Propan-1-ol

3

2

13.4 +/- 0.40% kJ

1.294 +/- 0.002 g

0.02153 +/- 0.15% mol

-624 +/- 0.56% kJ/mol

Propan-1-ol

3

3

14.3 +/- 0.40% kJ

1.608 +/- 0.002 g

0.02675 +/- 0.12% mol

-536 +/- 0.52% kJ/mol

Propan-1-ol

3

4

14.2 +/- 0.41% kJ

1.701 +/- 0.002 g

0.02830 +/- 0.12% mol

-500 +/- 0.53% kJ/mol

Propan-1-ol

3

5

14.3 +/- 0.40% kJ

2.798 +/- 0.002 g

0.04655 +/- 0.071% mol

-307 +/- 0.47% kJ/mol

Propan-1-ol

3

6

15.9 +/- 0.36% kJ

3.528 +/- 0.002 g

0.05869 +/- 0.057% mol

-272 +/- 0.42% kJ/mol

Butan-1-ol

4

1

13.6 +/- 0.42% kJ

1.214 +/- 0.002 g

0.01637 +/- 0.16% mol

-833 +/- 0.58% kJ/mol

Butan-1-ol

4

2

13.5 +/- 0.42% kJ

1.232 +/- 0.002 g

0.01662 +/- 0.16% mol

-811 +/- 0.58% kJ/mol

Butan-1-ol

4

3

14.4 +/- 0.44% kJ

1.435 +/- 0.002 g

0.01936 +/- 0.14% mol

-742 +/- 0.58% kJ/mol

Butan-1-ol

4

4

13.2 +/- 0.39% kJ

1.355 +/- 0.002 g

0.01828 +/- 0.15% mol

-722 +/- 0.54% kJ/mol

Butan-1-ol

4

5

15.6 +/- 0.38% kJ

1.650 +/- 0.002 g

0.02226 +/- 0.12% mol

-700 +/- 0.50% kJ/mol

Pentan-1-ol

5

1

14.9 +/- 0.39% kJ

0.852 +/- 0.002 g

0.00966 +/- 0.23% mol

-1.55E+3 +/- 0.63% kJ/mol

Pentan-1-ol

5

2

28.4 +/- 0.42% kJ

1.662 +/- 0.002 g

0.01885 +/- 0.12% mol

-1.51E+3 +/- 0.54% kJ/mol

Pentan-1-ol

5

3

14.6 +/- 0.37% kJ

0.905 +/- 0.002 g

0.0103 +/- 0.22% mol

-1.42E+3 +/- 0.59% kJ/mol

Pentan-1-ol

5

4

13.5 +/- 0.39% kJ

1.173 +/- 0.002 g

0.01330 +/- 0.17% mol

-1.01E+3 +/- 0.56% kJ/mol

Pentan-1-ol

5

5

15.2 +/- 0.39% kJ

1.399 +/- 0.002 g

0.01587 +/- 0.14% mol

-958 +/- 0.53% kJ/mol

Pentan-1-ol

5

6

11.8 +/- 0.50% kJ

1.182 +/- 0.002 g

0.01341 +/- 0.17% mol

-882 +/- 0.67% kJ/mol

Now, to calculate the average molar enthalpy of combustion for each of the alcohols, the data is grouped by alcohol type and the average is taken.

>>> results_df_2 = pd.DataFrame()
>>> results_df_2['Alcohol'] = results_df_1['Alcohol tested'].unique()
>>> grouped_data = list(results_df_1.groupby('Alcohol tested')['Molar Enthalpy of Combustion (kJ/mol)'])
>>> grouped_data_dict = {i[0]: i[1] for i in grouped_data}
>>> results_df_2['Average Molar Enthalpy of Combustion (kJ/mol)'] = [M.average(list(grouped_data_dict[i])).percent() for i in results_df_2['Alcohol']]
>>> results_df_2['Accepted Molar Enthalpy of Combustion (kJ/mol)'] = [M.fromStr('-1367c kJ/mol'), M.fromStr('-2021c kJ/mol'), M.fromStr('-2676c kJ/mol'), M.fromStr('-3329c kJ/mol')]
>>> results_df_2['Percent Error (%)'] = results_df_2.apply(lambda x: ((x['Accepted Molar Enthalpy of Combustion (kJ/mol)'] - x['Average Molar Enthalpy of Combustion (kJ/mol)']) * 100 / x['Accepted Molar Enthalpy of Combustion (kJ/mol)']), axis=1)

Results Table 2: Average Molar Enthalpy of Combustion

Alcohol

Average Molar Enthalpy of Combustion (kJ/mol)

Accepted Molar Enthalpy of Combustion (kJ/mol)

Percent Error (%)

Ethanol

-498.0 +/- 2E+1% kJ/mol

-1367 kJ/mol

63.57 +/- 9%

Propan-1-ol

-507.9 +/- 2E+1% kJ/mol

-2021 kJ/mol

74.869 +/- 7%

Butan-1-ol

-761.5 +/- 4% kJ/mol

-2676 kJ/mol

71.543 +/- 1.6%

Pentan-1-ol

-1222 +/- 1E+1% kJ/mol

-3329 kJ/mol

63.30 +/- 6%

Finally, we can convert the Measurement columns back into standard numeric columns.

>>> final_results_df_1 = results_df_1.copy()
>>> for i in range(4):
...     M.exportColumn(final_results_df_1, results_df_1.iloc[:, i + 3])
>>> final_results_df_2 = results_df_2.copy()
>>> final_results_df_2 = results_df_2.copy()
>>> for i in range(3):
...     M.exportColumn(final_results_df_2, results_df_2.iloc[:, i + 1], addUncertainty=i==0)

Final Results Table 1: Individual Molar Enthalpy of Combustion

Alcohol tested # of carbons Trial Q of H2O (kJ) Q of H2O Percent Uncertainty (%) Mass of Alcohol (g) Mass of Alcohol Percent Uncertainty (%) Molar Mass of Alcohol (g/mol) Molar Mass of Alcohol Percent Uncertainty (%) Molar Enthalpy of Combustion (kJ/mol) Molar Enthalpy of Combustion Percent Uncertainty (%)

Ethanol

2

1

16.2

0.41

1.07

0.19

0.02322

0.19

-697

0.59

Ethanol

2

2

17.3

0.38

1.411

0.14

0.03062

0.14

-565

0.52

Ethanol

2

3

16.2

0.37

1.33

0.15

0.02886

0.15

-562

0.52

Ethanol

2

4

15.7

0.41

1.497

0.13

0.03249

0.13

-483

0.54

Ethanol

2

5

16.2

0.39

2.09

0.096

0.04536

0.096

-358

0.48

Ethanol

2

6

15.5

0.38

2.219

0.09

0.04816

0.09

-323

0.47

Propan-1-ol

3

1

14.8

0.41

1.097

0.18

0.01825

0.18

-809

0.59

Propan-1-ol

3

2

13.4

0.4

1.294

0.15

0.02153

0.15

-624

0.56

Propan-1-ol

3

3

14.3

0.4

1.608

0.12

0.02675

0.12

-536

0.52

Propan-1-ol

3

4

14.2

0.41

1.701

0.12

0.0283

0.12

-500

0.53

Propan-1-ol

3

5

14.3

0.4

2.798

0.071

0.04655

0.071

-307

0.47

Propan-1-ol

3

6

15.9

0.36

3.528

0.057

0.05869

0.057

-272

0.42

Butan-1-ol

4

1

13.6

0.42

1.214

0.16

0.01637

0.16

-833

0.58

Butan-1-ol

4

2

13.5

0.42

1.232

0.16

0.01662

0.16

-811

0.58

Butan-1-ol

4

3

14.4

0.44

1.435

0.14

0.01936

0.14

-742

0.58

Butan-1-ol

4

4

13.2

0.39

1.355

0.15

0.01828

0.15

-722

0.54

Butan-1-ol

4

5

15.6

0.38

1.65

0.12

0.02226

0.12

-700

0.5

Pentan-1-ol

5

1

14.9

0.39

0.852

0.23

0.00966

0.23

-1550

0.63

Pentan-1-ol

5

2

28.4

0.42

1.662

0.12

0.01885

0.12

-1510

0.54

Pentan-1-ol

5

3

14.6

0.37

0.905

0.22

0.0103

0.22

-1420

0.59

Pentan-1-ol

5

4

13.5

0.39

1.173

0.17

0.0133

0.17

-1010

0.56

Pentan-1-ol

5

5

15.2

0.39

1.399

0.14

0.01587

0.14

-958

0.53

Pentan-1-ol

5

6

11.8

0.5

1.182

0.17

0.01341

0.17

-882

0.67

Final Results Table 2: Average Molar Enthalpy of Combustion

Alcohol Average Molar Enthalpy of Combustion (kJ/mol) Average Molar Enthalpy of Combustion Percent Uncertainty (%) Accepted Molar Enthalpy of Combustion (kJ/mol) Percent Error (%)

Ethanol

-498

20

-1367

63.57

Propan-1-ol

-507.9

20

-2021

74.869

Butan-1-ol

-761.5

4

-2676

71.543

Pentan-1-ol

-1222

10

-3329

63.3