100% found this document useful (6 votes)
52 views

Get (Ebook) Python Data Analysis Numpy, Matplotlib and Pandas by Bernd Klein PDF ebook with Full Chapters Now

The document provides information about various ebooks related to Python data analysis, focusing on libraries such as NumPy, Matplotlib, and Pandas. It highlights the importance of these tools in data science and numerical computing, emphasizing Python's growing popularity as an alternative to MATLAB. Additionally, it includes tutorials and examples for using NumPy for numerical operations and data manipulation.

Uploaded by

nugentipkav0
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (6 votes)
52 views

Get (Ebook) Python Data Analysis Numpy, Matplotlib and Pandas by Bernd Klein PDF ebook with Full Chapters Now

The document provides information about various ebooks related to Python data analysis, focusing on libraries such as NumPy, Matplotlib, and Pandas. It highlights the importance of these tools in data science and numerical computing, emphasizing Python's growing popularity as an alternative to MATLAB. Additionally, it includes tutorials and examples for using NumPy for numerical operations and data manipulation.

Uploaded by

nugentipkav0
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 71

Download the Full Ebook and Access More Features - ebooknice.

com

(Ebook) Python Data Analysis Numpy, Matplotlib and


Pandas by Bernd Klein

https://ebooknice.com/product/python-data-analysis-numpy-
matplotlib-and-pandas-47505714

OR CLICK HERE

DOWLOAD EBOOK

Download more ebook instantly today at https://ebooknice.com


Instant digital products (PDF, ePub, MOBI) ready for you
Download now and discover formats that fit your needs...

Start reading on any device today!

(Ebook) Data Analysis with Python: Introducing NumPy,


Pandas, Matplotlib, and Essential Elements of Python
Programming by Rituraj Dixit ISBN 9789355510655,
9355510659
https://ebooknice.com/product/data-analysis-with-python-introducing-
numpy-pandas-matplotlib-and-essential-elements-of-python-
programming-45347694
ebooknice.com

(Ebook) Python Data Analytics with Pandas, NumPy and


Matplotlib, 2nd Edition by Fabio Nelli ISBN 9781484239131,
148423913X
https://ebooknice.com/product/python-data-analytics-with-pandas-numpy-
and-matplotlib-2nd-edition-7198962

ebooknice.com

(Ebook) Python Data Analytics: With Pandas, NumPy, and


Matplotlib by Nelli, Fabio ISBN 9781484239124,
9781484239131, 1484239121, 148423913X
https://ebooknice.com/product/python-data-analytics-with-pandas-numpy-
and-matplotlib-11712292

ebooknice.com

(Ebook) Python Data Analytics: With Pandas, NumPy, and


Matplotlib, 3rd Edition by Fabio Nelli ISBN 9781484295311,
1484295315
https://ebooknice.com/product/python-data-analytics-with-pandas-numpy-
and-matplotlib-3rd-edition-51978758

ebooknice.com
(Ebook) Python Data Analytics: With Pandas, NumPy, and
Matplotlib, 3rd Edition by Fabio Nelli ISBN 9781484295311,
9781484295328, 1484295315, 1484295323
https://ebooknice.com/product/python-data-analytics-with-pandas-numpy-
and-matplotlib-3rd-edition-51983918

ebooknice.com

(Ebook) Python Data Analytics: Data Analysis and Science


Using Pandas, Matplotlib and the Python Programming
Language by Nelli Fabio ISBN 9781484209592, 1484209591
https://ebooknice.com/product/python-data-analytics-data-analysis-and-
science-using-pandas-matplotlib-and-the-python-programming-
language-38169124
ebooknice.com

(Ebook) Python Data Analytics: Data Analysis and Science


Using Pandas, Matplotlib and the Python Programming
Language by Nelli Fabio ISBN 9781484209592, 1484209591
https://ebooknice.com/product/python-data-analytics-data-analysis-and-
science-using-pandas-matplotlib-and-the-python-programming-
language-38180776
ebooknice.com

(Ebook) Python Data Analytics: Data Analysis and Science


Using Pandas, Matplotlib and the Python Programming
Language by Nelli Fabio ISBN 9781484209592, 1484209591
https://ebooknice.com/product/python-data-analytics-data-analysis-and-
science-using-pandas-matplotlib-and-the-python-programming-
language-38180778
ebooknice.com

(Ebook) Python for Data Analysis. Data Wrangling with


Pandas, NumPy, and IPython by Wes McKinney ISBN
9781491957660, 1491957662
https://ebooknice.com/product/python-for-data-analysis-data-wrangling-
with-pandas-numpy-and-ipython-6731100

ebooknice.com
Data
Analysis

Numpy, Matplotlib and Pandas

by
Bernd Klein

bodenseo
© 2021 Bernd Klein

All rights reserved. No portion of this book may be reproduced or used in any
manner without written permission from the copyright owner.

For more information, contact address: [email protected]

www.python-course.eu
Python Course
Data Analysis With
Python by Bernd
Klein
Numpy Tutorial ..........................................................................................................................8
Numpy Tutorial: Creating Arrays.............................................................................................17
Data Type Objects, dtype..........................................................................................................36
Numerical Operations on Numpy Arrays.................................................................................48
Numpy Arrays: Concatenating, Flattening and Adding Dimensions .......................................68
Python, Random Numbers and Probability ..............................................................................79
Weighted Probabilities..............................................................................................................90
Synthetical Test Data With Python.........................................................................................119
Numpy: Boolean Indexing......................................................................................................136
Matrix Multiplicaion, Dot and Cross Product ........................................................................143
Reading and Writing Data Files .............................................................................................149
Overview of Matplotlib ..........................................................................................................157
Format Plots............................................................................................................................168
Matplotlib Tutorial..................................................................................................................172
Shading Regions with fill_between() .....................................................................................183
Matplotlib Tutorial: Spines and Ticks ....................................................................................186
Matplotlib Tutorial, Adding Legends and Annotations..........................................................197
Matplotlib Tutorial: Subplots .................................................................................................212
Exercise ....................................................................................................................................44
Exercise ....................................................................................................................................44
Matplotlib Tutorial: Gridspec .................................................................................................239
GridSpec using SubplotSpec ..................................................................................................244
Matplotlib Tutorial: Histograms and Bar Plots ......................................................................248
Matplotlib Tutorial: Contour Plots .........................................................................................268
Introduction into Pandas.........................................................................................................303
Data Structures .......................................................................................................................305
Accessing and Changing values of DataFrames.....................................................................343
Pandas: groupby .....................................................................................................................361
Reading and Writing Data ......................................................................................................380
Dealing with NaN...................................................................................................................394
Binning in Python and Pandas................................................................................................404
Expenses and Income Example ..............................................................................................465
Net Income Method Example.................................................................................................478
3
NUMERICAL PROGRAMMING WITH
PYTHON

NUMERICAL PROGRAMMING DEFINITION


The term "Numerical Computing" - a.k.a. numerical computing or scientific computing - can be misleading.
One can think about it as "having to do with numbers" as opposed to algorithms dealing with texts for
example. If you think of Google and the way it provides links to websites for your search inquiries, you may
think about the underlying algorithm as a text based one. Yet, the core of the Google search engine is
numerical. To perform the PageRank algorithm Google executes the world's largest matrix computation.

Numerical Computing defines an area of computer science and mathematics dealing with algorithms for
numerical approximations of problems from mathematical or numerical analysis, in other words: Algorithms
solving problems involving continuous variables. Numerical analysis is used to solve science and engineering
problems.

DATA SCIENCE AND DATA ANALYSIS


This tutorial can be used as an online course on Numerical Python as it is needed by Data Scientists and Data
Analysts.

Data science is an interdisciplinary subject which includes for example statistics and computer science,
especially programming and problem solving skills. Data Science includes everything which is necessary to
create and prepare data, to manipulate, filter and clense data and to analyse data. Data can be both structured
and unstructured. We could also say Data Science includes all the techniques needed to extract and gain
information and insight from data.

Data Science is an umpbrella term which incorporates data analysis, statistics, machine learning and other
related scientific fields in order to understand and analyze data.

Another term occuring quite often in this context is "Big Data". Big Data is for sure one of the most often used
buzzwords in the software-related marketing world. Marketing managers have found out that using this term
can boost the sales of their products, regardless of the fact if they are really dealing with big data or not. The
term is often used in fuzzy ways.

Big data is data which is too large and complex, so that it is hard for data-processing application software to
deal with them. The problems include capturing and collecting data, data storage, search the data, visualization
of the data, querying, and so on.

The following concepts are associated with big data:

• volume:
the sheer amount of data, whether it will be giga-, tera-, peta- or exabytes
• velocity:
the speed of arrival and processing of data
• veracity:

4
uncertainty or imprecision of data
• variety:
the many sources and types of data both structured and unstructured

The big question is how useful Python is for these purposes. If we would only use Python without any special
modules, this language could only poorly perform on the previously mentioned tasks. We will describe the
necessary tools in the following chapter.

CONNECTIONS BETWEEN PYTHON, NUMPY, MATPLOTLIB, SCIPY AND


PANDAS
Python is a general-purpose language and as such it can and it is
widely used by system administrators for operating system
administration, by web developpers as a tool to create dynamic
websites and by linguists for natural language processing tasks.
Being a truely general-purpose language, Python can of course -
without using any special numerical modules - be used to solve
numerical problems as well. So far so good, but the crux of the
matter is the execution speed. Pure Python without any
numerical modules couldn't be used for numerical tasks Matlab,
R and other languages are designed for. If it comes to
computational problem solving, it is of greatest importance to
consider the performance of algorithms, both concerning speed
and data usage.

If we use Python in combination with its modules NumPy,


SciPy, Matplotlib and Pandas, it belongs to the top numerical
programming languages. It is as efficient - if not even more
efficient - than Matlab or R.

5
Numpy is a module which provides the basic data structures,
implementing multi-dimensional arrays and matrices. Besides
that the module supplies the necessary functionalities to create
and manipulate these data structures. SciPy is based on top of
Numpy, i.e. it uses the data structures provided by NumPy. It
extends the capabilities of NumPy with further useful functions
for minimization, regression, Fourier-transformation and many
others.

Matplotlib is a plotting library for the Python programming


language and the numerically oriented modules like NumPy and
SciPy.

The youngest child in this family of modules is Pandas. Pandas


is using all of the previously mentioned modules. It's build on
top of them to provide a module for the Python language, which
is also capable of data manipulation and analysis. The special
focus of Pandas consists in offering data structures and
operations for manipulating numerical tables and time series. The name is derived from the term "panel data".
Pandas is well suited for working with tabular data as it is known from spread sheet programming like Excel.

PYTHON, AN ALTERNATIVE TO MATLAB


Python is becoming more and more the main programming language for data scientists. Yet, there are still
many scientists and engineers in the scientific and engineering world that use R and MATLAB to solve their
data analysis and data science problems. It's a question troubling lots of people, which language they should
choose: The functionality of R was developed with statisticians in mind, whereas Python is a general-purpose
language. Nevertheless, Python is also - in combination with its specialized modules, like Numpy, Scipy,
Matplotlib, Pandas and so, - an ideal programming language for solving numerical problems. Furthermore, the
community of Python is a lot larger and faster growing than the one from R.

The principal disadvantage of MATLAB against Python are the costs. Python with NumPy, SciPy, Matplotlib
and Pandas is completely free, whereas MATLAB can be very expensive. "Free" means both "free" as in "free
beer" and "free" as in "freedom"! Even though MATLAB has a huge number of additional toolboxes available,
Python has the advantage that it is a more modern and complete programming language. Python is continually
becoming more powerful by a rapidly growing number of specialized modules.

Python in combination with Numpy, Scipy, Matplotlib and Pandas can be used as a complete replacement for
MATLAB.

6
7
NUMPY TUTORIAL

INTRODUCTION
NumPy is a module for Python. The name is an acronym for
"Numeric Python" or "Numerical Python". It is pronounced
/ˈnʌmpaɪ/ (NUM-py) or less often /ˈnʌmpi (NUM-pee)). It is an
extension module for Python, mostly written in C. This makes
sure that the precompiled mathematical and numerical functions
and functionalities of Numpy guarantee great execution speed.

Furthermore, NumPy enriches the programming language


Python with powerful data structures, implementing multi-
dimensional arrays and matrices. These data structures
guarantee efficient calculations with matrices and arrays. The
implementation is even aiming at huge matrices and arrays,
better know under the heading of "big data". Besides that the
module supplies a large library of high-level mathematical functions to operate on these matrices and arrays.

SciPy (Scientific Python) is often mentioned in the same breath with NumPy. SciPy needs Numpy, as it is
based on the data structures of Numpy and furthermore its basic creation and manipulation functions. It
extends the capabilities of NumPy with further useful functions for minimization, regression, Fourier-
transformation and many others.

Both NumPy and SciPy are not part of a basic Python installation. They have to be installed after the Python
installation. NumPy has to be installed before installing SciPy.

(Comment: The diagram of the image on the right side is the graphical visualisation of a matrix with 14 rows
and 20 columns. It's a so-called Hinton diagram. The size of a square within this diagram corresponds to the
size of the value of the depicted matrix. The colour determines, if the value is positive or negative. In our
example: the colour red denotes negative values and the colour green denotes positive values.)

NumPy is based on two earlier Python modules dealing with arrays. One of these is Numeric. Numeric is like
NumPy a Python module for high-performance, numeric computing, but it is obsolete nowadays. Another
predecessor of NumPy is Numarray, which is a complete rewrite of Numeric but is deprecated as well. NumPy
is a merger of those two, i.e. it is build on the code of Numeric and the features of Numarray.

COMPARISON BETWEEN CORE PYTHON AND NUMPY

8
When we say "Core Python", we mean Python without any special modules, i.e. especially without NumPy.

The advantages of Core Python:

• high-level number objects: integers, floating point


• containers: lists with cheap insertion and append methods, dictionaries with fast lookup

Advantages of using Numpy with Python:

• array oriented computing


• efficiently implemented multi-dimensional arrays
• designed for scientific computation

A SIMPLE NUMPY EXAMPLE


Before we can use NumPy we will have to import it. It has to be imported like any other module:

import numpy

But you will hardly ever see this. Numpy is usually renamed to np:

import numpy as np

Our first simple Numpy example deals with temperatures. Given is a list with values, e.g. temperatures in
Celsius:

cvalues = [20.1, 20.8, 21.9, 22.5, 22.7, 22.3, 21.8, 21.2, 20.9, 2
0.1]

We will turn our list "cvalues" into a one-dimensional numpy array:

C = np.array(cvalues)
print(C)
[20.1 20.8 21.9 22.5 22.7 22.3 21.8 21.2 20.9 20.1]
Let's assume, we want to turn the values into degrees Fahrenheit. This is very easy to accomplish with a
numpy array. The solution to our problem can be achieved by simple scalar multiplication:
print(C * 9 / 5 + 32)
[68.18 69.44 71.42 72.5 72.86 72.14 71.24 70.16 69.62 68.18]

9
The array C has not been changed by this expression:

print(C)
[20.1 20.8 21.9 22.5 22.7 22.3 21.8 21.2 20.9 20.1]

Compared to this, the solution for our Python list looks awkward:

fvalues = [ x*9/5 + 32 for x in cvalues]


print(fvalues)
[68.18, 69.44, 71.42, 72.5, 72.86, 72.14, 71.24000000000001, 70.1
6, 69.62, 68.18]

So far, we referred to C as an array. The internal type is "ndarray" or to be even more precise "C is an instance
of the class numpy.ndarray":

type(C)
Output: numpy.ndarray

In the following, we will use the terms "array" and "ndarray" in most cases synonymously.

GRAPHICAL REPRESENTATION OF THE VALUES


Even though we want to cover the module matplotlib not until a later chapter, we want to demonstrate how we
can use this module to depict our temperature values. To do this, we us the package pyplot from matplotlib.

If you use the jupyter notebook, you might be well advised to include the following line of code to prevent an
external window to pop up and to have your diagram included in the notebook:

%matplotlib inline

The code to generate a plot for our values looks like this:

import matplotlib.pyplot as plt

plt.plot(C)
plt.show()

10
The function plot uses the values of the array C for the values of the ordinate, i.e. the y-axis. The indices of the
array C are taken as values for the abscissa, i.e. the x-axis.

MEMORY CONSUMPTION: NDARRAY AND LIST


The main benefits of using numpy arrays should be smaller memory consumption and better runtime
behaviour. We want to look at the memory usage of numpy arrays in this subchapter of our turorial and
compare it to the memory consumption of Python lists.

11
To calculate the memory consumption of the list from the above picture, we will use the function getsizeof
from the module sys.

from sys import getsizeof as size

lst = [24, 12, 57]

size_of_list_object = size(lst) # only green box


size_of_elements = len(lst) * size(lst[0]) # 24, 12, 57

total_list_size = size_of_list_object + size_of_elements


print("Size without the size of the elements: ", size_of_list_obje
ct)
print("Size of all the elements: ", size_of_elements)
print("Total size of list, including elements: ", total_list_size)
Size without the size of the elements: 96
Size of all the elements: 84
Total size of list, including elements: 180

The size of a Python list consists of the general list information, the size needed for the references to the
elements and the size of all the elements of the list. If we apply sys.getsizeof to a list, we get only the size
without the size of the elements. In the previous example, we made the assumption that all the integer
elements of our list have the same size. Of course, this is not valid in general, because memory consumption
will be higher for larger integers.

We will check now, how the memory usage changes, if we add another integer element to the list. We also
look at an empty list:

lst = [24, 12, 57, 42]

size_of_list_object = size(lst) # only green box


size_of_elements = len(lst) * size(lst[0]) # 24, 12, 57, 42

total_list_size = size_of_list_object + size_of_elements


print("Size without the size of the elements: ", size_of_list_obje
ct)
print("Size of all the elements: ", size_of_elements)
print("Total size of list, including elements: ", total_list_size)

lst = []
print("Emtpy list size: ", size(lst))

12
Size without the size of the elements: 104
Size of all the elements: 112
Total size of list, including elements: 216
Emtpy list size: 72

We can conclude from this that for every new element, we need another eight bytes for the reference to the
new object. The new integer object itself consumes 28 bytes. The size of a list "lst" without the size of the
elements can be calculated with:

64 + 8 * len(lst)

To get the complete size of an arbitrary list of integers, we have to add the sum of all the sizes of the integers.

We will examine now the memory consumption of a numpy.array. To this purpose, we will have a look at the
implementation in the following picture:

We will create the numpy array of the previous diagram and calculate the memory usage:

a = np.array([24, 12, 57])


print(size(a))
120

We get the memory usage for the general array information by creating an empty array:

e = np.array([])
print(size(e))
96

13
We can see that the difference between the empty array "e" and the array "a" with three integers consists in 24
Bytes. This means that an arbitrary integer array of length "n" in numpy needs

96 + n * 8 Bytes

whereas a list of integers needs, as we have seen before

64 + 8 len(lst) + len(lst) 28

This is a minimum estimation, as Python integers can use more than 28 bytes.

When we define a Numpy array, numpy automatically chooses a fixed integer size. In our example "int64".
We can determine the size of the integers, when we define an array. Needless to say, this changes the memory
requirement:

a = np.array([24, 12, 57], np.int8)


print(size(a) - 96)

a = np.array([24, 12, 57], np.int16)


print(size(a) - 96)

a = np.array([24, 12, 57], np.int32)


print(size(a) - 96)

a = np.array([24, 12, 57], np.int64)


print(size(a) - 96)
3
6
12
24

TIME COMPARISON BETWEEN PYTHON LISTS AND NUMPY ARRAYS


One of the main advantages of NumPy is its advantage in time compared to standard Python. Let's look at the
following functions:

import time
size_of_vec = 1000

def pure_python_version():
t1 = time.time()

14
X = range(size_of_vec)
Y = range(size_of_vec)
Z = [X[i] + Y[i] for i in range(len(X)) ]
return time.time() - t1

def numpy_version():
t1 = time.time()
X = np.arange(size_of_vec)
Y = np.arange(size_of_vec)
Z = X + Y
return time.time() - t1

Let's call these functions and see the time consumption:

t1 = pure_python_version()
t2 = numpy_version()

print(t1, t2)
print("Numpy is in this example " + str(t1/t2) + " faster!")
0.0010614395141601562 5.2928924560546875e-05
Numpy is in this example 20.054054054054053 faster!

It's an easier and above all better way to measure the times by using the timeit module. We will use the Timer
class in the following script.

The constructor of a Timer object takes a statement to be timed, an additional statement used for setup, and a
timer function. Both statements default to 'pass'.

The statements may contain newlines, as long as they don't contain multi-line string literals.

A Timer object has a timeit method. timeit is called with a parameter number:

timeit(number=1000000)

The main statement will be executed "number" times. This executes the setup statement once, and then returns
the time it takes to execute the main statement a "number" of times. It returns the time in seconds.

import numpy as np
from timeit import Timer

size_of_vec = 1000

X_list = range(size_of_vec)
Y_list = range(size_of_vec)

15
X = np.arange(size_of_vec)
Y = np.arange(size_of_vec)

def pure_python_version():
Z = [X_list[i] + Y_list[i] for i in range(len(X_list)) ]

def numpy_version():
Z = X + Y

#timer_obj = Timer("x = x + 1", "x = 0")


timer_obj1 = Timer("pure_python_version()",
"from __main__ import pure_python_version")
timer_obj2 = Timer("numpy_version()",
"from __main__ import numpy_version")

for i in range(3):
t1 = timer_obj1.timeit(10)
t2 = timer_obj2.timeit(10)
print("time for pure Python version: ", t1)
print("time for Numpy version: ", t2)
print(f"Numpy was {t1 / t2:7.2f} times faster!")
time for pure Python version: 0.0021230499987723306
time for Numpy version: 0.0004346180066931993
Numpy was 4.88 times faster!
time for pure Python version: 0.003020321993972175
time for Numpy version: 0.00014882600225973874
Numpy was 20.29 times faster!
time for pure Python version: 0.002028984992648475
time for Numpy version: 0.0002098319964716211
Numpy was 9.67 times faster!

The repeat() method is a convenience to call timeit() multiple times and return a list of results:

print(timer_obj1.repeat(repeat=3, number=10))
print(timer_obj2.repeat(repeat=3, number=10))
[0.0030275019962573424, 0.002999588003149256, 0.002212086998042650
5]
[6.104000203777105e-05, 0.0001641790004214272, 1.904800592456013
e-05]
In [ ]:

16
NUMPY TUTORIAL: CREATING ARRAYS

We have alreday seen in the previous chapter of our Numpy


tutorial that we can create Numpy arrays from lists and tuples.
We want to introduce now further functions for creating basic
arrays.

There are functions provided by Numpy to create arrays with


evenly spaced values within a given interval. One 'arange' uses a
given distance and the other one 'linspace' needs the number of
elements and creates the distance automatically.

CREATION OF ARRAYS WITH EVENLY SPACED VALUES

ARANGE
The syntax of arange:

arange([start,] stop[, step], [, dtype=None])

arange returns evenly spaced values within a given interval. The values are generated within the half-open
interval '[start, stop)' If the function is used with integers, it is nearly equivalent to the Python built-in function
range, but arange returns an ndarray rather than a list iterator as range does. If the 'start' parameter is not given,
it will be set to 0. The end of the interval is determined by the parameter 'stop'. Usually, the interval will not
include this value, except in some cases where 'step' is not an integer and floating point round-off affects the
length of output ndarray. The spacing between two adjacent values of the output array is set with the optional
parameter 'step'. The default value for 'step' is 1. If the parameter 'step' is given, the 'start' parameter cannot be
optional, i.e. it has to be given as well. The type of the output array can be specified with the parameter 'dtype'.
If it is not given, the type will be automatically inferred from the other input arguments.

import numpy as np

a = np.arange(1, 10)
print(a)

x = range(1, 10)

17
print(x) # x is an iterator
print(list(x))

# further arange examples:


x = np.arange(10.4)
print(x)
x = np.arange(0.5, 10.4, 0.8)
print(x)
[1 2 3 4 5 6 7 8 9]
range(1, 10)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[ 0. 1. 2. 3. 4. 5. 6. 7. 8. 9. 10.]
[ 0.5 1.3 2.1 2.9 3.7 4.5 5.3 6.1 6.9 7.7 8.5 9.3 10.1]

Be careful, if you use a float value for the step parameter, as you can see in the following example:

np.arange(12.04, 12.84, 0.08)


Output: array([12.04, 12.12, 12.2 , 12.28, 12.36, 12.44, 12.52, 12.6
, 12.68,
12.76, 12.84])

The help of arange has to say the following for the stop parameter: "End of interval. The interval does
not include this value, except in some cases where step is not an integer and floating point round-off
affects the length of out . This is what happened in our example.

The following usages of arange is a bit offbeat. Why should we use float values, if we want integers as
result. Anyway, the result might be confusing. Before arange starts, it will round the start value, end value and
the stepsize:

x = np.arange(0.5, 10.4, 0.8, int)


print(x)
[ 0 1 2 3 4 5 6 7 8 9 10 11 12]

This result defies all logical explanations. A look at help also helps here: "When using a non-integer step, such
as 0.1, the results will often not be consistent. It is better to use numpy.linspace for these cases. Using
linspace is not an easy workaround in some situations, because the number of values has to be known.

18
LINSPACE
The syntax of linspace:

linspace(start, stop, num=50, endpoint=True, retstep=False)

linspace returns an ndarray, consisting of 'num' equally spaced samples in the closed interval [start, stop] or the
half-open interval [start, stop). If a closed or a half-open interval will be returned, depends on whether
'endpoint' is True or False. The parameter 'start' defines the start value of the sequence which will be created.
'stop' will the end value of the sequence, unless 'endpoint' is set to False. In the latter case, the resulting
sequence will consist of all but the last of 'num + 1' evenly spaced samples. This means that 'stop' is excluded.
Note that the step size changes when 'endpoint' is False. The number of samples to be generated can be set
with 'num', which defaults to 50. If the optional parameter 'endpoint' is set to True (the default), 'stop' will be
the last sample of the sequence. Otherwise, it is not included.

import numpy as np

# 50 values between 1 and 10:


print(np.linspace(1, 10))
# 7 values between 1 and 10:
print(np.linspace(1, 10, 7))
# excluding the endpoint:
print(np.linspace(1, 10, 7, endpoint=False))
[ 1. 1.18367347 1.36734694 1.55102041 1.73469388 1.91
836735
2.10204082 2.28571429 2.46938776 2.65306122 2.83673469 3.02
040816
3.20408163 3.3877551 3.57142857 3.75510204 3.93877551 4.12
244898
4.30612245 4.48979592 4.67346939 4.85714286 5.04081633 5.22
44898
5.40816327 5.59183673 5.7755102 5.95918367 6.14285714 6.32
653061
6.51020408 6.69387755 6.87755102 7.06122449 7.24489796 7.42
857143
7.6122449 7.79591837 7.97959184 8.16326531 8.34693878 8.53
061224
8.71428571 8.89795918 9.08163265 9.26530612 9.44897959 9.63
265306
9.81632653 10. ]
[ 1. 2.5 4. 5.5 7. 8.5 10. ]
[1. 2.28571429 3.57142857 4.85714286 6.14285714 7.42857143
8.71428571]

19
We haven't discussed one interesting parameter so far. If the optional parameter 'retstep' is set, the function
will also return the value of the spacing between adjacent values. So, the function will return a tuple
('samples', 'step'):

import numpy as np

samples, spacing = np.linspace(1, 10, retstep=True)


print(spacing)
samples, spacing = np.linspace(1, 10, 20, endpoint=True, retstep=T
rue)
print(spacing)
samples, spacing = np.linspace(1, 10, 20, endpoint=False, retste
p=True)
print(spacing)
0.1836734693877551
0.47368421052631576
0.45

ZERO-DIMENSIONAL ARRAYS IN NUMPY


It's possible to create multidimensional arrays in numpy. Scalars are zero dimensional. In the following
example, we will create the scalar 42. Applying the ndim method to our scalar, we get the dimension of the
array. We can also see that the type is a "numpy.ndarray" type.

import numpy as np
x = np.array(42)
print("x: ", x)
print("The type of x: ", type(x))
print("The dimension of x:", np.ndim(x))
x: 42
The type of x: <class 'numpy.ndarray'>
The dimension of x: 0

ONE-DIMENSIONAL ARRAYS
We have already encountered a 1-dimenional array - better known to some as vectors - in our initial example.
What we have not mentioned so far, but what you may have assumed, is the fact that numpy arrays are
containers of items of the same type, e.g. only integers. The homogenous type of the array can be determined
with the attribute "dtype", as we can learn from the following example:

F = np.array([1, 1, 2, 3, 5, 8, 13, 21])


V = np.array([3.4, 6.9, 99.8, 12.8])

20
print("F: ", F)
print("V: ", V)
print("Type of F: ", F.dtype)
print("Type of V: ", V.dtype)
print("Dimension of F: ", np.ndim(F))
print("Dimension of V: ", np.ndim(V))
F: [ 1 1 2 3 5 8 13 21]
V: [ 3.4 6.9 99.8 12.8]
Type of F: int64
Type of V: float64
Dimension of F: 1
Dimension of V: 1

TWO- AND MULTIDIMENSIONAL ARRAYS


Of course, arrays of NumPy are not limited to one dimension. They are of arbitrary dimension. We create them
by passing nested lists (or tuples) to the array method of numpy.

A = np.array([ [3.4, 8.7, 9.9],


[1.1, -7.8, -0.7],
[4.1, 12.3, 4.8]])
print(A)
print(A.ndim)
[[ 3.4 8.7 9.9]
[ 1.1 -7.8 -0.7]
[ 4.1 12.3 4.8]]
2

B = np.array([ [[111, 112], [121, 122]],


[[211, 212], [221, 222]],
[[311, 312], [321, 322]] ])
print(B)
print(B.ndim)
[[[111 112]
[121 122]]

[[211 212]
[221 222]]

[[311 312]
[321 322]]]
3

21
SHAPE OF AN ARRAY
The function "shape" returns the shape of an array. The shape is a tuple of
integers. These numbers denote the lengths of the corresponding array
dimension. In other words: The "shape" of an array is a tuple with the number
of elements per axis (dimension). In our example, the shape is equal to (6, 3),
i.e. we have 6 lines and 3 columns.

x = np.array([ [67, 63, 87],


[77, 69, 59],
[85, 87, 99],
[79, 72, 71],
[63, 89, 93],
[68, 92, 78]])

print(np.shape(x))
(6, 3)

There is also an equivalent array property:

print(x.shape)
(6, 3)

The shape of an array tells us also something about the order in which the indices
are processed, i.e. first rows, then columns and after that the further dimensions.

"shape" can also be used to change the shape of an array.

x.shape = (3, 6)
print(x)
[[67 63 87 77 69 59]
[85 87 99 79 72 71]
[63 89 93 68 92 78]]

x.shape = (2, 9)
print(x)

22
[[67 63 87 77 69 59 85 87 99]
[79 72 71 63 89 93 68 92 78]]

You might have guessed by now that the new shape must correspond to the number of elements of the array,
i.e. the total size of the new array must be the same as the old one. We will raise an exception, if this is not the
case.

Let's look at some further examples.

The shape of a scalar is an empty tuple:

x = np.array(11)
print(np.shape(x))
()

B = np.array([ [[111, 112, 113], [121, 122, 123]],


[[211, 212, 213], [221, 222, 223]],
[[311, 312, 313], [321, 322, 323]],
[[411, 412, 413], [421, 422, 423]] ])

print(B.shape)
(4, 2, 3)

INDEXING AND SLICING


Assigning to and accessing the elements of an array is similar to other sequential data types of Python, i.e. lists
and tuples. We have also many options to indexing, which makes indexing in Numpy very powerful and
similar to the indexing of lists and tuples.

Single indexing behaves the way, you will most probably expect it:

F = np.array([1, 1, 2, 3, 5, 8, 13, 21])


# print the first element of F
print(F[0])
# print the last element of F
print(F[-1])
1
21

23
Indexing multidimensional arrays:

A = np.array([ [3.4, 8.7, 9.9],


[1.1, -7.8, -0.7],
[4.1, 12.3, 4.8]])

print(A[1][0])
1.1

We accessed an element in the second row, i.e. the row with the index 1, and the first column (index 0). We
accessed it the same way, we would have done with an element of a nested Python list.

You have to be aware of the fact, that way of accessing multi-dimensional arrays can be highly inefficient. The
reason is that we create an intermediate array A[1] from which we access the element with the index 0. So it
behaves similar to this:

tmp = A[1]
print(tmp)
print(tmp[0])
[ 1.1 -7.8 -0.7]
1.1

There is another way to access elements of multi-dimensional arrays in Numpy: We use only one pair of
square brackets and all the indices are separated by commas:

print(A[1, 0])
1.1

We assume that you are familar with the slicing of lists and tuples. The syntax is the same in numpy for one-
dimensional arrays, but it can be applied to multiple dimensions as well.

The general syntax for a one-dimensional array A looks like this:

A[start:stop:step]

We illustrate the operating principle of "slicing" with some examples. We start with the easiest case, i.e. the
slicing of a one-dimensional array:

S = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
print(S[2:5])
print(S[:4])
print(S[6:])

24
print(S[:])
[2 3 4]
[0 1 2 3]
[6 7 8 9]
[0 1 2 3 4 5 6 7 8 9]

We will illustrate the multidimensional slicing in the following examples. The ranges for each dimension are
separated by commas:

A = np.array([
[11, 12, 13, 14, 15],
[21, 22, 23, 24, 25],
[31, 32, 33, 34, 35],
[41, 42, 43, 44, 45],
[51, 52, 53, 54, 55]])

print(A[:3, 2:])
[[13 14 15]
[23 24 25]
[33 34 35]]

print(A[3:, :])
[[41 42 43 44 45]
[51 52 53 54 55]]

25
print(A[:, 4:])
[[15]
[25]
[35]
[45]
[55]]

The following two examples use the third parameter "step". The reshape function is used to construct the two-
dimensional array. We will explain reshape in the following subchapter:

X = np.arange(28).reshape(4, 7)
print(X)
[[ 0 1 2 3 4 5 6]
[ 7 8 9 10 11 12 13]
[14 15 16 17 18 19 20]
[21 22 23 24 25 26 27]]

print(X[::2, ::3])
[[ 0 3 6]
[14 17 20]]

26
print(X[::, ::3])
[[ 0 3 6]
[ 7 10 13]
[14 17 20]
[21 24 27]]

If the number of objects in the selection tuple is less than the dimension N, then : is assumed
for any subsequent dimensions:

A = np.array(
[ [ [45, 12, 4], [45, 13, 5], [46, 12, 6] ],
[ [46, 14, 4], [45, 14, 5], [46, 11, 5] ],
[ [47, 13, 2], [48, 15, 5], [52, 15, 1] ] ])

A[1:3, 0:2] # equivalent to A[1:3, 0:2, :]


Output: array([[[46, 14, 4],
[45, 14, 5]],

[[47, 13, 2],


[48, 15, 5]]])

27
Attention: Whereas slicings on lists and tuples create new objects, a slicing operation on an array creates a
view on the original array. So we get an another possibility to access the array, or better a part of the array.
From this follows that if we modify a view, the original array will be modified as well.

A = np.array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
S = A[2:6]
S[0] = 22
S[1] = 23
print(A)
[ 0 1 22 23 4 5 6 7 8 9]

Doing the similar thing with lists, we can see that we get a copy:

lst = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
lst2 = lst[2:6]
lst2[0] = 22
lst2[1] = 23
print(lst)
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

If you want to check, if two array names share the same memory block, you can use the function
np.may_share_memory.

np.may_share_memory(A, B)

To determine if two arrays A and B can share memory the memory-bounds of A and B are computed. The
function returns True, if they overlap and False otherwise. The function may give false positives, i.e. if it
returns True it just means that the arrays may be the same.

np.may_share_memory(A, S)
Output: True

The following code shows a case, in which the use of may_share_memory is quite useful:

A = np.arange(12)
B = A.reshape(3, 4)
A[0] = 42
print(B)
[[42 1 2 3]
[ 4 5 6 7]
[ 8 9 10 11]]

28
We can see that A and B share the memory in some way. The array attribute "data" is an object pointer to the
start of an array's data.

But we saw that if we change an element of one array the other one is changed as well. This fact is reflected
by may_share_memory:

np.may_share_memory(A, B)
Output: True

The result above is "false positive" example for may_share_memory in the sense that somebody may think
that the arrays are the same, which is not the case.

CREATING ARRAYS WITH ONES, ZEROS AND EMPTY


There are two ways of initializing Arrays with Zeros or Ones. The method ones(t) takes a tuple t with the
shape of the array and fills the array accordingly with ones. By default it will be filled with Ones of type float.
If you need integer Ones, you have to set the optional parameter dtype to int:

import numpy as np

E = np.ones((2,3))
print(E)

F = np.ones((3,4),dtype=int)
print(F)
[[1. 1. 1.]
[1. 1. 1.]]
[[1 1 1 1]
[1 1 1 1]
[1 1 1 1]]

What we have said about the method ones() is valid for the method zeros() analogously, as we can see in the
following example:

Z = np.zeros((2,4))
print(Z)
[[0. 0. 0. 0.]
[0. 0. 0. 0.]]

29
There is another interesting way to create an array with Ones or with Zeros, if it has to have the same shape as
another existing array 'a'. Numpy supplies for this purpose the methods ones_like(a) and zeros_like(a).

x = np.array([2,5,18,14,4])
E = np.ones_like(x)
print(E)

Z = np.zeros_like(x)
print(Z)
[1 1 1 1 1]
[0 0 0 0 0]

There is also a way of creating an array with the empty function. It creates and returns a reference to a new
array of given shape and type, without initializing the entries. Sometimes the entries are zeros, but you
shouldn't be mislead. Usually, they are arbitrary values.

np.empty((2, 4))
Output: array([[0., 0., 0., 0.],
[0., 0., 0., 0.]])

COPYING ARRAYS

NUMPY.COPY()
copy(obj, order='K')

Return an array copy of the given object 'obj'.

Parameter Meaning

obj array_like input data.

The possible values are {'C', 'F', 'A', 'K'}. This parameter controls the memory layout of the copy. 'C' means C-order,
order 'F' means Fortran-order, 'A' means 'F' if the object 'obj' is Fortran contiguous, 'C' otherwise. 'K' means match the
layout of 'obj' as closely as possible.

30
import numpy as np

x = np.array([[42,22,12],[44,53,66]], order='F')
y = x.copy()

x[0,0] = 1001
print(x)

print(y)
[[1001 22 12]
[ 44 53 66]]
[[42 22 12]
[44 53 66]]

print(x.flags['C_CONTIGUOUS'])
print(y.flags['C_CONTIGUOUS'])
False
True

NDARRAY.COPY()
There is also a ndarray method 'copy', which can be directly applied to an array. It is similiar to the above
function, but the default values for the order arguments are different.

a.copy(order='C')

Returns a copy of the array 'a'.

Parameter Meaning

order The same as with numpy.copy, but 'C' is the default value for order.

import numpy as np

x = np.array([[42,22,12],[44,53,66]], order='F')
y = x.copy()
x[0,0] = 1001
print(x)

31
print(y)

print(x.flags['C_CONTIGUOUS'])
print(y.flags['C_CONTIGUOUS'])
[[1001 22 12]
[ 44 53 66]]
[[42 22 12]
[44 53 66]]
False
True

IDENTITY ARRAY
In linear algebra, the identity matrix, or unit matrix, of size n is the n × n square matrix with ones on the main
diagonal and zeros elsewhere.

There are two ways in Numpy to create identity arrays:

• identy
• eye

THE IDENTITY FUNCTION


We can create identity arrays with the function identity:

identity(n, dtype=None)

The parameters:

Parameter Meaning

n An integer number defining the number of rows and columns of the output, i.e. 'n' x 'n'

dtype An optional argument, defining the data-type of the output. The default is 'float'

The output of identity is an 'n' x 'n' array with its main diagonal set to one, and all other elements are 0.

import numpy as np

np.identity(4)

32
Output: array([[1., 0., 0., 0.],
[0., 1., 0., 0.],
[0., 0., 1., 0.],
[0., 0., 0., 1.]])

np.identity(4, dtype=int) # equivalent to np.identity(3, int)


Output: array([[1, 0, 0, 0],
[0, 1, 0, 0],
[0, 0, 1, 0],
[0, 0, 0, 1]])

THE EYE FUNCTION


Another way to create identity arrays provides the function eye. This function creates also diagonal arrays
consisting solely of ones.

It returns a 2-D array with ones on the diagonal and zeros elsewhere.

eye(N, M=None, k=0, dtype=float)

Parameter Meaning

N An integer number defining the rows of the output array.

M An optional integer for setting the number of columns in the output. If it is None, it defaults to 'N'.

Defining the position of the diagonal. The default is 0. 0 refers to the main diagonal. A positive value refers to an
k
upper diagonal, and a negative value to a lower diagonal.

dtype Optional data-type of the returned array.

eye returns an ndarray of shape (N,M). All elements of this array are equal to zero, except for the 'k'-th
diagonal, whose values are equal to one.

import numpy as np

np.eye(5, 8, k=1, dtype=int)

33
Output: array([[0, 1, 0, 0, 0, 0, 0, 0],
[0, 0, 1, 0, 0, 0, 0, 0],
[0, 0, 0, 1, 0, 0, 0, 0],
[0, 0, 0, 0, 1, 0, 0, 0],
[0, 0, 0, 0, 0, 1, 0, 0]])

The principle of operation of the parameter 'd' of the eye function is illustrated in the following diagram:

EXERCISES:
1) Create an arbitrary one dimensional array called "v".

2) Create a new array which consists of the odd indices of previously created array "v".

3) Create a new array in backwards ordering from v.

4) What will be the output of the following code:

a = np.array([1, 2, 3, 4, 5])

34
b = a[1:4]
b[0] = 200
print(a[1])

5) Create a two dimensional array called "m".

6) Create a new array from m, in which the elements of each row are in reverse order.

7) Another one, where the rows are in reverse order.

8) Create an array from m, where columns and rows are in reverse order.

9) Cut of the first and last row and the first and last column.

SOLUTIONS TO THE EXERCISES:


1)

import numpy as np
a = np.array([3,8,12,18,7,11,30])

2)

odd_elements = a[1::2]

3) reverse_order = a[::-1]

4) The output will be 200, because slices are views in numpy and not copies.

5) m = np.array([ [11, 12, 13, 14], [21, 22, 23, 24], [31, 32, 33, 34]])

6) m[::,::-1]

7) m[::-1]

8) m[::-1,::-1]

9) m[1:-1,1:-1]

35
DATA TYPE OBJECTS, DTYPE

DTYPE
The data type object 'dtype' is an instance of numpy.dtype class. It
can be created with numpy.dtype.

So far, we have used in our examples of numpy arrays only


fundamental numeric data types like 'int' and 'float'. These numpy
arrays contained solely homogenous data types. dtype objects are
construed by combinations of fundamental data types. With the aid
of dtype we are capable to create "Structured Arrays", - also
known as "Record Arrays". The structured arrays provide us with
the ability to have different data types per column. It has similarity
to the structure of excel or csv documents. This makes it possibe to
define data like the one in the following table with dtype:

Country Population Density Area Population

Netherlands 393 41526 16,928,800

Belgium 337 30510 11,007,020

United Kingdom 256 243610 62,262,000

Germany 233 357021 81,799,600

Liechtenstein 205 160 32,842

Italy 192 301230 59,715,625

Switzerland 177 41290 7,301,994

Luxembourg 173 2586 512,000

France 111 547030 63,601,002

Austria 97 83858 8,169,929

36
Country Population Density Area Population

Greece 81 131940 11,606,813

Ireland 65 70280 4,581,269

Sweden 20 449964 9,515,744

Finland 16 338424 5,410,233

Norway 13 385252 5,033,675

Before we start with a complex data structure like the previous data, we want to introduce dtype in a very
simple example. We define an int16 data type and call this type i16. (We have to admit, that this is not a nice
name, but we use it only here!). The elements of the list 'lst' are turned into i16 types to create the two-
dimensional array A.

import numpy as np

i16 = np.dtype(np.int16)
print(i16)

lst = [ [3.4, 8.7, 9.9],


[1.1, -7.8, -0.7],
[4.1, 12.3, 4.8] ]

A = np.array(lst, dtype=i16)

print(A)
int16
[[ 3 8 9]
[ 1 -7 0]
[ 4 12 4]]

We introduced a new name for a basic data type in the previous example. This has nothing to do with the
structured arrays, which we mentioned in the introduction of this chapter of our dtype tutorial.

STRUCTURED ARRAYS
ndarrays are homogeneous data objects, i.e. all elements of an array have to be of the same data type. The data
type dytpe on the other hand allows as to define separate data types for each column.

37
Now we will take the first step towards implementing the table with European countries and the information
on population, area and population density. We create a structured array with the 'density' column. The data
type is defined as np.dtype([('density', np.int)]) . We assign this data type to the variable 'dt'
for the sake of convenience. We use this data type in the darray definition, in which we use the first three
densities.

import numpy as np

dt = np.dtype([('density', np.int32)])

x = np.array([(393,), (337,), (256,)],


dtype=dt)

print(x)

print("\nThe internal representation:")


print(repr(x))
[(393,) (337,) (256,)]

The internal representation:


array([(393,), (337,), (256,)],
dtype=[('density', '<i4')])

We can access the content of the density column by indexing x with the key 'density'. It looks like accessing a
dictionary in Python:

print(x['density'])
[393 337 256]

You may wonder that we have used 'np.int32' in our definition and the internal representation shows '<i4'. We
can use in the dtype definition the type directly (e.g. np.int32) or we can use a string (e.g. 'i4'). So, we could
have defined our dtype like this as well:

dt = np.dtype([('density', 'i4')])
x = np.array([(393,), (337,), (256,)],
dtype=dt)
print(x)
[(393,) (337,) (256,)]

The 'i' means integer and the 4 means 4 bytes. What about the less-than sign in front of i4 in the result? We
could have written '<i4' in our definition as well. We can prefix a type with the '<' and '>' sign. '<' means that

38
the encoding will be little-endian and '>' means that the encoding will be big-endian. No prefix means that we
get the native byte ordering. We demonstrate this in the following by defining a double-precision floating-
point number in various orderings:

# little-endian ordering
dt = np.dtype('<d')
print(dt.name, dt.byteorder, dt.itemsize)

# big-endian ordering
dt = np.dtype('>d')
print(dt.name, dt.byteorder, dt.itemsize)

# native byte ordering


dt = np.dtype('d')
print(dt.name, dt.byteorder, dt.itemsize)
float64 = 8
float64 > 8
float64 = 8

The equal character '=' stands for 'native byte ordering', defined by the operating system. In our case this
means 'little-endian', because we use a Linux computer.

Another thing in our density array might be confusing. We defined the array with a list containing one-tuples.
So you may ask yourself, if it is possible to use tuples and lists interchangeably? This is not possible. The
tuples are used to define the records - in our case consisting solely of a density - and the list is the 'container'
for the records or in other words 'the lists are cursed upon'. The tuples define the atomic elements of the
structure and the lists the dimensions.

Now we will add the country name, the area and the population number to our data type:

dt = np.dtype([('country', 'S20'), ('density', 'i4'), ('area', 'i


4'), ('population', 'i4')])
population_table = np.array([
('Netherlands', 393, 41526, 16928800),
('Belgium', 337, 30510, 11007020),
('United Kingdom', 256, 243610, 62262000),
('Germany', 233, 357021, 81799600),
('Liechtenstein', 205, 160, 32842),
('Italy', 192, 301230, 59715625),
('Switzerland', 177, 41290, 7301994),
('Luxembourg', 173, 2586, 512000),
('France', 111, 547030, 63601002),
('Austria', 97, 83858, 8169929),
('Greece', 81, 131940, 11606813),

39
('Ireland', 65, 70280, 4581269),
('Sweden', 20, 449964, 9515744),
('Finland', 16, 338424, 5410233),
('Norway', 13, 385252, 5033675)],
dtype=dt)
print(population_table[:4])
[(b'Netherlands', 393, 41526, 16928800)
(b'Belgium', 337, 30510, 11007020)
(b'United Kingdom', 256, 243610, 62262000)
(b'Germany', 233, 357021, 81799600)]

We can acces every column individually:

print(population_table['density'])
print(population_table['country'])
print(population_table['area'][2:5])
[393 337 256 233 205 192 177 173 111 97 81 65 20 16 13]
[b'Netherlands' b'Belgium' b'United Kingdom' b'Germany' b'Liechten
stein'
b'Italy' b'Switzerland' b'Luxembourg' b'France' b'Austria' b'Gree
ce'
b'Ireland' b'Sweden' b'Finland' b'Norway']
[243610 357021 160]

UNICODE STRINGS IN ARRAY


Some may have noticed that the strings in our previous array have been prefixed with a lower case "b". This
means that we have created binary strings with the definition "('country', 'S20')". To get unicode strings we
exchange this with the definition "('country', np.unicode, 20)". We will redefine our population table now:

dt = np.dtype([('country', np.unicode, 20),


('density', 'i4'),
('area', 'i4'),
('population', 'i4')])
population_table = np.array([
('Netherlands', 393, 41526, 16928800),
('Belgium', 337, 30510, 11007020),
('United Kingdom', 256, 243610, 62262000),
('Germany', 233, 357021, 81799600),
('Liechtenstein', 205, 160, 32842),

40
('Italy', 192, 301230, 59715625),
('Switzerland', 177, 41290, 7301994),
('Luxembourg', 173, 2586, 512000),
('France', 111, 547030, 63601002),
('Austria', 97, 83858, 8169929),
('Greece', 81, 131940, 11606813),
('Ireland', 65, 70280, 4581269),
('Sweden', 20, 449964, 9515744),
('Finland', 16, 338424, 5410233),
('Norway', 13, 385252, 5033675)],
dtype=dt)
print(population_table[:4])
[('Netherlands', 393, 41526, 16928800) ('Belgium', 337, 30510, 1
1007020)
('United Kingdom', 256, 243610, 62262000)
('Germany', 233, 357021, 81799600)]

INPUT AND OUTPUT OF STRUCTURED ARRAYS


In most applications it will be necessary to save the data from a program into a file. We will write our
previously created "darray" to a file with the command savetxt. You will find a detailled introduction into this
topic in our chapter Reading and Writing Data Files

np.savetxt("population_table.csv",
population_table,
fmt="%s;%d;%d;%d",
delimiter=";")

It is highly probable that you will need to read in the previously written file at a later date. This can be
achieved with the function genfromtxt.

dt = np.dtype([('country', np.unicode, 20), ('density', 'i4'), ('a


rea', 'i4'), ('population', 'i4')])

x = np.genfromtxt("population_table.csv",
dtype=dt,
delimiter=";")

print(x)

41
[('Netherlands', 393, 41526, 16928800) ('Belgium', 337, 30510, 1
1007020)
('United Kingdom', 256, 243610, 62262000)
('Germany', 233, 357021, 81799600)
('Liechtenstein', 205, 160, 32842) ('Italy', 192, 301230, 5
9715625)
('Switzerland', 177, 41290, 7301994)
('Luxembourg', 173, 2586, 512000) ('France', 111, 547030, 636
01002)
('Austria', 97, 83858, 8169929) ('Greece', 81, 131940, 116068
13)
('Ireland', 65, 70280, 4581269) ('Sweden', 20, 449964, 95157
44)
('Finland', 16, 338424, 5410233) ('Norway', 13, 385252, 50336
75)]

There is also a function "loadtxt", but it is more difficult to use, because it returns the strings as binary strings!

To overcome this problem, we can use loadtxt with a converter function for the first column.

dt = np.dtype([('country', np.unicode, 20), ('density', 'i4'), ('a


rea', 'i4'), ('population', 'i4')])

x = np.loadtxt("population_table.csv",
dtype=dt,
converters={0: lambda x: x.decode('utf-8')},
delimiter=";")

print(x)
[('Netherlands', 393, 41526, 16928800) ('Belgium', 337, 30510, 1
1007020)
('United Kingdom', 256, 243610, 62262000)
('Germany', 233, 357021, 81799600)
('Liechtenstein', 205, 160, 32842) ('Italy', 192, 301230, 5
9715625)
('Switzerland', 177, 41290, 7301994)
('Luxembourg', 173, 2586, 512000) ('France', 111, 547030, 636
01002)
('Austria', 97, 83858, 8169929) ('Greece', 81, 131940, 116068
13)
('Ireland', 65, 70280, 4581269) ('Sweden', 20, 449964, 95157
44)
('Finland', 16, 338424, 5410233) ('Norway', 13, 385252, 50336
75)]

42
EXERCISES:
Before you go on, you may take time to do some exercises to deepen the understanding of the previously
learned stuff.

1. Exercise:
Define a structured array with two columns. The first column contains the product ID, which can
be defined as an int32. The second column shall contain the price for the product. How can you
print out the column with the product IDs, the first row and the price for the third article of this
structured array?

2. Exercise:
Figure out a data type definition for time records with entries for hours, minutes and seconds.

SOLUTIONS:
Solution to the first exercise:

import numpy as np

mytype = [('productID', np.int32), ('price', np.float64)]

stock = np.array([(34765, 603.76),


(45765, 439.93),
(99661, 344.19),
(12129, 129.39)], dtype=mytype)

print(stock[1])
print(stock["productID"])
print(stock[2]["price"])
print(stock)
(45765, 439.93)
[34765 45765 99661 12129]
344.19
[(34765, 603.76) (45765, 439.93) (99661, 344.19) (12129, 129.3
9)]

Solution to the second exercise:

43
Other documents randomly have
different content
The importance of this invention can hardly be overestimated. It
ranks with Maudslay’s slide-rest and the turret tool-holder, as it is an
essential feature in all modern automatic lathes, both for bar-stock
and chucking work.
Assured of the success of the machine, Spencer withdrew from
active connection with the Billings & Spencer Company in 1874, and
in 1876, with George A. Fairfield, then superintendent of the Weed
Sewing Machine Company, and others, formed the Hartford Machine
Screw Company, one of the most successful enterprises in the city.
Unfortunately, Mr. Spencer withdrew in 1882 to manufacture a new
repeating shotgun and rifle which he had invented. The gun was a
success mechanically, but the Spencer Arms Company, which had
been formed in 1883 at Windsor, Conn., was a failure, and Mr.
Spencer lost heavily. In his later years Mr. Spencer has returned to
the field where he did his most brilliant work, automatic lathes. He
represents the New England mechanic at his best, and his tireless
and productive ingenuity has made a permanent impress on modern
manufacturing methods.
Francis A. Pratt was born at Woodstock, Vt. When he was eight
years old his family moved to Lowell. He was a mechanic from
boyhood but he had the good fortune to be apprenticed as a
machinist with Warren Aldrich, a good mechanic and a wise teacher.
At twenty, Mr. Pratt went to Gloucester, N. J., where he was
employed first as a journeyman, later as a contractor. In 1852 he
came to the Colt shop, where he worked for two years. He then
accepted the foremanship of the Phœnix Iron Works, which was run
by Levi Lincoln and his two sons.
Amos Whitney was born in Maine and moved to Lawrence, Mass.,
where he served his apprenticeship with the Essex Machine
Company which built cotton machinery, locomotives and machine
tools. He came from a family of mechanics. His father was a
locksmith and machinist, his grandfather was an expert blacksmith,
his great-grandfather was a small manufacturer of agricultural tools,
and he is of the same family as Eli Whitney of New Haven, and
Baxter D. Whitney, the veteran tool builder of Winchendon. In 1850
both he and his father were working at Colt’s factory at Hartford. In
1854 Amos Whitney joined Pratt in the Phœnix Iron Works, where
they worked together for ten years, the former as a contractor, the
latter as superintendent. Whitney was earning over eight dollars a
day when he left Colt’s and took up the new contract work which
offered at the beginning only two dollars a day.
Many of the shops of that generation were “contract shops.” The
Colt Armory was run on that basis, at least in its manufacturing
departments. Under this system the firm or company furnished all
the materials, machinery, tools, shop room and supplies, while the
workmen were employed by the contractor, their wages being paid
by the firm but charged against the contractor’s account. A better
training for future manufacturers could hardly be devised, and a
surprising number of these old-time contractors have succeeded
later in business for themselves.
In the summer of 1860 Pratt and Whitney rented a small room
and, in addition to their regular employment, began doing work on
their own account, i.e., manufacturing the small winder for the
Willimantic Linen Company. Mr. Whitney’s father-in-law acted as
pattern maker, millwright, bookkeeper and general utility man. The
following February they were burned out, but were running again a
month later in other quarters. Here they continued to spread from
room to room until all available space was outgrown. They
succeeded from the very start, and at once became leaders and
teachers of other mechanics, suggesters of new methods of work
and of new means for its accomplishment. Both Pratt and Whitney
were thoroughly familiar with gun manufacture, and the business
was hardly started when the outbreak of the Civil War gave them
more than they could do. In 1862 they took into partnership Monroe
Stannard of New Britain, each of the three contributing $1200. Mr.
Stannard took charge of the shop, as Pratt and Whitney were still
with the Phœnix Iron Works. Within two years the business had
increased to such an extent that they gave up their positions at the
Phœnix works and in 1865 erected the first building on their present
site. From $3600 in 1862 their net assets grew in four years to
$75,000, and during the three years following that they earned and
put back into the business more than $100,000. In 1869 the Pratt &
Whitney Company was formed with a capital of $350,000, later
increased to $500,000. In 1893 it was reorganized with a
capitalization of $3,000,000. Since that time it has become a part of
the Niles-Bement-Pond Company.
Figure 35. Francis A. Pratt
Figure 36. Amos Whitney

Beginning with the manufacture of machine tools and tools for


making guns and sewing machines, they have extended their lines
until their catalog fills hundreds of pages. From their wide experience
in interchangeable manufacture, it was natural that they should take
a prominent part in developing the machinery for the manufacture of
bicycles and typewriters, when, later, these were introduced.
Soon after the Franco-Prussian War, an agent of the company
visited Prussia and found the royal and private gun factories
equipped with old and inferior machinery and the armories bare. Mr.
Pratt was sent for, and returned to Hartford with orders from the
German Government for $350,000 worth of gun machinery. During
the next few years Mr. Pratt made no less than ten trips to Europe,
taking orders aggregating over $2,000,000 worth of machinery.
When the panic of 1873 prostrated the industries of the United
States, Pratt & Whitney had orders, mostly foreign, which kept them
busy until 1875. Their equipment of the three royal armories of
Spandau, Erfurt and Danzig resulted in an improvement in quality of
output and a saving of 50 per cent in wages. Pratt & Whitney’s
production of gun-making machinery alone has run into many
millions of dollars, and there are few governments which have not at
one time or another purchased from them.
Pratt & Whitney from the start were leaders in establishing
standards, particularly in screw threads. Their gauges for pipe
threads have for years been the standard for the country. The
troubles which arose from the lack of agreement of standard gauges
and the growing demand for interchangeable bolts and nuts led to a
demand on the company for a set of gauges upon which all could
agree.
In undertaking this work Pratt & Whitney examined their own
standards of length with reference to government and other
standards in this country and abroad. The results were conflicting
and very unsatisfactory. By different measurements the same bar
would be reported as above and as below the standard length, and
the investigation produced no results which could be used for a
working basis. At length Prof. William A. Rogers of Harvard
University, and George M. Bond, backed by the Pratt & Whitney
Company, developed the Rogers-Bond comparator with which they
determined the length of the standard foot. When they began, the
length of the yard and its subdivisions varied with the number of
yardsticks. Professor Rogers’ work was based on line measurement
rather than the end measurement which had held sway from the time
of Whitworth and which is now generally recognized to be inferior for
final reference work. Professor Rogers went back of all the
secondary standards to the Imperial Yard in London and the
standard meter in the Archives at Paris. He obtained reliable
transfers of these, and with the coöperation of the United States
Coast Survey, the most delicate and exhaustive comparisons were
made of the standard bars prepared by him for the use of the
company with the government standard yard designated “Bronze No.
11.” Many thousands of dollars and three years of time went into this
work.
The methods used and the results obtained were examined and
reported upon by a committee of the American Society of
Mechanical Engineers, and the conclusion given in their report is as
follows:
The completion of the Rogers-Bond comparator marks a long stride in advance
over any method hitherto in use for comparison and subdivision of line-measure
standards, combining, as it does, all the approved methods of former observers
with others original with the designers. Comparisons can thus be checked
thoroughly by different systems, so that the final result of the series may be relied
on as being much nearer absolute accuracy than any hitherto produced.
The calipering attachment to the comparator deserves special commendation,
being simple in the extreme, and solving completely the problem of end
measurements within the limit of accuracy attainable in line reading, by means of
the microscope with the micrometer eye-piece. The standard to which the end
measurements are referred is not touched, and each measurement is referred
back to the same zero, so that error from end wear does not enter into the
problem. This attachment is in advance of all hitherto known methods of
comparing end measures, either with other end measures or with line standards,
both as to rapidity of manipulation and accuracy of its readings, the strong point in
its construction being that it refers all end measures to a carefully divided and
investigated standard bar, which is not touched during its use, and cannot be in the
slightest degree injured by this service, thus giving convincing assurance that the
measures and gauges produced by its use will be accurate and interchangeable.
In the opinion of this committee, the degree of accuracy already attained is such
that no future improvements can occasion changes sufficiently great to affect the
practical usefulness of the magnitudes here determined, or the interchangeability
of structures based upon them with those involving further refinement.
Prof. W. A. Rogers and Mr. George M. Bond are unquestionably entitled to great
credit for the admirable manner in which they have solved the problem of exact
and uniform measurement, while the enterprise of the Pratt & Whitney Company in
bringing the whole matter into practical shape, is deserving of the thanks of the
engineering community.[183]
[183] Those interested may find detailed descriptions of the methods used
and of the Rogers-Bond comparator in the following references: George M.
Bond: Paper on “Standard Measurements,” Trans. A. S. M. E., Vol. II, p. 80.
George M. Bond: Paper on “A Standard Gauge System,” Trans. A. S. M. E.,
Vol. III, p. 122. Report of Committee on Standards and Gauges, Trans. A. S.
M. E., Vol. IV, p. 21 (quoted above). W. A. Rogers: Paper, “On a Practical
Solution of the Perfect Screw Problem,” Trans. A. S. M. E., Vol. V, p. 216.
Two lectures delivered by George M. Bond before the Franklin Institute,
Philadelphia, in 1884, on: 1. “Standards of Length and their Subdivision.” 2.
“Standards of Length as Applied to Gauge Dimensions.”

The standards so obtained became the basis of the gauges which


Pratt & Whitney have produced.
In 1888 the company received its first order for Hotchkiss revolving
cannon, and for three- and six-pounders rapid-fire guns. They have
made hundreds of these guns for the secondary batteries of war
vessels. In 1895 they brought out a one-pounder invented by E. G.
Parkhurst, an expert mechanic, who had entered their employment
as assistant superintendent in 1869 and later took charge of their
gun department.
For many years the Pratt & Whitney tool-room lathes were the
standard for the country. Later their leadership was materially
affected by the Hendey Machine Company of Torrington, Conn., who
built a high grade tool-room lathe having the change-gear box which
has since been applied to nearly all types of machine tools. The
change-gear box is one of the important contributions to tool building
made in recent years. Among the later developments introduced by
Pratt & Whitney is the process of thread milling, and they have
designed a full line of machines for this work.
The Pratt & Whitney works, like the Colt Armory, has been a
training school for successful tool builders. Worcester R. Warner and
Ambrose Swasey were both foremen at Pratt & Whitney’s and left
there to go west, first to Chicago and then to Cleveland. Some
account of these two men will be given in a later chapter. Pratt &
Whitney have had a marked influence on tool building in Cleveland,
for, in addition to Warner and Swasey, E. C. Henn and Hakewessel
of the National Acme Manufacturing Company who developed the
multi-spindle automatic lathe, A. F. Foote of Foote, Burt & Company,
and George C. Bardons of Bardons & Oliver, come from their shop.
Johnston of Potter & Johnston, Pawtucket, was chief draftsman at
Pratt & Whitney’s; and J. N. Lapointe who later developed the
broaching machine, Dudley Seymour of Chicago, Gleason of the
Gleason Works in Rochester, E. P. Bullard of Bridgeport, and F. N.
Gardner of Beloit, Wis., inventor of the Gardner grinder, were all
workmen there.
Mr. Gleason was also a workman in the Colt Armory. He went to
Rochester in 1865 and the works which he developed form the most
important tool building interest in western New York. There have
been “a good many starts there in tool building and almost as many
finishes.” Mr. Gleason always said that but for the training and
methods he had gained at Hartford he would have shared their fate.
Like many others, his company began with a general line of machine
tools but has come to specialize on one type of machine, bevel-gear
cutters, of which they build a most refined type.
E. P. Bullard, like Gleason, worked at both Colt’s and Pratt &
Whitney’s. Later he formed a partnership with J. H. Prest and William
Parsons, manufacturing millwork and “all kinds of tools” in Hartford.
In 1866 he organized the Norwalk Iron Works Company of Norwalk,
but afterwards withdrew and continued the business in Hartford. For
a number of years Mr. Bullard was in the South and Middle West, at
Athens, Ga., at Cincinnati, where he organized the machine tool
department of Post & Company, and at Columbus, where he was
superintendent of the Gill Car Works. In 1875 he established a
machinery business in Beekman Street, New York, under the firm
name of Allis, Bullard & Company. Mr. Allis withdrew in 1877 and the
Bullard Machine Company was organized. Recognizing a demand
for a high grade lathe he went to Bridgeport, Conn., and engaged A.
D. Laws to manufacture lathes of his design, agreeing to take his
entire output. In the latter part of the same year Mr. Bullard took over
the business and it became the Bridgeport Machine Tool Works. In
1883 he designed his first vertical boring and turning mill, a single
head, belt feed machine of 37 inches capacity. This is believed to be
the first small boring machine designed to do the accurate work
previously performed on the face plate of a lathe. Up to that time
boring machines were relied on only for large and rough work. In
1889 he transferred his New York connections to J. J. McCabe and
gave his entire attention to manufacturing, the business being
incorporated as the Bullard Machine Tool Company in 1894.
The building of boring mills gradually crowded out the lathes, and
for twenty years the company has concentrated on the boring
machine as a specialty. In their hands it has received a remarkable
development. They introduced a range of small-sized mills capable
of much more accurate work than had been done on this type of
machine. They applied the turret principle to the head carried on the
cross rail and a few years later introduced a mill having a head
carried on the side of the frame which permitted of the close working
of the tools. These improvements transformed the boring mill into a
manufacturing machine, and it became practically a vertical turret
lathe with the advantages inherent in that type of machine. This
trend toward the lathe type has finally resulted in a multiple station-
type of machine which is in effect a vertical multi-spindle automatic
chucking lathe with five independent tool heads, as shown in Fig. 56.
Comparison of this with Fig. 15, shows how the lathe has developed
in the 115 years since Maudslay introduced the slide-rest principle
and the lead screw.
CHAPTER XV
ROBBINS & LAWRENCE
A glance at the genealogical chart, Fig. 37, will show why the old
Robbins & Lawrence shop, at Windsor, Vt., in the backwoods of
northern New England, deserves a special chapter. When built, it
was miles away from a railroad. It was never large, and the wheels
of the original shop have long since ceased to turn, but few plants
have had so great an influence on American manufacturing. Three
brilliant mechanics, Lawrence, Howe and Stone, were working there
in the early fifties, and from them and their successors came wholly,
or in part, the vertical lathe turret, the miller, the profiler and a large
number of the modern machines used in interchangeable
manufacture. Of these three, Lawrence went to Hartford, Howe to
Providence, while Stone remained at Windsor. In each case an
important line of influence may be traced.
In the region about Windsor, sixty or seventy years ago, there
were a number of small custom gun shops, and one firm, N. Kendall
& Company, was regularly making guns at the Windsor prison, using
prison labor in addition to that of a number of free mechanics, who
did the finer work. The history of the Robbins & Lawrence Company
begins about 1838, when Lawrence came to Windsor from the
neighborhood of Watertown, N. Y. Fortunately he wrote out an
account of his life shortly before his death, at the request of his son,
giving a very interesting record of his early work and his connections
with his various manufacturing enterprises. This account shows
clearly the integrity, modesty and worth of the man.[184]
[184] By the courtesy of Mr. Ned Lawrence this account is given in
Appendix A. It has never been published before.
N. KENDALL & CO. R. S LAWRENCE
Kendall & Lawrence
Custom Gun Shop, Windsor, Vt.
ROBBINS & LAWRENCE
Guns and Gun Machinery, Turret Lathes, Millers, etc.
R S. Lawrence, H. D. Stone, F. W. Howe
ENFIELD CHAS. E.
GUN BILLINGS
MACHRY., LAMSON, GOODNOW & Billings &
1855 YALE, 1859 Spencer,
Enfield, later Hartford
England E. G. LAMSON & CO.
SHARPS Guns, Sewing Machines, PROVIDENCE
J. R. BROWN
RIFLE Machine Tools, TOOL
S. B.
WORKS Windsor WORKS
DARLING,
Hartford, F. W. Howe,
ETC.
Conn. Supt., 1853-68
J. D. ALVORD
a contractor in R.
& L. Shop,
Hartford & Sharpe
Wks. Built the
Wheeler & Wilson
Shop,
Bridgeport
BROWN &
SHARPE
WEED SEWING F. W. Howe,
MACH. CO. Supt., 1868-73
Hartford, Conn. Plain and Univ.
Sewing Machine business sold Millers, Turret
about 1861 to Mr. White Lathes
POPE MFG. RHODE ISLAND TOOL CO.
CO. Successors of Providence Tool
Hartford, Works
Conn.
WHEELER & PUTNAM
WILSON MACH. CO.
Bridgeport, Conn. Fitchburg,
Sewing Machines Mass.
S. C. Wright
WINDSOR MANUFACTURING SULLIVAN MACHRY.
WHITE
CO. CO.
SEWING
1865 Claremont, N. H.
MACH. CO.
Mine and Quarrying
Cleveland, O.
Machinery
CLEVELAND AUTO JONES, LAMSON & CO., JAMES
MACH. CO., ETC. 1869 HARTNESS
Cleveland, O. JONES & LAMSON 1889
WINDSOR MACHINE CO., 1879 FITCHBURG
MACHINE CO. Moved from Windsor to MACH. WORKS
Windsor, Vt., Springfield, Vt., in 1889 Fitchburg, Mass.
1889, Hartness Flat Turret, Fay Lo-Swing Lathe
Gridley Automatic Lathes
Automation
JAMES HARTNESS
BRYANT
E. R. FELLOWS FELLOWS GEAR SHAPER
CHUCKING
G. O. GRIDLEY CO.
GRINDER CO.
Wm. BRYANT Springfield, Vt.
Springfield, Vt.

Figure 37. Genealogy of the Robbins & Lawrence Shop

Richard S. Lawrence, whose portrait appears in Fig. 40, was born


in Chester, Vt., in 1817. When two years old, his father moved to
Jefferson County, N. Y., and his boyhood was spent in the
neighborhood of Watertown. He was only nine years old when his
father died, and consequently he had a hard boyhood, with very little
schooling, and was early at work in the support of the family. He
worked on a farm and later in a woodworking shop, making
carpenter’s and joiner’s tools. In the basement of this place was a
custom gun shop, where he spent much of his spare time and
became an expert gun maker. He worked with indifferent success at
various jobs until the winter of 1837-1838, when he served in the
United States army for three months, guarding the frontier during the
Canadian Rebellion. At his discharge he determined to start in
elsewhere for himself and thought of his relatives in Vermont. After a
long journey by the Erie Canal, the newly built Albany &
Schenectady Railroad, and by stage, he reached Windsor in 1838.
A week or two after his arrival, while visiting a Doctor Story, he
undertook to repair an old rifle, a “Turkey rifle,” made by the doctor’s
brother in a gun shop in the neighborhood, and put on a peep-sight,
a thing never heard of before in that neighborhood. He took the gun
apart, leaded out the barrel, forged and finished the sight and put it
on the gun. His skill in handling tools astonished those who watched
him. Two days later, when the work was done, the doctor and
Lawrence went out to try the gun. They paced off twelve rods from a
maple tree which had a three-quarter-inch auger hole in it that had
been used for a sap spout. Lawrence did the shooting. His own
account of it is as follows: “The doctor tended target. Could find no
ball hole. Said I missed the tree. I fired again, no ball hole to be
found. Doctor came up to me and said I had spoiled his rifle. Before
my repairs he could kill a chicken every time at twelve rods. I said,
‘Uncle, I am very sorry, but I will make the gun all right before I leave
it.’ He said he could not consent to my doing anything more to
improve the shooting qualities—the sight he liked very much. I said
that as the gun was loaded I would take one more shot and see if I
could not hit the tree. After the third shot I went up to the tree to
investigate, and all of the three balls which I had fired were found in
the auger hole.”[185] The doctor was astonished, for he had never
heard of such shooting.
[185] Quoted from the full account given in Appendix A.
The next day he took Lawrence down to see N. Kendall &
Company, who were making guns at the Windsor prison. They hired
him at once for two years at $100 a year. His first work was stocking
rifles by hand and the first day he put on five stocks. The next day
the superintendent looked over the work and said it was well done,
but it would never do to rush the work as he had, for he would “soon
gun-stock them out of town,” and he “must take it more easy.” In the
course of the next six months, he had so far mastered every process
in the factory, even that of engraving in which he could soon
compete with the oldest hands, that he was put in charge of the
shop. Four years later the company gave up the gun business, and
for a time Lawrence remained as foreman of the carriage department
in the prison shop.
In 1843 Kendall and Lawrence hired a small shop in Windsor
village and started a custom gun shop. In the winter of 1844 S. E.
Robbins, a business man, came to them and said that the
Government was in the market for 10,000 rifles. The matter was
talked over, a partnership formed, and a bid sent to Washington. In
spite of the opposition of nearly all the other Government
contractors, who said they could never do the work, it resulted in the
award of a contract for 10,000 to Robbins, Kendall & Lawrence, at
$10.90 each, attachments extra, to be furnished within three years.
They bought land, built a shop, and bought or made the necessary
machinery. It was in the performance of this and the subsequent
contract that many of the early machine tools were developed. The
contract was finished eighteen months ahead of time, at a good
profit, and they obtained a second contract for 15,000 at the same
price. Soon after finishing the first contract, Robbins and Lawrence
bought out Kendall’s interest in the firm, which became Robbins &
Lawrence. The business proved very profitable. About 38 per cent of
their work for the Government had to be rejected on account of poor
material and workmanship, but the California gold excitement was
then at its height and guns were in great demand. They were
therefore able to sell their second-quality work for the full
government price. About 1850 they contracted with Courtland C.
Palmer for 5000 Jennings rifles, a gun which later developed through
the Henry rifle into the present well-known Winchester rifle.
About 1850 Robbins & Lawrence took the first of the steps which
led to their undoing. The railroad had just been completed through
Windsor, and S. F. Belknap, a large railroad contractor, induced them
to start in the car business, which, of course, had no rational relation
with their main activity of building guns. Mr. Belknap assured them
that he could control all the car work in that section, and put in
$20,000 as a silent partner. The firm went to a large outlay, but just
as they were finishing the first cars, Belknap quarreled with the
president of the railroad and the firm could not sell a single car when
they had expected to. After a considerable delay they were sold to
other roads, and stock which proved valueless was taken in
payment. The operation involved an actual loss of $134,000, which
was later increased to nearly $240,000.

Figure 38. Robbins & Lawrence Armory, Windsor, Vt.

From an Old Lithograph

In all of their gun work, Robbins & Lawrence used the


interchangeable system, and they contributed very largely to its
development. Lawrence, Howe, and later Stone, were constantly
improving the methods of manufacture. Fitch’s article on
Interchangeable Manufacture in the U. S. Census Report of 1880,
describes and illustrates a profiling machine built by Howe as early
as 1848. The design shown there was used for many years
throughout all the gun shops in the country. He also designed a
barrel drilling and rifling machine, and he and Lawrence designed
and built a plain miller, which was the forerunner of the well-known
Lincoln miller. One of these millers, built in 1853, is still running in the
shop of the North Brothers Manufacturing Company in Philadelphia.
This machine had a rack-and-pinion feed for the table, which
chattered badly when starting a heavy cut. The principal
improvement which F. A. Pratt introduced in the Lincoln miller was
the substitution for this of a screw and nut. The original drawing of
this Robbins & Lawrence machine is still on file in the office of the
Jones & Lamson Machine Company and shows clearly that it
furnished the basis of the design of the Lincoln miller.
In 1851 Robbins & Lawrence sent to the Exposition in London a
set of rifles built on the interchangeable system, which excited great
interest and for which they received a medal. This led to the visit of
an English commission which resulted in a large contract to Robbins
& Lawrence for Enfield rifles, and for gun machinery which was
installed in the Armory at Enfield, near London. It has been said that
this contract caused the failure of Robbins & Lawrence. This is not
true.
In 1852 the company contracted to make 5000 Sharps carbines at
Windsor, and 15,000 rifles and carbines at a plant which they were to
erect in Hartford. The Sharps Company advanced $40,000 to enable
them to build a new factory and Mr. Lawrence moved to Hartford in
1853 to superintend the building and equipment of the plant. Shortly
after it was completed, Robbins & Lawrence, already strained by
their losses in the car-building venture and with the erecting of the
new plant, undertook a contract with Fox, Henderson & Company for
25,000 Minié rifles. They were assured by the agent that he had in
his pockets contracts for 300,000 more, which he promised them on
the completion of the 25,000. Lawrence objected strenuously to
signing the contract for the 25,000 without more assurance as to the
300,000 to follow, as the outlay for the work would greatly exceed
the profits on the first contract. It was signed, however, and it later
developed that the agent had no authorization for the 300,000. It was
this which caused the failure of Robbins & Lawrence.
Mr. Lawrence left the firm and took charge of the new Hartford
plant which had been bought by the Sharps Rifle Company. J. D.
Alvord, one of the contractors at Hartford under Lawrence, later built
the Wheeler & Wilson plant at Bridgeport. Robbins and others leased
the Windsor shops and began the manufacture of sewing machines.
In 1859 the plant and business were purchased by Lamson,
Goodnow & Yale, who retained Henry D. Stone as their mechanical
expert. During the Civil War the plant was given over entirely to the
manufacture of army rifles, and the sewing-machine business was
sold to Mr. White of the White Sewing Machine Company of
Cleveland, Ohio.
In the early thirties Silas Lamson had begun manufacturing scythe
snaths in one of the hill towns of western Massachusetts. Up to that
time the farmers had either used straight poles or those which
happened naturally to have a convenient twist. Lamson conceived
the idea of steaming the poles and bending them to a predetermined
curve. About 1840 his sons, Nathan and E. G. Lamson, moved to
Shelburne Falls and after some years began the manufacture of
cutlery, founding the factory which has been in successful operation
ever since. After the completion of the railroad through Windsor, they
moved their snath factory to that place. They and their successors,
the Lamson & Goodnow Manufacturing Company, continued this
work there for many years. When the Robbins & Lawrence property
was put on the market it was purchased by E. G. Lamson, A. F.
Goodnow and B. B. Yale, under the name of Lamson, Goodnow &
Yale. E. G. Lamson & Company and the Windsor Manufacturing
Company succeeded this firm and continued the manufacture of
machine tools and Ball and Palmer carbines, and completed a
number of government rifle contracts. In 1869 R. L. Jones, a
business man, of the Ascutney Mill at Windsor, joined the firm, which
became Jones, Lamson & Company, and a small cotton mill was
added to their other activities. Ten years later the Jones & Lamson
Company was organized to take over the machine business. During
all these changes Henry D. Stone continued as the designer. A large
poster of the Windsor Manufacturing Company, printed some time
about 1865, shows that they had plenty of irons in the fire, for they
were prepared to furnish guns and machinery for manufacturing
guns, sewing machines and needles, a standard line of hand-
operated turret lathes, plain and index millers, planers, trimming
presses, drill presses, sawmills, rock drills and mining machinery.
Later their mining and quarry-machinery business was moved to
Claremont, N. H., and became the Sullivan Machinery Company.
In 1889 the present Jones & Lamson Machine Company moved to
Springfield, Vt., where it now is. That same year, James Hartness
entered the employment of the company as superintendent. With his
advent the scattering of activities ceased and the Jones & Lamson
Machine Company began concentrating on turret lathes, which
Robbins & Lawrence and their various successors have been
manufacturing continuously since the early fifties. A number of the
old mechanics and foremen, who had homes in Windsor at the time
the company was moving to Springfield, took over the old shops and
organized the present Windsor Machine Company which now
manufactures the Gridley Automatic Lathes.
This, briefly, is the history of the old Robbins & Lawrence shop.
The men, however, who worked with Robbins & Lawrence and its
successors, are of greater interest.
While Lawrence continued as master-armorer of the Sharps Rifle
Works, the company was successful financially. Fitch, in the Census
article frequently referred to, says that he brought with him “from
Windsor the first plain milling machine used in Hartford.” Lawrence
also applied the broaching process to the manufacture of Sharps
rifles, effecting great economies, and was the inventor of the split
pulley which was first made for him at Lincoln’s Phœnix Iron Works.
In the winter of 1850 Lawrence introduced the practice of lubricating
rifle bullets with tallow, making possible the repeating rifle which had
been a failure up to that time as the barrel “leaded” and the gun lost
its accuracy. This was done in connection with some trials of the
Jennings rifle during the visit of Louis Kossuth, the Hungarian patriot,
who was in this country for the supposed purpose of purchasing
rifles.[186] Mr. Lawrence left the Sharps company in 1872 and was for
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!

ebooknice.com

You might also like