T.J. Langford
Vincent Balbarin
Yale Center for Reasearch Computing
October 25, 2022
numpy
and matplotlib
numpy
matplotlib
jupyter/scipy-notebook
Docker imagejupiter/scipy-notebook
image includes popular packages from the scientific Python ecosystempodman
cli supports many of the same flags as docker
cliFollow the instructions to install Podman on your operating system of choice.
# Clone the repository
git clone https://github.com/WrightLaboratory/data_analysis data_analysis
# Use the provided script to launch Jupyter container
cd data_analysis
bash ./scripts/podman_jupyterlab.sh
# Find the url in the standard output log trace and open in your browser
...
[C 2022-10-18 03:30:26.665 ServerApp]
To access the server, open this file in a browser:
file:///home/jovyan/.local/share/jupyter/runtime/jpserver-2-open.html
Or copy and paste one of these URLs:
http://784772c24b81:8888/lab?token=929d6fbdc29185ba5ac86b60c689e84b1f3fa2eb22b46ebc
or http://127.0.0.1:8888/lab?token=929d6fbdc29185ba5ac86b60c689e84b1f3fa2eb22b46ebc
...
numpy
¶import numpy as np
NumPy is the fundamental package for scientific computing with Python. It contains among other things:
array
objectArrays can be created in a variety of ways. The most common are either empty:
a = np.zeros(10)
a
array([0., 0., 0., 0., 0., 0., 0., 0., 0., 0.])
or you can create them from an existing list
:
b = np.array([0,1,2,3,4,5,6,7,8,9])
b
array([0, 1, 2, 3, 4, 5, 6, 7, 8, 9])
Arrays have a few key properties:
print(a.dtype)
print(b.dtype)
float64 int64
a.shape
(10,)
c = np.array([[0,1,2,3],[4,5,6,7]])
c
array([[0, 1, 2, 3], [4, 5, 6, 7]])
We can also act on these arrays with specific operations:
a = np.multiply(b, 4)
a
array([ 0, 4, 8, 12, 16, 20, 24, 28, 32, 36])
np.multiply(a, b)
array([ 0, 4, 16, 36, 64, 100, 144, 196, 256, 324])
np.max(b)
9
np.mean(a)
18.0
np.std(a)
11.489125293076057
np.sum(c, axis=0)
array([ 4, 6, 8, 10])
Array elements can be selected based on their values (or values of different arrays)
print(a)
[ 0 4 8 12 16 20 24 28 32 36]
a > 5
array([False, False, True, True, True, True, True, True, True, True])
This array of True
/False
values can then filter either a
or other arrays:
a[a > 5]
array([ 8, 12, 16, 20, 24, 28, 32, 36])
b[a > 5]
array([2, 3, 4, 5, 6, 7, 8, 9])
We will use this to filter some real data later in the tutorial.
Numpy has two main ways of exporting and importing data:
np.savetxt
:np.savetxt('test.txt', c, fmt='%f', delimiter=',', header='My favorite array')
cat test.txt
# My favorite array 0.000000,1.000000,2.000000,3.000000 4.000000,5.000000,6.000000,7.000000
test.npy
):np.save('test.npy', c)
np.loadtxt
or np.fromfile
np.loadtxt('test.txt',delimiter=',')
array([[0., 1., 2., 3.], [4., 5., 6., 7.]])
Numpy
and pandas
also provide a variety of tools to read specific data formats (csv, binary, etc.)numpy
¶Numpy has a full suite of tools for generating random numbers. Very helpful for Monte Carlo simulations or toy data.
Here we will generate 100k random floats from a normal distribution with mean = 2.0
and sigma = 1.0
.
r = np.random.normal(loc=2, scale=1, size=100000)
print(r[0:10])
[4.59294897 3.15374283 3.04135266 1.28198312 2.19810513 1.51165547 1.75905533 2.94476109 1.28497692 1.17879256]
We can randomly select elements from an array:
np.random.choice(a, size=2)
array([24, 32])
All the "heavy-lifting" is done in C
, so numpy
-based work can be very fast.
We can perform a Monte Carlo-based simulation to calculate $\pi$ using two uniform random number generators.
def mc_pi(num_trials):
x = np.random.uniform(low=0.0, high=1.0, size=num_trials)
y = np.random.uniform(low=0.0, high=1.0, size=num_trials)
r = x**2 + y**2
return len(r[r<1])*4/num_trials
for n in [10,100,1000,10000,100000,1000000,10000000]:
print(f"{n}: {mc_pi(n)}")
10: 3.2 100: 3.16 1000: 3.028 10000: 3.1464 100000: 3.13692 1000000: 3.142888 10000000: 3.1423868
import matplotlib.pyplot as plt
x = np.array([0,1,2,3,4,5])
y = np.power(x, 2)
plt.plot(x, y, marker='o', color='k', label='Square');
plt.xlabel('X-values');
plt.ylabel('Y-values');
plt.legend(loc=2);
x = np.array([0,2,4,6,8,10])
y = np.power(x, 2)
r = np.power(x, 3)
plt.scatter(x, y, s=r)
plt.xlabel('X-values'); plt.ylabel('Y-values');
Using our previously discussed Monte Carlo method for determining $\pi$, we can visualize this procedure in a few different ways.
First, we can make a scatter plot of one determination of Pi and show how the algorithm works. X and Y values are generated with a uniform random distribution and any which fall inside the shaded region (where x^2 + y^2 <= 1
) are counted.
plt.figure(figsize=(5,5))
ax = plt.gca()
circle = plt.Circle((0,0), radius=1, color='C4', alpha=0.3)
num_trials = 1000
x = np.random.uniform(low=0.0, high=1.0, size=num_trials)
y = np.random.uniform(low=0.0, high=1.0, size=num_trials)
plt.scatter(x,y,marker='.')
ax.add_patch(circle)
plt.ylim(0,1)
plt.xlim(0,1)
(0.0, 1.0)
Next, we can plot the evolution of our MC-generated value of $\pi$ as we increase the number of samples:
mc_pi_samples = np.logspace(start=1, stop=6, num=100, dtype='int')
mc_pi_values = [mc_pi(x) for x in mc_pi_samples]
plt.plot(mc_pi_samples, mc_pi_values, marker='o', linestyle='None', label='Monte Carlo')
plt.ylim(np.pi-1,np.pi+1)
plt.hlines(np.pi, xmin=0,xmax=np.max(mc_pi_samples), color='k', linestyle='--', label='Pi')
plt.xscale('log');
plt.legend()
plt.xlabel('MC Samples');
plt.ylabel('Simulated Value of Pi')
Text(0, 0.5, 'Simulated Value of Pi')
Combining numpy
and matplotlib
we can begin to generate some of the key plots that are used to display data. One of the most common types of data visualizations are histograms.
To get started, let's generate some random data using numpy.random
:
a = np.random.uniform(low=0, high=10, size=100000)
b = np.random.exponential(scale=1, size=100000)
Now we can create a histogram (tabulation of values into discrete bins)
h, bins = np.histogram(a, bins=20, range=(0,10))
and plot the distributions using matplotlib
:
plt.stairs(h, bins, label='Data')
plt.hlines(h.mean(), xmin=-0.25,xmax=10.25,linestyles='--', color='k', alpha=0.5, label='Average')
plt.xlabel('Value'); plt.ylabel('Counts/bin')
plt.legend(loc=3)
<matplotlib.legend.Legend at 0xffff759df0d0>
We can do the same to plot our exponential distribution of data, but this time we can set the y-scale to be log
to better highlight the distribution:
h, bins = np.histogram(b, bins=20, range=(0,10))
plt.stairs(h, bins, label='Data')
plt.xlabel('Value'); plt.ylabel('Counts/bin'); plt.yscale('log')
plt.legend(loc=0)
<matplotlib.legend.Legend at 0xffff77bba560>
Numpy
¶Now that we have a basic familiarity with numpy
, we will attempt to process some low-level data produced by a PMT connected to a scintillator cell.
A few key details about the data file:
Set the path to the data file and specify the trigger event properties.
from pathlib import Path
data_file = '180822-EJ309-1700V-Cf252.dat'
HEADER_SIZE = 4
WINDOW_SIZE = 300
data_file_path = Path.cwd().parent.joinpath('data', data_file)
Get header from the beginning of the file and first event trace.
header = np.fromfile(data_file_path, dtype=np.uint32,
count=HEADER_SIZE)
# Since each header item is 1 long-word (4 bytes)
# The data for 1st event begins 4 * HEADER_SIZE from the beginning of file
trace = np.fromfile(data_file_path, dtype=np.uint16,
count=WINDOW_SIZE, offset=HEADER_SIZE*4)
Plot the first trigger event trace.
plt.title(f"Channel: {header[1]}, Trigger: {header[2]}, TimeStamp: {header[3]}")
plt.plot(trace)
plt.xlabel('Samples');plt.ylabel('ADC');
Remove baseline counts
plt.title(f"Channel: {header[1]}, Trigger: {header[2]}, TimeStamp: {header[3]}")
plt.plot(trace)
plt.axvspan(xmin=0,xmax=50, color='C2',alpha=0.2)
plt.axvspan(xmin=50,xmax=300, color='C3',alpha=0.2)
plt.xlabel('Samples'); plt.ylabel('ADC');
Calculate the baseline from the average of the first 51 samples.
baseline = np.average(trace[0:50])
print(f"baseline: {baseline:0.2f}ADC")
baseline: 14614.12ADC
Subtract the baseline value from all the elments of the trace
array.
trace = np.subtract(trace, baseline)
plt.title(f"Channel: {header[1]}, Trigger: {header[2]}, TimeStamp: {header[3]}")
plt.plot(trace)
plt.axvspan(xmin=0,xmax=50, color='C2',alpha=0.2)
plt.axvspan(xmin=50,xmax=300, color='C3',alpha=0.2)
plt.xlabel('Samples');plt.ylabel('ADC');
Calculate the signal integral for the trigger event.
sig_int = -np.sum(trace)
print(f"signal integral: {sig_int:.2f}ADC counts")
signal integral: 913.00ADC counts
def data_reader(file_path, header_size=4, window_size=300, num_ev=10000):
with file_path.open(mode='r') as d:
# define data structure
dtype = [('time_stamp','f4'), ('en','f4'), ('psd', 'f4')]
data = np.zeros(shape=num_ev, dtype=dtype)
for i in range(num_ev):
header = np.fromfile(d, dtype=np.uint32, count=header_size)
data['time_stamp'][i] = header[3]
trace = np.fromfile(d, dtype=np.uint16, count=window_size)
# Average the first 30 samples to determine what "zero" is
bl = np.average(trace[0:30])
# Subtract off the baseline
trace = np.subtract(trace, bl)
# find the minimum of the pulse
peak_loc = np.argmin(trace)
# Integrate the full pulse
data['en'][i] = -np.sum(trace[peak_loc-30:peak_loc+100])
# Integrate the tail of the pulse, then take the ratio to the full
data['psd'][i] = -np.sum(trace[peak_loc+10:peak_loc+100])
data['psd'][i] /= data['en'][i]
return data
data = data_reader(data_file_path,
header_size=HEADER_SIZE,
window_size=WINDOW_SIZE,
num_ev=50000)
/tmp/ipykernel_7262/2814272060.py:27: RuntimeWarning: divide by zero encountered in float_scalars data['psd'][i] /= data['en'][i]
plt.plot(data['time_stamp'][0:1000], marker=',')
plt.xlabel('Event Counter');
plt.ylabel('Time Stamp');
h, bins = np.histogram(data['en'], bins=200, range=(0,100000))
plt.stairs(h, bins)
plt.yscale('log');
plt.xlabel('Pulse Integral (ADC)');
plt.ylabel('Counts/bin');
plt.hist2d(data['en'], data['psd'], bins=50, range=((0,50000),(0,0.5)), norm=LogNorm());
plt.xlabel('Pulse Integral (ADC)');
plt.ylabel('Tail-fraction (%)');
filter = data['en']>15000
h, bins = np.histogram(data['psd'][filter], bins=200, range=(0,0.5))
plt.stairs(h, bins, label='high-energy');
filter = data['en']<15000
h, bins = np.histogram(data['psd'][filter], bins=200, range=(0,0.5))
plt.stairs(h, bins, label='low-energy');
plt.xlabel('Tail-fraction (%)');plt.ylabel('Counts/bin'); plt.legend();
Pandas
¶The pandas
library builds on top of numpy
. It excels at processing tabular data of heterogenous types.
This example deals with an Excel worksheet used to track project activities.
string
and float
.Load the necessary modules
import numpy as np
import pandas as pd
from pathlib import Path
Load the Excel worksheet into a data frame
data_file = '02-VA BMTv3 20220225.xlsx'
worksheet_name = 'OUTPUT'
data_file_path = Path.cwd().parent.joinpath('data', data_file)
df = pd.read_excel(data_file_path, sheet_name=worksheet_name, header=[0, 1, 2])
df
INDEX VALUE | Priority | Team | Project Mgr. | Building Code | Building ID | Building Description | Cluster # | # closets | Legacy Switch Count | ... | Building Transitions Building Transitions | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
Unnamed: 0_level_1 | Unnamed: 1_level_1 | Unnamed: 2_level_1 | Unnamed: 3_level_1 | Unnamed: 4_level_1 | Unnamed: 5_level_1 | Unnamed: 6_level_1 | Unnamed: 7_level_1 | Unnamed: 8_level_1 | Unnamed: 9_level_1 | ... | Healthcare_VN | Voice_VN | PCI_VN | Building Communication Wired | Full Building Wired Network Services Cutover to NGN | Building Comms Wireless | Wireless Cutover to NGN | Legacy Cable & Equipment Removal | Building Comms Completion | Lessons Learned | |
Unnamed: 0_level_2 | Unnamed: 1_level_2 | Unnamed: 2_level_2 | Unnamed: 3_level_2 | Unnamed: 4_level_2 | Unnamed: 5_level_2 | Unnamed: 6_level_2 | Unnamed: 7_level_2 | Unnamed: 8_level_2 | Unnamed: 9_level_2 | ... | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | |
0 | 1.0 | 1.0 | NaN | NaN | VAMC-01 | 4160 | VA MEDICAL CTR BLDG 01 | C02-02 MDF | 9 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
1 | 2.0 | 2.0 | NaN | NaN | VAMC-02 | 4161 | VA MEDICAL CTR BLDG 02 | C02-02 | 4 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
2 | 3.0 | 3.0 | NaN | NaN | VAMC-03 | 41?? | VA MEDICAL CTR BLDG 03 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
3 | 4.0 | 4.0 | NaN | NaN | VAMC-04 | 4162 | VA MEDICAL CTR BLDG 04 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
4 | 5.0 | 5.0 | NaN | NaN | VAMC-05 | 4164 | VA MEDICAL CTR BLDG 05 | C02-01 MDF | 4 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
5 | 6.0 | 6.0 | NaN | NaN | VAMC-08 | 41?? | VA MEDICAL CTR BLDG 08 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
6 | 7.0 | 7.0 | NaN | NaN | VAMC-08.5 | 41?? | VA MEDICAL CTR BLDG 08.5 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
7 | 8.0 | 8.0 | NaN | NaN | VAMC-12A | 41?? | VA MEDICAL CTR BLDG 12A | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
8 | 9.0 | 9.0 | NaN | NaN | VAMC-34 | 4020 | VA MEDICAL CTR BLDG 34 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
9 | 10.0 | 10.0 | NaN | NaN | VAMC-35 | 41?? | VA MEDICAL CTR BLDG 35 | C02-01 | 2 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
10 | 11.0 | 11.0 | NaN | NaN | VAMC-35A | 4165 | VA MEDICAL CTR BLDG 35A | C02-01 | 2 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
11 | 12.0 | 12.0 | NaN | NaN | VAMC-36 | 41?? | VA MEDICAL CTR BLDG 36 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
12 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 28 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
13 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
14 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
15 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
16 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
17 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
18 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
19 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 12.0 | NaN | NaN | NaN | NaN | NaN |
20 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
21 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
22 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
23 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
24 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
25 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
26 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
27 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
28 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 12.0 | NaN | NaN | NaN | NaN | NaN |
29 rows × 63 columns
Collapse the column names by iterating through the list of the dataframes columns and creating a new list of column names, replacing any Unnamed
column with the value of the column name in level l2
)
flattened_column_names = [
(l1 if ('Unnamed:' in l2) else l2 ) for l1, l2, l3 in df.columns]
flattened_column_names
['INDEX VALUE', 'Priority', 'Team', 'Project Mgr.', 'Building Code', 'Building ID', 'Building Description', 'Cluster #', '# closets', 'Legacy Switch Count', 'NGN Switch Count', "AP's", 'Assigned General Building VN', 'Cutover Type', 'Known special use networks in building', 'Fabric Site Designation', 'Wired Migration Date\n(tentative)', 'Wireless Migration Date', 'STAGE 1', 'STAGE 2/3', 'Building', 'Program and Building Communication', 'Switch Discovery', 'Extension Discovery & Design', 'Inter-Fiber Discovery & Deployment', 'Building Comms Closet Communication', 'Closet Surveys', 'Bldg/Clstr -InterConnected Design', 'IP Discovery', 'Speciality VN Device Discovery', 'Firewall Review', 'WAP Predictive Review', 'Business Questionnaire', 'Building Comms DDNS Awareness', 'DDNS', 'IP, AV, & Printer Remediation', 'Walkthrough & Intrabuilding Architecture Design', 'BOM Process', 'Closet Remediation', 'Switch Hardware Staging', 'Logistics', 'Switch Rack & Stack', 'LAN Automation (Fabric Connection)', 'Building Communications', 'WAP Prep', 'QA Testing', 'Printers to NGN', 'Building Comms - User Specific App Testing Awareness - Building Ops Awareness', 'Specialty Devices to NGN', 'User Specific Testing', 'Safety_VN', 'BLDGSYS_VN', 'ScienceNet to NGN', 'Healthcare_VN', 'Voice_VN', 'PCI_VN', 'Building Communication Wired ', 'Full Building Wired Network Services Cutover to NGN', 'Building Comms Wireless ', 'Wireless Cutover to NGN', 'Legacy Cable & Equipment Removal', 'Building Comms Completion', 'Lessons Learned']
Rename the data frame columns with the flattened_column_names
df.columns = flattened_column_names
df
INDEX VALUE | Priority | Team | Project Mgr. | Building Code | Building ID | Building Description | Cluster # | # closets | Legacy Switch Count | ... | Healthcare_VN | Voice_VN | PCI_VN | Building Communication Wired | Full Building Wired Network Services Cutover to NGN | Building Comms Wireless | Wireless Cutover to NGN | Legacy Cable & Equipment Removal | Building Comms Completion | Lessons Learned | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1.0 | 1.0 | NaN | NaN | VAMC-01 | 4160 | VA MEDICAL CTR BLDG 01 | C02-02 MDF | 9 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
1 | 2.0 | 2.0 | NaN | NaN | VAMC-02 | 4161 | VA MEDICAL CTR BLDG 02 | C02-02 | 4 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
2 | 3.0 | 3.0 | NaN | NaN | VAMC-03 | 41?? | VA MEDICAL CTR BLDG 03 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
3 | 4.0 | 4.0 | NaN | NaN | VAMC-04 | 4162 | VA MEDICAL CTR BLDG 04 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
4 | 5.0 | 5.0 | NaN | NaN | VAMC-05 | 4164 | VA MEDICAL CTR BLDG 05 | C02-01 MDF | 4 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
5 | 6.0 | 6.0 | NaN | NaN | VAMC-08 | 41?? | VA MEDICAL CTR BLDG 08 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
6 | 7.0 | 7.0 | NaN | NaN | VAMC-08.5 | 41?? | VA MEDICAL CTR BLDG 08.5 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
7 | 8.0 | 8.0 | NaN | NaN | VAMC-12A | 41?? | VA MEDICAL CTR BLDG 12A | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
8 | 9.0 | 9.0 | NaN | NaN | VAMC-34 | 4020 | VA MEDICAL CTR BLDG 34 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
9 | 10.0 | 10.0 | NaN | NaN | VAMC-35 | 41?? | VA MEDICAL CTR BLDG 35 | C02-01 | 2 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
10 | 11.0 | 11.0 | NaN | NaN | VAMC-35A | 4165 | VA MEDICAL CTR BLDG 35A | C02-01 | 2 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
11 | 12.0 | 12.0 | NaN | NaN | VAMC-36 | 41?? | VA MEDICAL CTR BLDG 36 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
12 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 28 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
13 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
14 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
15 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
16 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
17 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
18 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
19 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 12.0 | NaN | NaN | NaN | NaN | NaN |
20 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
21 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
22 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
23 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
24 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
25 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
26 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
27 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
28 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 12.0 | NaN | NaN | NaN | NaN | NaN |
29 rows × 63 columns
The column names should be converted the names of the fields used by the relational database.
sql_table_fields = [
'index',
'priority',
'team',
'project_manager',
'building_code',
'building_id',
'building_description',
'cluster_number',
'number_closets',
'legacy_switch_count',
'ngn_switch_count',
'aps',
'assigned_building_vn',
'cutover_type',
'known_special_networks',
'fabric_site_designation',
'wired_migration_date',
'wireless_migration_date',
'stage_1_complete',
'stage_2_3_complete',
'building_complete',
'program_building_communication',
'switch_discovery',
'extension_discovery',
'inter_fiber',
'building_coms_closet',
'closet_surveys',
'bldg_clstr_design',
'ip_discovery',
'speciality_vn',
'firewall_review',
'wap_predictive_review',
'business_questionnaire',
'building_comms_ddns',
'ddns',
'ip_av_printer_remediation',
'walkthrough_intrabuilding',
'bom_process',
'closet_remediation',
'switch_hardware_staging',
'logistics',
'switch_rack_stack',
'lan_automation',
'building_comms',
'wap_prep',
'qa_testing',
'printers_ngn',
'building_comms_app_testing',
'specialty_devices',
'user_specific_testing',
'safety_vn',
'bldgsys_vn',
'sciencenet_ngn',
'healthcare_vn',
'voice_vn',
'pci_vn',
'building_comms_wired',
'full_building_wired_cutover_ngn',
'building_comms_wireless',
'wireless_cutover_ngn',
'legacy_cable_removal',
'building_comms_completion',
'lessons_learned']
Construct a lookup dictionary of flattened_column_names
to sql_table_fields
rename_map = dict(zip(flattened_column_names, sql_table_fields))
rename_map
{'INDEX VALUE': 'index', 'Priority': 'priority', 'Team': 'team', 'Project Mgr.': 'project_manager', 'Building Code': 'building_code', 'Building ID': 'building_id', 'Building Description': 'building_description', 'Cluster #': 'cluster_number', '# closets': 'number_closets', 'Legacy Switch Count': 'legacy_switch_count', 'NGN Switch Count': 'ngn_switch_count', "AP's": 'aps', 'Assigned General Building VN': 'assigned_building_vn', 'Cutover Type': 'cutover_type', 'Known special use networks in building': 'known_special_networks', 'Fabric Site Designation': 'fabric_site_designation', 'Wired Migration Date\n(tentative)': 'wired_migration_date', 'Wireless Migration Date': 'wireless_migration_date', 'STAGE 1': 'stage_1_complete', 'STAGE 2/3': 'stage_2_3_complete', 'Building': 'building_complete', 'Program and Building Communication': 'program_building_communication', 'Switch Discovery': 'switch_discovery', 'Extension Discovery & Design': 'extension_discovery', 'Inter-Fiber Discovery & Deployment': 'inter_fiber', 'Building Comms Closet Communication': 'building_coms_closet', 'Closet Surveys': 'closet_surveys', 'Bldg/Clstr -InterConnected Design': 'bldg_clstr_design', 'IP Discovery': 'ip_discovery', 'Speciality VN Device Discovery': 'speciality_vn', 'Firewall Review': 'firewall_review', 'WAP Predictive Review': 'wap_predictive_review', 'Business Questionnaire': 'business_questionnaire', 'Building Comms DDNS Awareness': 'building_comms_ddns', 'DDNS': 'ddns', 'IP, AV, & Printer Remediation': 'ip_av_printer_remediation', 'Walkthrough & Intrabuilding Architecture Design': 'walkthrough_intrabuilding', 'BOM Process': 'bom_process', 'Closet Remediation': 'closet_remediation', 'Switch Hardware Staging': 'switch_hardware_staging', 'Logistics': 'logistics', 'Switch Rack & Stack': 'switch_rack_stack', 'LAN Automation (Fabric Connection)': 'lan_automation', 'Building Communications': 'building_comms', 'WAP Prep': 'wap_prep', 'QA Testing': 'qa_testing', 'Printers to NGN': 'printers_ngn', 'Building Comms - User Specific App Testing Awareness - Building Ops Awareness': 'building_comms_app_testing', 'Specialty Devices to NGN': 'specialty_devices', 'User Specific Testing': 'user_specific_testing', 'Safety_VN': 'safety_vn', 'BLDGSYS_VN': 'bldgsys_vn', 'ScienceNet to NGN': 'sciencenet_ngn', 'Healthcare_VN': 'healthcare_vn', 'Voice_VN': 'voice_vn', 'PCI_VN': 'pci_vn', 'Building Communication Wired ': 'building_comms_wired', 'Full Building Wired Network Services Cutover to NGN': 'full_building_wired_cutover_ngn', 'Building Comms Wireless ': 'building_comms_wireless', 'Wireless Cutover to NGN': 'wireless_cutover_ngn', 'Legacy Cable & Equipment Removal': 'legacy_cable_removal', 'Building Comms Completion': 'building_comms_completion', 'Lessons Learned': 'lessons_learned'}
Rename the dataframe fields
df.rename(columns=rename_map, inplace=True)
df
index | priority | team | project_manager | building_code | building_id | building_description | cluster_number | number_closets | legacy_switch_count | ... | healthcare_vn | voice_vn | pci_vn | building_comms_wired | full_building_wired_cutover_ngn | building_comms_wireless | wireless_cutover_ngn | legacy_cable_removal | building_comms_completion | lessons_learned | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 1.0 | 1.0 | NaN | NaN | VAMC-01 | 4160 | VA MEDICAL CTR BLDG 01 | C02-02 MDF | 9 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
1 | 2.0 | 2.0 | NaN | NaN | VAMC-02 | 4161 | VA MEDICAL CTR BLDG 02 | C02-02 | 4 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
2 | 3.0 | 3.0 | NaN | NaN | VAMC-03 | 41?? | VA MEDICAL CTR BLDG 03 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
3 | 4.0 | 4.0 | NaN | NaN | VAMC-04 | 4162 | VA MEDICAL CTR BLDG 04 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
4 | 5.0 | 5.0 | NaN | NaN | VAMC-05 | 4164 | VA MEDICAL CTR BLDG 05 | C02-01 MDF | 4 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
5 | 6.0 | 6.0 | NaN | NaN | VAMC-08 | 41?? | VA MEDICAL CTR BLDG 08 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
6 | 7.0 | 7.0 | NaN | NaN | VAMC-08.5 | 41?? | VA MEDICAL CTR BLDG 08.5 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
7 | 8.0 | 8.0 | NaN | NaN | VAMC-12A | 41?? | VA MEDICAL CTR BLDG 12A | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
8 | 9.0 | 9.0 | NaN | NaN | VAMC-34 | 4020 | VA MEDICAL CTR BLDG 34 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
9 | 10.0 | 10.0 | NaN | NaN | VAMC-35 | 41?? | VA MEDICAL CTR BLDG 35 | C02-01 | 2 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
10 | 11.0 | 11.0 | NaN | NaN | VAMC-35A | 4165 | VA MEDICAL CTR BLDG 35A | C02-01 | 2 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
11 | 12.0 | 12.0 | NaN | NaN | VAMC-36 | 41?? | VA MEDICAL CTR BLDG 36 | C02-01 | 1 | NaN | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
12 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 28 | 0.0 | ... | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 | 0.0 |
13 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
14 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
15 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | |
16 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
17 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
18 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
19 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 12.0 | NaN | NaN | NaN | NaN | NaN |
20 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
21 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
22 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
23 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
24 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
25 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
26 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 0.0 | NaN | NaN | NaN | NaN | NaN |
27 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
28 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | ... | NaN | NaN | NaN | NaN | 12.0 | NaN | NaN | NaN | NaN | NaN |
29 rows × 63 columns
NaN
archive_date column
with current date to note date of import into tablestring
data type for columns with strings and standardize string valuesstring
to float
We've only scratched the surface of what python can do for data analysis.
JupyterLab lends itself well to exploratory data analysis.
Online Resources:
Further reading (O'Reilly Books available through Yale Library):