100% found this document useful (1 vote)
5 views

Python Programming for Data Analysis 1st Edition José Unpingco instant download

The document provides information about the book 'Python Programming for Data Analysis' by José Unpingco, which is designed for readers with basic programming knowledge. It emphasizes effective Python usage for data analysis, covering essential topics like Numpy, Pandas, and data visualization. Additionally, it includes links to various related resources and other books by the author.

Uploaded by

denentrehyil
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
5 views

Python Programming for Data Analysis 1st Edition José Unpingco instant download

The document provides information about the book 'Python Programming for Data Analysis' by José Unpingco, which is designed for readers with basic programming knowledge. It emphasizes effective Python usage for data analysis, covering essential topics like Numpy, Pandas, and data visualization. Additionally, it includes links to various related resources and other books by the author.

Uploaded by

denentrehyil
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 60

Python Programming for Data Analysis 1st Edition

José Unpingco download

https://textbookfull.com/product/python-programming-for-data-
analysis-1st-edition-jose-unpingco/

Download more ebook from https://textbookfull.com


We believe these products will be a great fit for you. Click
the link to download now, or visit textbookfull.com
to discover even more!

Python for Probability Statistics and Machine Learning


José Unpingco

https://textbookfull.com/product/python-for-probability-
statistics-and-machine-learning-jose-unpingco/

Python for Probability, Statistics, and Machine


Learning 2nd Edition José Unpingco

https://textbookfull.com/product/python-for-probability-
statistics-and-machine-learning-2nd-edition-jose-unpingco/

Vertically Integrated Architectures: Versioned Data


Models, Implicit Services, and Persistence-Aware
Programming 1st Edition Jos Jong

https://textbookfull.com/product/vertically-integrated-
architectures-versioned-data-models-implicit-services-and-
persistence-aware-programming-1st-edition-jos-jong/

Practical Machine Learning for Data Analysis Using


Python 1st Edition Abdulhamit Subasi

https://textbookfull.com/product/practical-machine-learning-for-
data-analysis-using-python-1st-edition-abdulhamit-subasi/
Python for Data Analysis Data Wrangling with Pandas
NumPy and IPython Wes Mckinney

https://textbookfull.com/product/python-for-data-analysis-data-
wrangling-with-pandas-numpy-and-ipython-wes-mckinney/

Python for Excel A Modern Environment for Automation


and Data Analysis 1st Edition Felix Zumstein

https://textbookfull.com/product/python-for-excel-a-modern-
environment-for-automation-and-data-analysis-1st-edition-felix-
zumstein/

Python for Data Analysis Data Wrangling with pandas


NumPy and Jupyter 3rd Edition Wes Mckinney

https://textbookfull.com/product/python-for-data-analysis-data-
wrangling-with-pandas-numpy-and-jupyter-3rd-edition-wes-mckinney/

Functional Programming in R: Advanced Statistical


Programming for Data Science, Analysis and Finance 1st
Edition Thomas Mailund

https://textbookfull.com/product/functional-programming-in-r-
advanced-statistical-programming-for-data-science-analysis-and-
finance-1st-edition-thomas-mailund/

Python Data Analysis: Perform data collection, data


processing, wrangling, visualization, and model
building using Python 3rd Edition Avinash Navlani

https://textbookfull.com/product/python-data-analysis-perform-
data-collection-data-processing-wrangling-visualization-and-
model-building-using-python-3rd-edition-avinash-navlani/
José Unpingco

Python
Programming
for Data
Analysis
Python Programming for Data Analysis
José Unpingco

Python Programming
for Data Analysis
José Unpingco
University of California
San Diego
CA, USA

ISBN 978-3-030-68951-3 ISBN 978-3-030-68952-0 (eBook)


https://doi.org/10.1007/978-3-030-68952-0

© The Editor(s) (if applicable) and The Author(s), under exclusive license to Springer Nature Switzerland
AG 2021
This work is subject to copyright. All rights are solely and exclusively licensed by the Publisher, whether
the whole or part of the material is concerned, specifically the rights of translation, reprinting, reuse
of illustrations, recitation, broadcasting, reproduction on microfilms or in any other physical way, and
transmission or information storage and retrieval, electronic adaptation, computer software, or by similar
or dissimilar methodology now known or hereafter developed.
The use of general descriptive names, registered names, trademarks, service marks, etc. in this publication
does not imply, even in the absence of a specific statement, that such names are exempt from the relevant
protective laws and regulations and therefore free for general use.
The publisher, the authors, and the editors are safe to assume that the advice and information in this book
are believed to be true and accurate at the date of publication. Neither the publisher nor the authors or
the editors give a warranty, expressed or implied, with respect to the material contained herein or for any
errors or omissions that may have been made. The publisher remains neutral with regard to jurisdictional
claims in published maps and institutional affiliations.

This Springer imprint is published by the registered company Springer Nature Switzerland AG
The registered company address is: Gewerbestrasse 11, 6330 Cham, Switzerland
To Irene, Nicholas, and Daniella, for all their
patient support.
Preface

This book grew out of notes for the ECE143 Programming for Data Analysis class
that I have been teaching at the University of California, San Diego, which is a
requirement for both graduate and undergraduate degrees in Machine Learning and
Data Science. The reader is assumed to have some basic programming knowledge
and experience using another language, such as Matlab or Java. The Python idioms
and methods we discuss here focus on data analysis, notwithstanding Python’s
usage across many other topics. Specifically, because raw data is typically a mess
and requires much work to prepare, this text focuses on specific Python language
features to facilitate such cleanup, as opposed to only focusing on particular Python
modules for this.
As with ECE143, here we discuss why things are the way they are in Python
instead of just that they are this way. I have found that providing this kind of
context helps students make better engineering design choices in their codes, which
is especially helpful for newcomers to both Python and data analysis. The text is
sprinkled with little tricks of the trade to make it easier to create readable and
maintainable code suitable for use in both production and development.
The text focuses on using the Python language itself effectively and then moves
on to key third-party modules. This approach improves effectiveness in different
environments, which may or may not have access to such third-party modules. The
Numpy numerical array module is covered in depth because it is the foundation
of all data science and machine learning in Python. We discuss the Numpy array
data structure in detail, especially its memory aspects. Next, we move on to Pandas
and develop its many features for effective and fluid data processing. Because data
visualization is key to data science and machine learning, third-party modules such
as Matplotlib are developed in depth, as well as web-based modules such as Bokeh,
Holoviews, Plotly, and Altair.
On the other hand, I would not recommend this book to someone with no
programming experience at all, but if you can do a little Python already and want to
improve by understanding how and why Python works the way it does, then this is
a good book for you.

vii
viii Preface

To get the most out of this book, open a Python interpreter and type-along with
the many code samples. I worked hard to ensure that all of the given code samples
work as advertised.

Acknowledgments I would like to acknowledge the help of Brian Granger and Fernando Perez,
two of the originators of the Jupyter Notebook, for all their great work, as well as the Python
community as a whole, for all their contributions that made this book possible. Hans Petter
Langtangen was the author of the Doconce [1] document preparation system that was used to
write this text. Thanks to Geoffrey Poore [2] for his work with PythonTeX and LATEX, both key
technologies used to produce this book.

San Diego, CA, USA José Unpingco


February, 2020

References

1. H.P. Langtangen, DocOnce markup language. https://github.com/hplgit/doconce


2. G.M. Poore, Pythontex: reproducible documents with latex, python, and more. Comput. Sci.
Discov. 8(1), 014010 (2015)
Contents

1 Basic Programming . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1 Basic Language . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1
1.1.1 Getting Started . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2
1.1.2 Reserved Keywords . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.3 Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3
1.1.4 Complex Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5
1.1.5 Strings . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
1.1.6 Loops and Conditionals. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 17
1.1.7 Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21
1.1.8 File Input/Output . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 34
1.1.9 Dealing with Errors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
1.1.10 Power Python Features to Master . . . . . . . . . . . . . . . . . . . . . . . . . . . 40
1.1.11 Generators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 43
1.1.12 Decorators . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 48
1.1.13 Iteration and Iterables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 52
1.1.14 Using Python Assertions to Pre-debug Code . . . . . . . . . . . . . . . 60
1.1.15 Stack Tracing with sys.settrace . . . . . . . . . . . . . . . . . . . . . . 61
1.1.16 Debugging Using IPython . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
1.1.17 Logging from Python . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
2 Object-Oriented Programming. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.1 Properties/Attributes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
2.2 Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 69
2.3 Inheritance . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 71
2.4 Class Variables . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 73
2.5 Class Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
2.6 Static Methods . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 75
2.7 Hashing Hides Parent Variables from Children . . . . . . . . . . . . . . . . . . . . . . 76
2.8 Delegating Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 76
2.9 Using super for Delegation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 77
2.10 Metaprogramming: Monkey Patching . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79

ix
x Contents

2.11 Abstract Base Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 80


2.12 Descriptors . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 82
2.13 Named Tuples and Data Classes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
2.14 Generic Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 89
2.15 Design Patterns . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
2.15.1 Template . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91
2.15.2 Singleton . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92
2.15.3 Observer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 93
2.15.4 Adapter . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 94
3 Using Modules . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.1 Standard Library . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 95
3.2 Writing and Using Your Own Modules. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 96
3.2.1 Using a Directory as a Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
3.3 Dynamic Importing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 98
3.4 Getting Modules from the Web . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
3.5 Conda Package Management . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 99
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101
4 Numpy. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
4.1 Dtypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 103
4.2 Multidimensional Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 104
4.3 Reshaping and Stacking Numpy Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105
4.4 Duplicating Numpy Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 106
4.5 Slicing, Logical Array Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 107
4.6 Numpy Arrays and Memory . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 108
4.7 Numpy Memory Data Structures . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 111
4.8 Array Element-Wise Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
4.9 Universal Functions . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 114
4.10 Numpy Data Input/Output. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
4.11 Linear Algebra . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115
4.12 Broadcasting . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 116
4.13 Masked Arrays . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120
4.14 Floating Point Numbers . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121
4.15 Advanced Numpy dtypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 126
5 Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
5.1 Using Series . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127
5.2 Using DataFrame . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 131
5.3 Reindexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135
5.4 Deleting Items . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 136
5.5 Advanced Indexing . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 137
5.6 Broadcasting and Data Alignment . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 138
5.7 Categorical and Merging . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 140
Contents xi

5.8 Memory Usage and dtypes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 143


5.9 Common Operations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146
5.10 Displaying DataFrames. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 148
5.11 Multi-index. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 150
5.12 Pipes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152
5.13 Data Files and Databases . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 153
5.14 Customizing Pandas . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 154
5.15 Rolling and Filling Operations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 155
6 Visualizing Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157
6.1 Matplotlib . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 158
6.1.1 Setting Defaults . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
6.1.2 Legends . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 160
6.1.3 Subplots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
6.1.4 Spines . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 161
6.1.5 Sharing Axes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 162
6.1.6 3D Surfaces . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
6.1.7 Using Patch Primitives . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 164
6.1.8 Patches in 3D . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165
6.1.9 Using Transformations. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 168
6.1.10 Annotating Plots with Text . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 170
6.1.11 Annotating Plots with Arrows . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 171
6.1.12 Embedding Scalable and Non-scalable Subplots . . . . . . . . . . . 173
6.1.13 Animations . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 175
6.1.14 Using Paths Directly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 177
6.1.15 Interacting with Plots Using Sliders . . . . . . . . . . . . . . . . . . . . . . . . 179
6.1.16 Colormaps . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181
6.1.17 Low-Level Control Using setp and getp . . . . . . . . . . . . . . . 183
6.1.18 Interacting with Matplotlib Figures . . . . . . . . . . . . . . . . . . . . . . . . . 183
6.1.19 Keyboard Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 184
6.1.20 Mouse Events . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 185
6.2 Seaborn . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 186
6.2.1 Automatic Aggregation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 190
6.2.2 Multiple Plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 194
6.2.3 Distribution Plots . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 196
6.3 Bokeh. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
6.3.1 Using Bokeh Primitives. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 204
6.3.2 Bokeh Layouts . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 206
6.3.3 Bokeh Widgets . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207
6.4 Altair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213
6.4.1 Detailing Altair. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 215
6.4.2 Aggregations and Transformations. . . . . . . . . . . . . . . . . . . . . . . . . . 217
6.4.3 Interactive Altair . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 222
6.5 Holoviews . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 224
6.5.1 Dataset . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230
xii Contents

6.5.2 Image Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232


6.5.3 Tabular Data . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 232
6.5.4 Customizing Interactivity . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 235
6.5.5 Streams . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 236
6.5.6 Pandas Integration with hvplot . . . . . . . . . . . . . . . . . . . . . . . . . . 237
6.5.7 Network Graphs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 243
6.5.8 Holoviz Panel for Dashboards . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 247
6.6 Plotly . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 251
References . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 259

Index . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 261
Chapter 1
Basic Programming

1.1 Basic Language

Before we get into the details, it is a good idea to get a high-level orientation to
Python. This will improve your decision-making later regarding software develop-
ment for your own projects, especially as these get bigger and more complex. Python
grew out of a language called ABC, which was developed in the Netherlands in the
1980s as an alternative to BASIC to get scientists to utilize microcomputers, which
were new at the time. The important impulse was to make non-specialist scientists
able to productively utilize these new computers. Indeed, this pragmatic approach
continues to this day in Python which is a direct descendent of the ABC language.
There is a saying in Python—come for the language, stay for the community.
Python is an open source project that is community driven so there is no corporate
business entity making top-down decisions for the language. It would seem that such
an approach would lead to chaos but Python has benefited over many years from
the patient and pragmatic leadership of Guido van Rossum, the originator of the
language. Nowadays, there is a separate governance committee that has taken over
this role since Guido’s retirement. The open design of the language and the quality
of the source code has made it possible for Python to enjoy many contributions from
talented developers all over the world over many years, as embodied by the richness
of the standard library. Python is also legendary for having a welcoming community
for newcomers so it is easy to find help online for getting started with Python.
The pragmatism of the language and the generosity of the community have long
made Python a great way to develop web applications. Before the advent of data
science and machine learning, upwards of 80% of the Python community were web
developers. In the last five years (at the time of this writing), the balance is tilted to
an almost even split between web developers and data scientists. This is the reason
you find a lot of web protocols and technology in the standard library.
Python is an interpreted language as opposed to a compiled language like C
or FORTRAN. Although both cases start with a source code file, the compiler

© The Editor(s) (if applicable) and The Author(s), under exclusive license 1
to Springer Nature Switzerland AG 2021
J. Unpingco, Python Programming for Data Analysis,
https://doi.org/10.1007/978-3-030-68952-0_1
2 1 Basic Programming

examines the source code end-to-end and produces an executable that is linked to
system-specific library files. Once the executable is created, there is no longer any
need for the compiler. You can just run the executable on the system. On the other
hand, an interpreted language like Python you must always have a running Python
process to execute the code. This is because the Python process is an abstraction on
the platform it is running on and thus must interpret the instructions in the source
code to execute them on the platform. As the intermediary between the source
code on the platform, the Python interpreter is responsible for the platform specific
issues. The advantage of this is that source code can be run on different platforms as
long as there is a working Python interpreter on each platform. This makes Python
source codes portable between platforms because the platform specific details are
handled by the respective Python interpreters. Portability between platforms was
a key advantage of Python, especially in the early days. Going back to compiled
languages, because the platform specific details are embedded in the executable, the
executable is tied to a specific platform and to those specific libraries that have been
linked into the executable. This makes these codes are less portable than Python,
but because the compiler is able to link to the specific platform it has the option
to exploit platform- specific level optimizations and libraries. Furthermore, the
compiler can study the source code file and apply compiler-level optimizations that
accelerate the resulting executable. In broad strokes, those are the key differences
between interpreted and compiled languages. We will later see that there are many
compromises between these two extremes for accelerating Python codes.
It is sometimes said that Python is slow as compared to compiled languages,
and pursuant to the differences we discussed above, that may be expected, but it
is really a question of where the clock starts. If you start the clock to account for
developer time, not just code runtime, then Python is clearly faster, just because
the development iteration cycle does not require a tedious compile and link step.
Furthermore, Python is just simpler to use than compiled languages because so
many tricky elements like memory management are handled automatically. Pythons
quick turnaround time is a major advantage for product development, which requires
rapid iteration. On the other hand, codes that are compute-limited and must run
on specialized hardware are not good use-cases for Python. These include solving
systems of parallel differential equations simulating large-scale fluid mechanics or
other large-scale physics calculations. Note that Python is used in such settings but
mainly for staging these computations or postprocessing the resulting data.

1.1.1 Getting Started

Your primary interface to the Python interpreter is the commandline. You can type
in python in your terminal you should see something like the following,
Python 3.7.3 (default, Mar 27 2019, 22:11:17)
[GCC 7.3.0] :: Anaconda, Inc. on linux
1.1 Basic Language 3

Type "help", "copyright", "credits" or "license" for more


→ information.
>>>

There is a lot of useful information including the version of Python and its
provenance. This matters because sometimes the Python interpreter is compiled to
allow fast access to certain preferred modules (i.e., math module). We will discuss
this more when we talk about Python modules.

1.1.2 Reserved Keywords

Although Python will not stop you, do not use these as variable or function names.
and del from not while
as elif global or with
assert else if pass yield
break except import print
class exec in raise
continue finally is return
def for lambda try

nor these neither


abs all any ascii bin bool breakpoint bytearray bytes callable
chr classmethod compile complex copyright credits delattr
dict dir display divmod enumerate eval exec filter float
format frozenset getattr globals hasattr hash help hex id
input int isinstance issubclass iter len list locals map max
memoryview min next object oct open ord pow print property
range repr reversed round set setattr slice sorted
staticmethod str sum super tuple type vars zip

For example, a common mistake is to assign sum=10, not realizing that now the
sum() Python function is no longer available.

1.1.3 Numbers

Python has common-sense number-handling capabilities. The comment character is


the hash (#) symbol.
>>> 2+2
4
>>> 2+2 # and a comment on the same line as code
4
>>> (50-5*6)/4
5.0

Note that division in Python 2 is integer-division and in Python 3 it is floating


point division with the // symbol providing integer-division. Python is dynamically
4 1 Basic Programming

typed, so we can do the following assignments without declaring the types of


width and height.
>>> width = 20
>>> height = 5*9
>>> width * height
900
>>> x = y = z = 0 # assign x, y and z to zero
>>> x
0
>>> y
0
>>> z
0
>>> 3 * 3.75 / 1.5
7.5
>>> 7.0 / 2 # float numerator
3.5
>>> 7/2
3.5
>>> 7 // 2 # double slash gives integer division
3

It is best to think of assignments as labeling values in memory. Thus, width is a


label for the number 20. This will make more sense later.1 Since Python 3.8, the
walrus assignment operator allows the assignment itself to have the value of the
assignee, as in the following,
>>> print(x:=10)
10
>>> print(x)
10

The operator has many other subtle uses and was introduced to improve readability
in certain situations. You can also cast among the numeric types in a common-sense
way:
>>> int(1.33333)
1
>>> float(1)
1.0
>>> type(1)
<class 'int'>
>>> type(float(1))
<class 'float'>

Importantly, Python integers are of arbitrary length and can handle extremely large
integers. This is because they are stored as a list of digits internally. This means that
they are slower to manipulate than Numpy integers which have fixed bit-lengths,
provided that the integer can fit into allocated memory.

1 Notehttp://www.pythontutor.com is a great resource for exploring how variables are assigned in


Python.
1.1 Basic Language 5

Programming Tip: IPython


The default Python interpreter is useful and you should be familiar with it
but the IPython interpretera is a useful extension that provides features like
sophisticated tab-completion and many other conveniences that make it easier
to work with Python in the terminal.
a
See http://github.com/ipython/ipython for the latest on how to get started with IPython.

1.1.4 Complex Numbers

Python has rudimentary support for complex numbers.


>>> 1j * 1J
(-1+0j)
>>> 1j * complex(0,1)
(-1+0j)
>>> 3+1j*3
(3+3j)
>>> (3+1j)*3
(9+3j)
>>> (1+2j)/(1+1j)
(1.5+0.5j)
>>> a=1.5+0.5j
>>> a.real # the dot notation gets an attribute
1.5
>>> a.imag
0.5
>>> a=3.0+4.0j
>>> float(a)
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: can't convert complex to float
>>> a.real
3.0
>>> a.imag
4.0
>>> abs(a) # sqrt(a.real**2 + a.imag**2)
5.0
>>> tax = 12.5 / 100
>>> price = 100.50
>>> price * tax
12.5625
>>> price + _
113.0625
>>> # the underscore character is the last evaluated result
>>> round(_, 2) # the underscore character is the last evaluated
→ result
113.06
6 1 Basic Programming

We typically use Numpy for complex numbers, though.

1.1.5 Strings

String-handling is very well developed and highly optimized in Python. We just


cover the main points here. First, single or double quotes define a string and there is
no precedence relationship between single and double quotes.
>>> 'spam eggs'
'spam eggs'
>>> 'doesn\'t' # backslash defends single quote
"doesn't"
>>> "doesn't"
"doesn't"
>>> '"Yes," he said.'
'"Yes," he said.'
>>> "\"Yes,\" he said."
'"Yes," he said.'
>>> '"Isn\'t," she said.'
'"Isn\'t," she said.'

Python strings have C-style escape characters for newlinewsnewlines, tabs, etc.
String literals defined this way are by default encoded using UTF-8 instead of
ASCII, as in Python 2. The triple single (’) or triple double quote (") denotes a
block with embedded newlines or other quotes. This is particularly important for
function documentation docstrings that we will discussed later.
>>> print( '''Usage: thingy [OPTIONS]
... and more lines
... here and
... here
... ''')
Usage: thingy [OPTIONS]
and more lines
here and
here

Strings can be controlled with a character before the single or double quote. For
example, see the comments (#) below for each step,
>>> # the 'r' makes this a 'raw' string
>>> hello = r"This long string contains newline characters \n, as
→ in C"
>>> print(hello)
This long string contains newline characters \n, as in C
>>> # otherwise, you get the newline \n acting as such
>>> hello = "This long string contains newline characters \n, as
→ in C"
>>> print(hello)
This long string contains newline characters
, as in C
1.1 Basic Language 7

>>> u'this a unicode string μ ±' # the 'u' makes it a unicode


→ string for Python2
'this a unicode string μ ±'
>>> 'this a unicode string μ ±' # no 'u' in Python3 is still
→ unicode string
'this a unicode string μ ±'
>>> u'this a unicode string \xb5 \xb1' # using hex-codes
'this a unicode string μ ±'

Note that a f-string evaluates (i.e., interpolates) the Python variables in the
current scope,
>>> x = 10
>>> s = f'{x}'
>>> type(s)
<class 'str'>
>>> s
'10'

Beware that an f-string is not resolved until run-time because it has to resolve
the embedded variables. This means that you cannot use f-strings as docstrings.
Importantly, Python strings are immutable which means that once a string is created,
it cannot be changed in-place. For example,
>>> x = 'strings are immutable '
>>> x[0] = 'S' # not allowed!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'str' object does not support item assignment

This means you have to create new strings to make this kind of change.
Strings vs Bytes In Python 3, the default string encoding for string literals is UTF-
8. The main thing to keep in mind is that bytes and strings are now distinct objects,
as opposed to both deriving from basestring in Python 2. For example, given
the following unicode string,
>>> x='Ø'
>>> isinstance(x,str) # True
True
>>> isinstance(x,bytes) # False
False
>>> x.encode('utf8') # convert to bytes with encode
b'\xc3\x98'

Note the distinction between bytes and strings. We can convert bytes to strings using
decode,
>>> x=b'\xc3\x98'
>>> isinstance(x,bytes) # True
True
>>> isinstance(x,str) # False
False
>>> x.decode('utf8')
'Ø'
8 1 Basic Programming

An important consequence is that you cannot append strings and bytes as in the
following: u"hello"+b"goodbye". This used to work fine in Python 2 because
bytes would automatically be decoded using ASCII, but this no longer works in
Python 3. To get this behavior, you have to explicitly decode/encode. For
example,
>>> x=b'\xc3\x98'
>>> isinstance(x,bytes) # True
True
>>> y='banana'
>>> isinstance(y,str) # True
True
>>> x+y.encode()
b'\xc3\x98banana'
>>> x.decode()+y
'Øbanana'

Slicing Strings Python is a zero-indexed language (like C). The colon (:) character
denotes .
>>> word = 'Help' + 'A'
>>> word
'HelpA'
>>> '<' + word*5 + '>'
'<HelpAHelpAHelpAHelpAHelpA>'
>>> word[4]
'A'
>>> word[0:2]
'He'
>>> word[2:4]
'lp'
>>> word[-1] # The last character
'A'
>>> word[-2] # The last-but-one character
'p'
>>> word[-2:] # The last two characters
'pA'
>>> word[:-2] # Everything except the last two characters
'Hel'

String Operations Some basic numerical operations work with strings.


>>> 'hey '+'you' # concatenate with plus operator
'hey you'
>>> 'hey '*3 # integer multiplication duplicates strings
'hey hey hey '
>>> ('hey ' 'you') # using parentheses without separating comma
'hey you'

Python has a built-in and very powerful regular expression module (re) for string
manipulations. String substitution creates new strings.
>>> x = 'This is a string'
>>> x.replace('string','newstring')
'This is a newstring'
>>> x # x hasn't changed
'This is a string'
1.1 Basic Language 9

Formatting Strings There are so many ways to format strings in Python, but here
is the simplest that follows C-language sprintf conventions in conjunction with
the modulo operator %.
>>> 'this is a decimal number %d'%(10)
'this is a decimal number 10'
>>> 'this is a float %3.2f'%(10.33)
'this is a float 10.33'
>>> x = 1.03
>>> 'this is a variable %e' % (x) # exponential format
'this is a variable 1.030000e+00'

Alternatively, you can just join them using +,


>>> x = 10
>>> 'The value of x = '+str(x)
'The value of x = 10'

You can format using dictionaries as in the following,


>>> data = {'x': 10, 'y':20.3}
>>> 'The value of x = %(x)d and y = %(y)f'%(data)
'The value of x = 10 and y = 20.300000'

You can use the format method on the string,


>>> x = 10
>>> y = 20
>>> 'x = {0}, y = {1}'.format(x,y)
'x = 10, y = 20'

The advantage of format is you can reuse the placeholders as in the following,
>>> 'x = {0},{1},{0}; y = {1}'.format(x,y)
'x = 10,20,10; y = 20'

And also the f-string method we discussed above.

Programming Tip: Python 2 Strings


In Python 2, the default string encoding was 7-bit ASCII. There was no
distinction between bytes and strings. For example, you could read from a
binary-encoded JPG file as in the following,
with open('hour_1a.jpg','r') as f:
x = f.read()

This works fine in Python 2 but throws a UnicodeDecodeError error in


Python 3. To fix this in Python 3, you have to read using the rb binary mode
instead of just the r file mode.

Basic Data Structures Python provides many powerful data structures. The two
most powerful and fundamental are the list and dictionary. Data structures and
10 1 Basic Programming

algorithms go hand-in-hand. If you do not understand data structures, then you


cannot effectively write algorithms and vice versa. Fundamentally, data structures
provide guarantees to the programmer that will be fulfilled if the data structures are
used in the agreed-upon manner. These guarantees are known as the invariants for
the data structure.
Lists The list is an order-preserving general container that implements the
sequence data structure. The invariant for the list is that indexing a non-empty list
will always give you the next valid element in order. Indeed, the list is Python’s
primary ordered data structure. This means that if you have a problem where order
is important, then you should be thinking about the list data structure. This will
make sense with following examples.
>>> mix = [3,'tree',5.678,[8,4,2]] # can contain sublists
>>> mix
[3, 'tree', 5.678, [8, 4, 2]]
>>> mix[0] # zero-indexed Python
3
>>> mix[1] # indexing individual elements
'tree'
>>> mix[-2] # indexing from the right, same as strings
5.678
>>> mix[3] # get sublist
[8, 4, 2]
>>> mix[3][1] # last element is sublist
4
>>> mix[0] = 666 # lists are mutable
>>> mix
[666, 'tree', 5.678, [8, 4, 2]]
>>> submix = mix[0:3] # creating sublist
>>> submix
[666, 'tree', 5.678]
>>> switch = mix[3] + submix # append two lists with plus
>>> switch
[8, 4, 2, 666, 'tree', 5.678]
>>> len(switch) # length of list is built-in function
6
>>> resize=[6.45,'SOFIA',3,8.2E6,15,14]
>>> len(resize)
6
>>> resize[1:4] = [55] # assign slices
>>> resize
[6.45, 55, 15, 14]
>>> len(resize) # shrink a sublist
4
>>> resize[3]=['all','for','one']
>>> resize
[6.45, 55, 15, ['all', 'for', 'one']]
>>> len(resize)
4
>>> resize[4]=2.87 # cannot append this way!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IndexError: list assignment index out of range
>>> temp = resize[:3]
1.1 Basic Language 11

>>> resize = resize + [2.87] # add to list


>>> resize
[6.45, 55, 15, ['all', 'for', 'one'], 2.87]
>>> len(resize)
5
>>> del resize[3] # delete item
>>> resize
[6.45, 55, 15, 2.87]
>>> len(resize) # shorter now
4
>>> del resize[1:3] # delete a sublist
>>> resize
[6.45, 2.87]
>>> len(resize) # shorter now
2

Programming Tip: Sorting Lists


The built-in function sorted sorts lists,
>>> sorted([1,9,8,2])
[1, 2, 8, 9]

Lists can also be sorted in-place using the sort() list method,
>>> x = [1,9,8,2]
>>> x.sort()
>>> x
[1, 2, 8, 9]

Both of these use the powerful Timsort algorithm. Later, we will see more
variations and uses for these sorting functions.

Now that we have a feel for how to index and use lists, let us talk about the invariant
that it provides: as long as you index a list within its bounds, it provides the next
ordered element of the list. For example,
>>> x = ['a',10,'c']
>>> x[1] # return 10
10
>>> x.remove(10)
>>> x[1] # next element
'c'

Notice that the list data structure filled in the gap after removing 10. This is extra
work that the list data structure did for you without explicitly programming. Also,
list elements are accessible via integer indices and integers have a natural ordering
and thus so does the list. The work of maintaining the invariant does not come for
free, however. Consider the following,
>>> x = [1,3,'a']
>>> x.insert(0,10) # insert at beginning
12 1 Basic Programming

>>> x
[10, 1, 3, 'a']

Seem harmless? Sure, for small lists, but not so for large lists. This is because
to maintain the invariant the list has to scoot (i.e., memory copy) the remaining
elements over to the right to accommodate the new element added at the beginning.
Over a large list with millions of elements and in a loop, this can take a substantial
amount of time. This is why the default append() and pop() list methods work
at the tail end of the list, where there is no need to scoot items to the right.
Tuples Tuples are another general purpose sequential container in Python, very
similar to lists, but these are immutable. Tuples are delimited by commas (parenthe-
ses are grouping symbols). Here are some examples,
>>> a = 1,2,3 # no parenthesis needed!
>>> type(a)
<class 'tuple'>
>>> pets=('dog','cat','bird')
>>> pets[0]
'dog'
>>> pets + pets # addition
('dog', 'cat', 'bird', 'dog', 'cat', 'bird')
>>> pets*3
('dog', 'cat', 'bird', 'dog', 'cat', 'bird', 'dog', 'cat', 'bird')
>>> pets[0]='rat' # assignment not work!
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: 'tuple' object does not support item assignment

It may seem redundant to have tuples which behave in terms of their indexing like
lists, but the key difference is that tuples are immutable, as the last line above shows.
The key advantage of immutability is that it comes with less overhead for Python
memory management. In this sense, they are lighter weight and provide stability for
codes that pass tuples around. Later, we will see this for function signatures, which
is where the major advantages of tuples arise.

Programming Tip: Understanding List Memory


Python’s id function shows an integer corresponding to the internal reference
for a given variable. Earlier, we suggested considering variable assignment as
labeling because internally Python works with a variable’s id, not its variable
name/label.
>>> x = y = z = 10.1100
>>> id(x) # different labels for same id
140271927806352
>>> id(y)
140271927806352
>>> id(z)
140271927806352

(continued)
1.1 Basic Language 13

This is more consequential for mutable data structures like lists. Consider the
following,
>>> x = y = [1,3,4]
>>> x[0] = 'a'
>>> x
['a', 3, 4]
>>> y
['a', 3, 4]
>>> id(x),id(y)
(140271930505344, 140271930505344)

Because x and y are merely two labels for the same underlying list, changes to
one of the labels affects both lists. Python is inherently stingy about allocating
new memory so if you want to have two different lists with the same content,
you can force a copy as in the following,
>>> x = [1,3,4]
>>> y = x[:] # force copy
>>> id(x),id(y) # different ids now!
(140271930004160, 140271929640448)
>>> x[1] = 99
>>> x
[1, 99, 4]
>>> y # retains original data
[1, 3, 4]

Tuple Unpacking Tuples unpack assignments in order as follows:,


>>> a,b,c = 1,2,3
>>> a
1
>>> b
2
>>> c
3

Python 3 can unpack tuples in chunks using the * operator,


>>> x,y,*z = 1,2,3,4,5
>>> x
1
>>> y
2
>>> z
[3, 4, 5]

Note how the z variable collected the remaining items in the assignment. You can
also change the order of the chunking,
>>> x,*y,z = 1,2,3,4,5
>>> x
1
14 1 Basic Programming

>>> y
[2, 3, 4]
>>> z
5

This unpacking is sometimes called de-structuring, or splat, in case you read this
term elsewhere.
Dictionaries Python dictionaries are central to Python because many other ele-
ments (e.g., functions, classes) are built around them. Effectively programming
Python means using dictionaries effectively. Dictionaries are general containers that
implement the mapping data structure, which is sometimes called a hash table or
associative array. Dictionaries require a key/value pair, which maps the key to the
value.
>>> x = {'key': 'value'}

The curly braces and the colon make the dictionary. To retrieve the value from the
x dictionary, you must index it with the key as shown,
>>> x['key']
'value'

Let us get started with some basic syntax.


>>> x={'play':'Shakespeare','actor':'Wayne','direct':'Kubrick',
... 'author':'Hemmingway','bio':'Watson'}

>>> len(x) # number of key/value pairs


5
>>> x['pres']='F.D.R.' # assignment to key 'pres'
>>> x
{'play': 'Shakespeare', 'actor': 'Wayne', 'direct': 'Kubrick',
→ 'author': 'Hemmingway', 'bio': 'Watson', 'pres': 'F.D.R.'}
>>> x['bio']='Darwin' # reassignment for 'bio' key
>>> x
{'play': 'Shakespeare', 'actor': 'Wayne', 'direct': 'Kubrick',
→ 'author': 'Hemmingway', 'bio': 'Darwin', 'pres': 'F.D.R.'}
>>> del x['actor'] # delete key/value pair
>>> x
{'play': 'Shakespeare', 'direct': 'Kubrick', 'author':
→ 'Hemmingway', 'bio': 'Darwin', 'pres': 'F.D.R.'}

Dictionaries can also be created with the dict built-in function,


>>> # another way of creating a dict
>>> x=dict(key='value',
... another_key=1.333,
... more_keys=[1,3,4,'one'])
>>> x
{'key': 'value', 'another_key': 1.333, 'more_keys': [1, 3, 4,
→ 'one']}
>>> x={(1,3):'value'} # any immutable type can be a valid key
>>> x
{(1, 3): 'value'}
>>> x[(1,3)]='immutables can be keys'
1.1 Basic Language 15

As generalized containers, dictionaries can contain other dictionaries or lists or other


Python types.

Programming Tip: Unions of Dictionaries


What if you want to create a union of dictionaries in one- line?
>>> d1 = {'a':1, 'b':2, 'c':3}
>>> d2 = {'A':1, 'B':2, 'C':3}
>>> dict(d1,**d2) # combo of d1 and d2
{'a': 1, 'b': 2, 'c': 3, 'A': 1, 'B': 2, 'C': 3}
>>> {**d1,**d2} # without dict function
{'a': 1, 'b': 2, 'c': 3, 'A': 1, 'B': 2, 'C': 3}

Pretty slick.

The invariant that the dictionary provides is that as long as you provide a valid key,
then it will always retrieve the corresponding value; or, in the case of assignment,
store the value reliably. Recall that lists are ordered data structures in the sense that
when elements are indexed, the next element can be found by a relative offset from
the prior one. This means that these elements are laid out contiguously in memory.
Dictionaries do not have this property because they will put values wherever they
can find memory, contiguous or not. This is because dictionaries do not rely upon
relative offsets for indexing, they rely instead on a hash function. Consider the
following,
>>> x = {0: 'zero', 1: 'one'}
>>> y = ['zero','one']
>>> x[1] # dictionary
'one'
>>> y[1] # list
'one'

Indexing both variables looks notationally the same in both cases, but the process
is different. When given a key, the dictionary computes a hash function and the
stores the value at a memory location based upon the hash function. What is a hash
function? A hash function takes an input and is designed to return, with very high
probability, a value that is unique to the key. In particular, this means that two keys
cannot have the same hash, or, equivalently, cannot store different values in the
same memory location. Here are two keys which are almost identical, but have very
different hashes.
>>> hash('12345')
3973217705519425393
>>> hash('12346')
3824627720283660249

All this is with respect to probability, though. Because memory is finite, it could
happen that the hash function produces values that are the same. This is known
as a hash collision and Python implements fallback algorithms to handle this
16 1 Basic Programming

case. Nonetheless, as memory becomes scarce, especially on a small platform, the


struggle to find suitable blocks of memory can be noticeable if your code uses many
large dictionaries.
As we discussed before, inserting/removing elements from the middle of a list
causes extra memory movement as the list maintains its invariant but this does
not happen for dictionaries. This means that elements can be added or removed
without any extra memory overhead beyond the cost of computing the hash function
(i.e., constant-time lookup). Thus, dictionaries are ideal for codes that do not need
ordering. Note that since Python 3.6+, dictionaries are ordered in the sense of the
order in which items were inserted to the dictionary. In Python 2.7, this was known
as collections.OrderedDict but has since become the default in Python
3.6+.
Now that we have a good idea of how dictionaries work, consider the inputs to
the hash function: the keys. We have mainly used integers and strings for keys, but
any immutable type can also be used, such as a tuple,
>>> x= {(1,3):10, (3,4,5,8):10}

However, if you try to use a mutable type as a key,


>>> a = [1,2]
>>> x[a]= 10
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Let us think about why this happens. Remember that the hash function guarantees
that when given a key it will always be able to retrieve the value. Suppose that it
were possible use mutable keys in dictionaries. In the above code, we would have
hash(a) -> 132334, as an example, and let us suppose the 10 value is inserted
in that memory slot. Later in the code, we could change the contents of a as in
a[0]=3. Now, because the hash function is guaranteed to produce different outputs
for different inputs, the hash function output would be different from 132334 and
thus the dictionary could not retrieve the corresponding value, which would violate
its invariant. Thus we have arrived at a contradiction that explains why dictionary
keys must be immutable.
Sets Python provides mathematical sets and corresponding operations with the
set() data structure, which are basically dictionaries without values.
>>> set([1,2,11,1]) # union-izes elements
{1, 2, 11}
>>> set([1,2,3]) & set([2,3,4]) # bitwise intersection
{2, 3}
>>> set([1,2,3]) and set([2,3,4])
{2, 3, 4}
>>> set([1,2,3]) ^ set([2,3,4]) # bitwise exclusive OR
{1, 4}
>>> set([1,2,3]) | set([2,3,4]) # OR
{1, 2, 3, 4}
>>> set([ [1,2,3],[2,3,4] ]) # no sets of lists
1.1 Basic Language 17

(without more work)


Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: unhashable type: 'list'

Note that since Python 3.6+, keys can be used as set objects, as in the following,
>>> d = dict(one=1,two=2)
>>> {'one','two'} & d.keys() # intersection
{'one', 'two'}
>>> {'one','three'} | d.keys() # union
{'one', 'two', 'three'}

This also works for dictionary items if the values are hashable,
>>> d = dict(one='ball',two='play')
>>> {'ball','play'} | d.items()
{'ball', 'play', ('one', 'ball'), ('two', 'play')}

Once you create a set, you can add individual elements or remove them as follows:,
>>> s = {'one',1,3,'10'}
>>> s.add('11')
>>> s
{1, 3, 'one', '11', '10'}
>>> s.discard(3)
>>> s
{1, 'one', '11', '10'}

Remember sets are not ordered and you cannot directly index any of the constituent
items. Also, the subset() method is for a proper subset not a partial subset. For
example,
>>> a = {1,3,4,5}
>>> b = {1,3,4,5,6}
>>> a.issubset(b)
True
>>> a.add(1000)
>>> a.issubset(b)
False

And likewise for issuperset. Sets are optimal for fast lookups in Python, as in
the following,
>>> a = {1,3,4,5,6}
>>> 1 in a
True
>>> 11 in a
False

which works really fast, even for large sets.

1.1.6 Loops and Conditionals

There are two primary looping constructs in Python: the for loop and the while
loop. The syntax of the for loop is straightforward:
18 1 Basic Programming

>>> for i in range(3):


... print(i)
...
0
1
2

Note the colon character at the end. This is your hint that the next line should be
indented. In Python, blocks are denoted by whitespace indentation (four spaces
is recommended) which makes the code more readable anyway. The for loop
iterates over items that provided by the iterator, which is the range(3) list
in the above example. Python abstracts the idea of iterable out of the looping
construction so that some Python objects are iterable all by themselves and are just
waiting for an iteration provider like a for or while loop to get them going.
Interestingly, Python has an else clause, which is used to determine whether or
not the loop exited with a break3 or not.
>>> for i in [1,2,3]:
... if i>20:
... break # won't happen
... else:
... print('no break here!')
...
no break here!

The else block is only executed when the loop terminates without breaking.
The while loop has a similar straightforward construct:
>>> i = 0
>>> while i < 3:
... i += 1
... print(i)
...
1
2
3

This also has a corresponding optional else block. Again, note that the presence
of the colon character hints at indenting the following line. The while loop will
continue until the boolean expression (i.e., i<10) evaluates False. Let us consider
boolean and membership in Python.
Logic and Membership Python is a truthy language in the sense that things are
true except for the following:
• None
• False
• zero of any numeric type, for example, 0, 0L, 0.0, 0j.
• any empty sequence, for example, ”, (), [].

3 There is also a continue statement which will jump to the top of the for or while loop.
Random documents with unrelated
content Scribd suggests to you:
in my state of mind, I felt compelled to watch and wait. Yet,
if I had had a weapon ready to my hand at that moment, I
verily believe that I must have thrown myself upon this
arrogant cad, and mercilessly killed him.

The manner in which his hat was set upon his head, slightly
askew, in the manner of the London “’Arry,” and his over-
burdening mannerism, were in themselves sufficient to
show the type of lover my wife cultivated. As I stepped
softly behind them in the gloom, I told myself that she must
leave my house that night, or I should. I felt in my throat a
choking sensation, for I had loved her so fervently that this
discovery of her falseness had utterly unnerved me, and
even in those moments of fierce anger and hatred I confess
that tears welled in my eyes. Ella was the only woman I had
ever loved, yet she who had taken her marriage vows only
a few short months before had already discarded me for
this overdressed idiot, who would be termed in vulgar
parlance a “bounder.”

Perhaps he did not know her to be married. This thought


took possession of me. When their quarrel ended it became
manifest that Ella herself was endeavouring to fascinate and
hold him, just as she had charmed me, by the softness of
her speech, her exquisite grace, and her wonderful beauty.
She spoke quietly, with her dainty finger-tips laid lightly
upon his arm, while he listened, gazing earnestly into her
face, enchanted.

To-night, I told myself, the bonds uniting me to Ella should


be for ever severed. I remembered the many occasions
when she had been absent, visiting imaginary friends; I
recollected the evening she brought home the violets and
preserved them carefully in water until they smelt so faint
that she was compelled to throw them away; I had not
forgotten the fact that blades of grass did not grow in the
squalid, overcrowded streets of modern Camberwell. I
glanced around at the grass on every side. Perhaps she
frequented that place, and took clandestine walks daily with
her lover beneath those leafless trees. The thought
provoked my bitter hatred, and I know not how I refrained
from facing the pair. I managed, however, to hold myself
back, watching them exchange a tender farewell at the gate
that led into Kensington High Street, next the Palace Hotel,
and while the man raised his hat politely and, turning,
walked away in the direction of Knightsbridge, Ella, her face
radiant and happy, bowed and set out homeward in the
opposite direction.

Beneath the lamp in the gateway I had, in those brief


seconds, obtained a glimpse of his face. It was that of a
young man of about two-and-twenty, with strongly marked
features, fair-haired, and of quite a different type than I had
conjectured. The features were rather refined, by no means
those of a cad, but rather those of a well-bred young idler,
who affected the dress and manners of that class of youths
who frequent the Café Monico on Sunday evenings, the
slaves of the counter.

Once he glanced back to Ella, but she did not turn; then he
went on and was lost in the darkness, while I followed my
wife’s neat figure through the bustling throng of foot-
passengers.
Chapter Twenty Two.
To Err is Human.

Instead of keeping behind her straight home, I turned from


the main road, and with my mind full of gloomy thoughts,
wandered about the dark, quiet thoroughfares in the
neighbourhood of Campden Hill until, having walked for
over an hour undecided how to act, I awoke to a
consciousness that I was before my own house.

When I entered I opened a telegram lying on the hall table,


and found it was from Lord Warnham, stating that he was
leaving the Premier’s suddenly, and asking me to call at
Berkeley Square at six. It was then a quarter to six, and I
saw that even by cab I must be ten minutes late for the
appointment.

“Has my wife returned, Juckes?” I asked my faithful man,


who stood ready to relieve me of hat and coat.

“Yes, sir. She returned an hour ago, and is now in the


drawing-room.”

My first impulse was to return to Berkeley Square without


seeing her, but unable longer to bear the suspense, I
allowed Juckes to take my things, and entered the room,
where she awaited me.

“Ah! Geoffrey!” she exclaimed, jumping to her feet with an


expression of joy, and coming forward to meet me. “I
expected you home long ago, dearest.” And she raised her
face for the habitual kiss.
“Oh,” I said coldly, placing her away from me without
caressing her. “Have you been home long?”

“A long, long time,” she answered, regarding my coldness


with unfeigned surprise.

“Where have you been to-day?” I inquired, rather sharply,


taking up a position on the hearthrug, with my back to the
bright wood fire.

“This morning I went to Mr Praga’s studio in Hornton Street,


and gave him a sitting. He is painting my portrait for the
Academy, you know.”

“Yes,” I answered. “He told me so at the club the other day.


Where else have you been?”

“Why are you so anxious to have a complete record of my


doings?” she asked, pouting. “You seem absurdly
suspicious.”

I smiled bitterly. Since her return she had exchanged her


tailor-made gown for a handsome dinner-dress, and wore
as her only ornament a string of pearls, my wedding gift.
She stood gazing at me with her dark blue eyes wide-open,
and brows arched in well-feigned reproach.

“You did not return to lunch,” I said quietly.

“No, I went to Pont Street,” she answered. “Mother was so


fearfully upset.”

“Why?”

“Last night she detected Helmholtz in the act of opening a


letter he had taken from the postman. It contained a
cheque, and she was compelled to discharge him at a
moment’s notice.”

“I understood he was quite a model servant,” I said, in


genuine surprise at this latest development. To me it was
astounding that a shrewd officer like Renouf should have
thus allowed himself to be caught napping.

“Mother thought most highly of him,” she went on. “But it


now appears that for the past few weeks she has had
suspicions that her letters were being tampered with, for
two cheques sent by tenants for rent have been stolen.”

“I never thought very much of him,” I said.

“Neither did I,” she declared. “He had such a silent, cunning
way, and moved so softly, that dozens of times when I have
turned suddenly I have been quite startled to find him
standing close to me. I’m glad mother has got rid of him.
She packed him off bag and baggage.”

“Did he protest his innocence?”

“No. He treated her with cool indifference, placed his things


in his portmanteau leisurely, hailed a cab, and went off
without asking for his wages.”

I was silent. The reason Renouf should descend to steal


cheques was inexplicable. One thing, however, appeared
clear, namely, that he had taken an unusual interest in the
nature of Mrs Laing’s correspondence. To me it was a
matter for congratulation that as he had been detected by
his mistress and discharged, he could not cast upon me the
blame for his betrayal.

“What did you do after lunch?” I at last inquired, returning


to my charge.
“I went shopping,” she replied, smiling.

“With whom?”

“Alone.”

“Were you alone the whole time?” I inquired, regarding her


intently.

Her lips quivered slightly and her glance wavered. “Yes,” she
answered, “I did not meet anyone I knew.”

“That is a lie, Ella!” I cried.

“It is not,” she stammered, pale and agitated. “I have told


you the truth.”

“To prevaricate is utterly useless,” I said angrily. “I followed


you through Kensington Gardens, where you were walking
with your lover. I—”

“My lover?” she cried hoarsely, in dismay. “He—he is not my


lover. I had never seen him before!”

“Then by your own admission you have abandoned all


respect for me and yourself. You are addicted to strolling
alone with any idiot who flatters you.”

“I swear I do not,” she retorted. “You misjudge me entirely.”


And she placed her trembling hand upon my arm.

But I shook it off wrathfully, saying, “I have discovered the


truth, alas! too late. While making pretence to love me you
prefer the society of other men. I was a blind fool, or I
should have discovered the fact, plain to everybody else,
that Ogle was your lover, and that you mourned for him
when he met the fate he so justly deserved.”
“He never uttered one word of love to me, Geoffrey,” she
protested. “How can you make such horrible charges
against me when I love you so dearly,” she cried, bursting
into a torrent of tears.

“Because!” I said, with emphasis, “because I have myself


followed you this evening. Surely Kensington Gardens is not
the spot where a wife should take recreation, unless
clandestinely, as you have done! No, this is not the first
occasion you have lied to me, Ella; but it shall be the last.”

“The last!” she gasped, glancing up at me. “What do you


mean?”

“I mean that I can have no further confidence in you, and


that we are better apart.”

“You don’t intend to leave me. Surely you would never be


so cruel, Geoffrey. It would kill me.”

“I have loved you, Ella,” I said hoarsely, after a pause, brief


and full of suspense. “No man could have loved a woman
with a passion more tender than I have done, but now that
I have discovered how basely I have been deceived, my
affection has turned to hatred.”

“You hate me!” she wailed. “Ah, no, you cannot—you shall
not,” she cried, as, rushing towards me, she threw both
arms around my neck, and, notwithstanding my efforts to
avert her, pressed her tear-stained face to mine.

Roughly I unclasped her arms and cast her from me,


saying,—

“I have resolved. Nothing will cause me to reconsider my


decision. We must part.”
“It is not like you, Geoffrey, to be cruel to a woman,” she
said reproachfully, standing before me. “I admit I have
acted foolishly, but that man you saw was not my lover. I
care for no one except your own dear self.”

“Terms of endearment are unnecessary,” I answered


impatiently, turning from her. “Such expressions from one
who has so grossly deceived me are absolutely nauseating.
I have striven for your social advancement and have loved
you dearly, but from this moment you are my wife only in
name.”

She buried her face in her hands and was seized by a fit of
hysterical sobbing. All her self-control had vanished at the
instant she realised that I know the truth, and she now
stood before me bent and penitent.

“Forgive me,” she whispered earnestly. “Forgive me,


Geoffrey.”

“No,” I answered, with firmness. “I cannot trust you.”

“Overlook this incident, and I will never again give you


cause for jealousy,” she exclaimed. “I will do anything you
ask, only have patience with me.”

“I have already had patience,” I answered. “Yet, deceived as


I am daily, we can live together no longer.”

“But I love you,” she declared, with fierce earnestness,


fixing her fathomless eyes upon me. “If I lose you I shall kill
myself.”

“It is your own fault entirely,” I said. “You have chosen to


act in this manner, and whatever are the consequences they
are of your own seeking. I suppose you will tell me next
that this man who was with you compelled you to meet
him.”

“That is the absolute truth,” she faltered.

“Ah, always the same lame tale,” I observed in disgust. “I


have not forgotten that night at ‘The Nook’ when I watched
you walking with Beck. No, Ella. There is some strange
mystery about it all that I don’t like. You pretend to love
me; but you have some ulterior motive.”

“There is a mystery, it is true,” she admitted, her eyes


dimmed with tears. “A mystery so strange and startling that
when you know the truth you will stand aghast and
dumbfounded. But with its elucidation you will have
knowledge of how I have suffered and striven for your sake;
therefore I can only pray that the revelations that must
accrue may be hastened, for, although to-day you regard
me as base and deceitful, you will then learn how much one
woman has endured and sacrificed because she loved you.”

“Then we must part until this mystery is cleared up,” I said


calmly, my heart full of grief. “You refuse to take me, your
husband, into your confidence, therefore I can place no
further reliance in your word.”

“Think,” she cried, clutching my arms convulsively. “Why


should the happiness of both of us be wrecked by a mere
misunderstanding?”

“A misunderstanding!” I echoed. “It is assuredly more than


that.”

“No,” she answered, endeavouring to stifle her sobs. “You


misunderstand me, believing me false to you, whereas I am
acting solely in our mutual interests.”
“To walk alone with a stranger is surely not acting in your
husband’s interests,” I observed bitterly.

“Ah, you are mistaken,” she said quickly. “When all is


explained you will regret the cruel words you have uttered
this evening.”

“Have I, then, no cause to object to your acquaintance with


this man?” I inquired, looking sharply at her.

“None whatever. He is neither my lover nor my friend.”

“What is his name?”

“I do not know. He did not tell me,” she replied.

“Was this the only occasion you had met?”

“It was.”

“He spoke to you casually in the street, I suppose?”

“No, we met by appointment at Victoria Station,” she


answered quite frankly.

“By appointment! Then you knew him!”

“No, our meeting was arranged by a third person. It was by


no means of an amatory character, I assure you.”

“What was its object?” I asked.

Slowly she shook her head. “I cannot tell you without


relating to you facts which I dare not yet divulge.”

“Ah! as I thought,” I cried in anger. “You refuse always to


explain. As each week passes the mystery surrounding you
increases.”
“Unfortunately I cannot prevent it,” she answered in a low,
earnest tone. “Before we married I told you plainly that I
intended to seek the truth of the conspiracy against
Dudley’s life, and you did not object.”

“Why not leave that wretched affair to the police and secure
our own happiness?” I urged.

“Because the police are powerless. They can have no clue.”

“Is it then absolutely necessary that you should attain this


end?” I inquired dubiously. “Are you ready to sacrifice your
own home and husband in order to ascertain the truth
regarding a crime?”

“Yes, it is absolutely imperative,” she replied emphatically.


“Before perfect happiness can be ours we must both be
aware of the causes which led to Dudley’s sudden death.
Towards that end I am striving, and knowing what I do, I
am regardless of your suspicions and your cruel words. If
we part—well, it will be you who one day will be filled with
bitter regret; and as for me, I shall not pause in my
merciless quest.”

Often she had told me that to ascertain the true cause of


Dudley’s death was, next to her duty as my wife, her main
object in life, and these words, uttered with an earnestness
that was genuine, bore out her most frequent declarations.
Glancing at the facts as a whole, it was not surprising that I
should have suspected Dudley of having been her lover,
whose death she intended to avenge.

In silence and hesitation I paced the room that she had


furnished with such exquisite taste. A dozen times she
asked forgiveness, but no word passed my lips. She stood
motionless, her head bent in submission, her hands clasped
before her, awaiting my decision.
Her pale, tear-stained face betrayed signs of a terrible,
breathless suspense, she fearing that I intended to cast her
off, while I could not bring myself to any firm belief that her
declarations of affection were genuine. Between us there
yawned a gulf of darkness and mystery which hourly grew
wider and more impassable.

“Tell me that you’ll still be patient and wait,” she implored at


last. “Surely you can see how intensely I love you and how
utterly aimless will be my life if we part.”

“This mystery is, I confess, Ella, driving me to distraction,” I


said, halting at last before her. “Cannot you confide in me? I
will preserve silence, I promise.”

“No, no,” she gasped in fear. “I dare not.”

Her attitude was one of deep dejection, yet I could not fail
to notice, even at this moment of her abject despair, how
beautiful she was. But a look of unutterable terror was in
her deep blue eyes, and upon her handsome features was
an expression as though, dreading exposure, she were
haunted by some terrible ghost of the past.

“You told me this once before,” I said gravely, “and I trusted


you. To-day I have discovered my confidence ill-placed.”

“Trust me once again,” she cried hoarsely. “Only once, and I


will show you ere long that your suspicions are utterly
without foundation.”

I took another turn up and down the drawing-room, my


hands clasped behind my back, my gaze fixed upon the
carpet. I was still undecided.

With a sudden impulse she rushed forward, and flinging her


warm arms about my neck, kissed me, next second bursting
into tears and burying her face upon my shoulder. My hand
unconsciously stroked her hair, and, bending, I pressed my
lips upon her soft cheek.

Then she knew that I had forgiven, and holding back her
sobs with difficulty, raised her face, and kissing me
passionately, thanked me in a low, broken voice, assuring
me that I should never regret the step I had taken.

During half-an-hour we remained together, she full of love


and confidence, I admiring and hopeful. I was glad I had
not acted rashly, nor left her as I had intended, and as we
went in to dinner arm in arm, we laughed together, joyous
in each other’s love.

After we had eaten, I smoked a cigarette and lingered as


long as possible, happy with my well-beloved; then kissing
her fondly, I was compelled to take a hansom to Berkeley
Square, promising her to return at the earliest possible
moment, and expressing confidence that our love would last
always.

The Earl, grumbling at my tardy arrival, was busy in his


library with a number of important dispatches relating to
our affairs in the East. When he had expressed displeasure
that I had not been waiting to receive him, he added,—

“But there, I suppose now you are married, Deedes, your


wife is exacting; they always are. She likes you to dine with
her, eh?”

“Yes,” I admitted, smiling. “I did dine at home.”

“Ah, I thought so,” snapped the shrewd old Minister. “A good


dinner and your wife’s smiles were of more consequence to
you than England’s prestige with the Sultan,—oh?”
I made no answer to this sarcasm, but began busying
myself with the correspondence, packing it away in the
dispatch-bag and sealing it for delivery to Hammerton, the
messenger, who was waiting in an adjoining room ready to
take it to Constantinople.

Not until eleven o’clock was I able to get away from


Berkeley Square, and leaving the aged statesman alone,
deeply immersed in the puzzling applications for advice of
all sorts from Her Majesty’s representatives at the various
Courts of Europe, I drove back to Phillimore Gardens.

On arrival home my first question of Juckes was whether


Ella was in the drawing-room.

“No, sir. Madame is out, sir.”

“Out! When did she go out?”

“About an hour after you had left, sir,” replied the man.
“She has gone into the country, I believe.”

“Into the country? What makes you think so?”

“Because she put on her travelling dress, and took two


trunks with her,” he answered. “Roberts, her maid, says she
packed the boxes herself three days ago.”

“Did she say where she was going?” I inquired breathlessly.

“No, sir. She left no message with anyone.”

Entering the drawing-room with my overcoat still on, I


noticed, lying upon her little rosewood escritoire, a note
addressed to me.
Eagerly I took it up, tore it open, and read its contents.
There were only a few hurriedly-scrawled words—a brief
and formal farewell.

“You cannot trust me,” she wrote, “therefore we are best


apart. Do not attempt to follow me, for you cannot find me.
Do not think ill of me, for even if I have wronged and
deceived you, I have, nevertheless, been your friend.” It
commenced formally, without any endearing term, and
concluded abruptly with the two words, “Your Wife.”

For a few moments I stood with it in my hand, staring at it


in blank amazement. Then it occurred to me that in that
very escritoire she kept all her correspondence, and it was
more than probable that I might learn the truth from some
of the letters therein contained.

I endeavoured to open it, but it was, as usual, locked. She


had taken the key. In my sudden excitement I called to
Juckes to bring a hammer, and with a few sharp blows
broke open the sloping, leather-covered top, finding a
number of letters addressed in unfamiliar handwriting.

One, larger than the rest, crumpled, dirty and worn, as if it


had reposed in someone’s pocket for a long period, I took
out, and eagerly opened beneath the soft-shaded lamp.

“My God!” I cried aloud, scarcely able to believe my own


eyes, when next instant I realised the terrible truth. “My
God! I had never suspected this!”
Chapter Twenty Three.
A Terrible Truth.

Ella’s cold, formal adieu stunned me. I stood open-


mouthed, petrified. We had parted on the best of terms, she
kissing me affectionately, and with wifely solicitude bidding
me hasten back; yet in my absence she had departed,
evidently carrying out some pre-arranged plan. Her maid,
Roberts, had noticed her packing her trunks three days
before, therefore it was certain that she meant to desert me
as soon as opportunity offered.

Unaccountable and astounding as was her sudden flight, the


discovery I had made among the papers in her escritoire
was even more amazing. It held me stupefied and aghast.

The paper I held in my hand was the original of the secret


convention between England and Germany; the document
which had been stolen from me, transmitted by telegraph to
the Russian Foreign Office, and had nearly caused a terrible
and disastrous European war.

When I took it from among the letters and saw its neat,
formal writing and sprawly signatures, I gazed upon it in
blank amazement, unable at first to realise the startling
truth. There was, however, no room for doubt. It was the
actual document which had been so ingeniously purloined,
for it reposed in the escritoire still in its official envelope.
The great black seal affixed by the Earl of Warnham had
been broken, and both envelope and document had the
appearance of having at some time or other been folded
small, besides being sadly crumpled.
Beneath the shaded light I examined the envelope carefully,
and detected a faint carmine streak upon it; then, placing it
to my nostrils, found that it exuded a stale odour of
sampaguita. In an instant the truth was plain. The pink
discolouration had been caused by rouge; the scent was
Ella’s favourite perfume, which she always procured from
Paris. No doubt the document had been carried for a
considerable period in her pocket for safety, and become
crumpled, as papers will if carried in a woman’s dress. While
the envelope might easily have absorbed the odour of that
unmistakable perfume from her handkerchief, the streak of
rouge puzzled me, for I had never suspected her of an
artificial complexion, nor had I ever seen the hare’s foot and
carmine among her toilet articles.

“Tell Roberts I wish to speak to her,” I said, turning to


Juckes, who had stood by in silence, puzzled at my strange
action of breaking the top of the escritoire.

He obeyed, and in a few moments the neat, dark-eyed maid


entered.

“Roberts,” I exclaimed, “I want you to tell me something.


Does my wife use any carmine to give artificial colour to her
cheeks?”

“Oh, no, sir,” the girl assured me. “Madame is very averse
to the use of such things. Once or twice, when she has been
going out at night, and looked unusually pale, I have
suggested a little additional colour, but she has always
refused.”

“Did she have any rouge or anything of that sort in her


possession?” I inquired.

“No, sir, I am quite certain she hadn’t.”


“Why are you so confident?”

“Because only the other day, when I was ill with a sick
headache, madame urged me to use some colour, as my
face was so pale. Visitors were coming, she said, and she
didn’t want me to look like a ghost. I told her that I had no
carmine, and she remarked that she had none, therefore
nothing could be done.”

“When did my wife pack those two trunks she took with her
this evening?”

“Last Monday, sir,” the girl answered, slowly twisting her


befrilled apron in her hands. “She received a note by boy-
messenger, and immediately set about packing the boxes.”

“Did she tell you anything?” I asked, adding confidentially,


“I have reason to believe that my wife has left us, therefore
anything you tell me may assist me in tracing her.”

The girl glanced at me in genuine surprise.

“Do you mean, sir, that madame has—has run away?” she
gasped.

“No—well, not exactly,” I stammered. “But did she tell you


anything?”

With eyes downcast the girl paused in hesitation, answering


at last, “She didn’t actually tell me anything.”

“But what do you know about her intentions?”

“Nothing,” she answered. Then, after a pause, she added,


“Well, to tell you the truth, sir, I had suspicions.”
“Of what? Do not fear to speak because I am her husband,”
I said reassuringly. “I may as well know the worst at once.”

“She used frequently to receive notes from a gentleman.


They were brought by a commissionaire or by a man-
servant, who waited for the answer. When they came I
always knew that on the following day she would be absent
many hours.”

“You believe that she met this mysterious individual—eh?” I


asked huskily.

“Yes, for she always told me never to admit to you that she
had been long absent. Therefore I had suspicion that she
met somebody clandestinely.”

“What was his name?”

“I have never been able to ascertain. Once I glanced at a


note lying on madame’s dressing-table. It merely
announced the writer’s intention to attend Lady Pearson’s
‘at home,’ and was signed ‘X.’”

“Well,” I said hoarsely, after a long silence. “What else?”

“Nothing,” she replied. “That is all I know, sir.”

“Has my wife taken her jewels?” I inquired.

“No. She has left her jewel-case unlocked, but everything is


there. She has even left behind her wedding-ring.”

“Her wedding-ring!” I echoed, astounded and dismayed.


“Then she has discarded me completely.”

“Unfortunately it appears so, sir,” the girl observed gravely.


“Very well, Roberts,” I said in a broken voice. “Thank you.
You may go.”

The girl glanced at me for an instant, with a sad, pitying


look, then turned and left, closing the door noiselessly
behind her.

Alone, I sank into the chair utterly broken down, still


holding in my nervous, trembling fingers the secret
document that secured the peace and welfare of the two
most powerful nations on earth. I had at last discovered the
hideous truth. Ella, the woman whose grace and beauty had
held me enmeshed, and whom I had loved with an intensity
of passion that was all-consuming, was, after all, base and
worthless. Although making a hollow pretence to love me,
she had cast me aside for this mysterious man who signed
himself with an initial, and who met her secretly almost
daily. I had been a blind, devoted idiot, I knew, but until I
had watched her in Kensington Gardens I had never
suspected her of infamy. It seemed, however, that she had
no sense of shame, and cared nought for my dishonour or
despair. Her perfidy was now revealed in all its painful
reality. Ella, whom I had always regarded as pure, honest
and trusting, was a woman of tarnished repute. The fact
that she had the secret convention in her possession was, in
itself, sufficient evidence that the mystery surrounding her
was deep, and of no ordinary character. Sonia had warned
me that she was my enemy, and this fact was now indeed
vividly apparent.

How she had become possessed of the stolen treaty was


inexplicable. Full well she knew all the terrible anxiety its
loss had caused me, and the sensation that its revelation
had created throughout Europe. Times without number I
had mentioned to her how anxious my chief was to recover
the original, so that our enterprising friends in St Petersburg
could have no tangible proof that it had actually existed, yet
she had given no sign that she knew anything of it, much
less that it actually reposed in my own drawing-room. I did
not fail, in those moments of my despair, to recollect that
she had been on the most intimate terms with Dudley Ogle,
the man suspected to have been in the service of the Tzar’s
Government, and as I sat in wonderment it became
gradually impressed upon me that through those many
months I had been basely tricked, and that Ella herself,
charming and ingenuous as she seemed, was actually a
secret agent of the enemies of England.

Several facts that I recollected combined to produce this


startling belief. Because of my confidential position as
secretary to the Earl of Warnham, it was apparent that Ella,
with the assistance of my whilom friend Dudley and the
encouragement of her mother, had conspired to hold me
beneath her spell. She had become my wife, not because
she had ever loved me, but because she could feign
affection or hatred with equal impunity, and had some
ulterior motive in obtaining my confidence. Her firm resolve
to ascertain the true facts regarding Dudley’s mysterious
end showed plainly that if they were not lovers they had
acted in complete accord, and what was more likely than
that he, having stolen the secret convention, had on that
memorable night at “The Nook” handed it to her, the
instigator of the ingenious theft. Yet an hour or so later he
died from some cause that neither doctors nor police had
been able to determine.

To her, the tragic occurrence was a mystery, as to all, and


her refusal to render me any explanation of her suspicious
actions was, I now saw, quite natural. Held beneath the iron
thraldom of her masters in St Petersburg, she dared not
utter one word; hence I had remained in the outer darkness
of doubt and ignorance.
However it might be, one thing was certain. She had been
unexpectedly parted from me, either by choice or
compulsion. Perhaps it was that to pose as my wife was no
longer necessary; yet if she were actually a spy, was it not
curious that in departing she should overlook this
document, of which the Ministry at St Petersburg were so
anxious to possess themselves.

Again, as I sat alone before the cheerless grate, I reflected


that if she were in the pay of Russia, surely Monsieur
Grodekoff, the Ambassador, would have been acquainted
with her. Besides, what reason could Renouf have had in
making such careful inquiries, or why did Paul
Verblioudovitch discredit the truths uttered by Sonia and
urge me to marry the woman I loved? Nevertheless if, as I
supposed, my position in the Foreign Office had caused me
to be the victim of a clever and deeply-conceived
conspiracy, it was scarcely surprising that the Tzar’s
representative should disclaim all knowledge of the sweet-
faced agent, or that Paul had praised her and cast obloquy
upon Sonia in order that their plans, whatever they were,
should be achieved. Of the actions of Renouf, and his
strange disregard for detection, I could form no satisfactory
conclusion. All I knew was that Ella’s career had been an
unscrupulous and inglorious one, and that she had cast me
aside as soon as her infamous ends had been attained.

The only person who could elucidate the mystery was


Sonia, the pretty girl who had been denounced by Renouf
as a murderess, and who was now in hiding in far-off
Russia, in some out-of-the-world place where I could never
hope to find her. If she were clever enough to elude the
combined vigilance of the detective force of Europe, as
undoubtedly she had done, there was but little hope that I
could ever run her to earth.
The mystery had, by Ella’s flight, been increased rather than
explained, for the more I pondered the more deeply-rooted
became the conviction that she had decamped because she
had cause to fear some strange development that would
lead to her exposure and shame.

After a time I roused myself, and taking from the broken


escritoire the other letters it contained, five in number,
examined them eagerly beneath the light.

All were in the same hand, a heavy masculine one, written


evidently with a quill. One by one I read them, finding that
they contained appointments, which fully bore out her
maid’s suspicions.

“My dear Ella,” one ran, “to-morrow I shall be on the


departure platform at King’s Cross Station at 11:30. I have
good news for you. Come.—X.”

Another regretted the writer’s inability to keep an


appointment, as he had been called unexpectedly to Paris,
and was compelled to leave by the night mail from Charing
Cross. He, however, promised to return in three days, and
gave her the Grand Hotel as his address if she found it
necessary to telegraph.

Strangely enough, the letters contained no endearing terms


either at their commencement or conclusion. Formal and
brief, they all related to appointments at various places in
London where two persons might meet unnoticed by the
crowd, and all were signed by the single mysterious initial. I
stood with them in my hand for a long time, puzzled and
hesitating, then placing them carefully in my pocket,
together with the secret document I had so unexpectedly
unearthed, I crammed on my hat and hastily drove to Pont
Street.
The house was in darkness, save for a light in the
basement, and in answer to my summons, after a lapse of
some minutes a tall, gaunt, woman in rusty black appeared
in the area below.

I was surprised at being thus met by a stranger, but


inquired for Mrs Laing.

“Mrs Laing ain’t at ’ome, sir,” answered the woman, looking


up and speaking with a strong Cockney twang.

“Not at home?” I exclaimed, surprised. “Where is she?”

“She’s gone abroad somewheres, but I don’t know where,”


the woman answered. “She’s sold all her valuables,
discharged the servants, and left me ’ere as ’ouse-keeper.”

“When did she go?” I asked.

“This morning. I answered an advertisement in the


Chronicle yesterday, and entered on my duties ’ere to-day.
Quick, ain’t it?”

The rapidity of her engagement I was compelled to admit,


but proceeded to make further inquiry whether Mrs Laing’s
daughter had been there.

“No, sir. No one’s been ’ere to-day, except a foreign-looking


gentleman who asked if madame had left, and when I said
that she had, he went away quite satisfied.”

“What kind of man was he?”

“Tall and thin, with a longish dark beard.”

The description did not correspond with anyone of my


acquaintance; therefore, after some further questions
regarding Mrs Laing’s mysterious departure, I was
compelled to wish the worthy woman good evening. She
knew nothing of Mrs Laing’s movements, not even the name
of the terminus to which she had driven, such pains had
Ella’s mother taken to conceal the direction in which she
intended to travel.

Some secret undoubtedly existed between mother and


daughter; its nature held me perplexed and bewildered.
Chapter Twenty Four.
Strictly Confidential.

The early morning was dry, frosty, but starless. The clock of
that fashionable temple of Hymen, St George’s, Hanover
Square, was slowly chiming three as I alighted from a cab
at the corner of Mount Street, and walking along Berkeley
Square, ascended the steps of the Earl of Warnham’s great
mansion, and rang its ponderous bell. The place was severe
and gloomy enough by day, but in the silence and darkness
of the night its exterior presented a forbidding, almost
ghostly appearance. It was an unusual hour for a call, but,
knowing that a porter was on duty always, and that
dispatches frequently arrived during the night, I had no
hesitation in seeking an interview.

In a few moments there was a grating sound of bolts drawn


back, a clanking of chains, and the heavy door was slowly
opened by the sleepy man, who, with a word of recognition,
at once admitted me. Walking across the great square hall;
warmed by a huge, roaring fire, I passed down the passage
to the Earl’s study and rapped at the door, receiving an
impatient permission to enter.

The Minister for Foreign Affairs was sitting at his table


where I had left him, with an empty tea-cup at his side,
resting his pale, weary brow upon his hand and writing
dispatches rapidly with his scratchy quill. His fire was nearly
out, the pair of candles, in their heavy, old-fashioned silver
candlesticks that stood upon his writing-table, had burned
down almost to their sockets, and the strong smell of burnt
paper that pervaded the book-lined den, showed that, with
Welcome to our website – the ideal destination for book lovers and
knowledge seekers. With a mission to inspire endlessly, we offer a
vast collection of books, ranging from classic literary works to
specialized publications, self-development books, and children's
literature. Each book is a new journey of discovery, expanding
knowledge and enriching the soul of the reade

Our website is not just a platform for buying books, but a bridge
connecting readers to the timeless values of culture and wisdom. With
an elegant, user-friendly interface and an intelligent search system,
we are committed to providing a quick and convenient shopping
experience. Additionally, our special promotions and home delivery
services ensure that you save time and fully enjoy the joy of reading.

Let us accompany you on the journey of exploring knowledge and


personal growth!

textbookfull.com

You might also like