test

In [1]:
import folium
import pandas as pd


url = (
    "https://raw.githubusercontent.com/python-visualization/folium/master/examples/data"
)
state_geo = f"{url}/us-states.json"
state_unemployment = f"{url}/US_Unemployment_Oct2012.csv"

state_data = pd.read_csv(state_unemployment)

m = folium.Map(location=[48, -102], zoom_start=3, tiles="Stamen Toner")

folium.Choropleth(
    state_geo,
    data=state_data,
    columns=["State", "Unemployment"],
    key_on="feature.id",
    fill_color="YlGn",
    fill_opacity=0.7,
    line_opacity=0.2,
    legend_name="Unemployment Rate (%)",
).add_to(m)


popup = "Must be on top of the choropleth"

folium.CircleMarker(
    location=[48, -102],
    radius=10,
    fill=True,
    popup=popup,
    weight=1,
).add_to(m)


m
Out[1]:
Make this Notebook Trusted to load map: File -> Trust Notebook

Basic datatypes

In [1]:
x=1
y=2
In [2]:
print(x)
1
In [5]:
x = 16   # integer
y = 2.6  # float
z = 'abc' # string
# this is a comment
In [4]:
print(z)
abc
In [7]:
result = x+y
In [8]:
print(result)
18.6
In [9]:
365*10
Out[9]:
3650
In [10]:
365*24
Out[10]:
8760
In [11]:
a = True
In [12]:
not a
Out[12]:
False

Other useful python types

In [13]:
# list
l = [1, 2, 3, 'abc', 3.5, True, [4,5,6]]
In [14]:
# indexing starts at 0!
l[3]
Out[14]:
'abc'
In [15]:
# tuple
t = (1,2,3)
In [16]:
t[1]
Out[16]:
2
In [17]:
# tuples are like lists, but lists are more flexible
l.append(89.7)
In [18]:
l
Out[18]:
[1, 2, 3, 'abc', 3.5, True, [4, 5, 6], 89.7]
In [19]:
# the syntax object.method() is very common
l.reverse()
In [20]:
l
Out[20]:
[89.7, [4, 5, 6], True, 3.5, 'abc', 3, 2, 1]
In [21]:
# dictionary
d = {'a': 1, 'b': 2}
In [22]:
d['a']
Out[22]:
1
In [23]:
colors = ['red', 'green', 'blue', 'black']
d['red'] = (255, 0, 0)
d['blue'] = (0,0,255)
In [24]:
d['red']
Out[24]:
(255, 0, 0)
In [25]:
d
Out[25]:
{'a': 1, 'b': 2, 'red': (255, 0, 0), 'blue': (0, 0, 255)}
In [26]:
list(d.keys())
Out[26]:
['a', 'b', 'red', 'blue']
In [27]:
list(d.values())
Out[27]:
[1, 2, (255, 0, 0), (0, 0, 255)]

Numpy

In [28]:
import numpy as np
In [31]:
a = np.array([0,1,2,3,4,5])
In [38]:
# an example of method access
a.max()
Out[38]:
5
In [39]:
# ndim is one of the attributes of a numpy array.
a.ndim
Out[39]:
1
In [40]:
a.shape
Out[40]:
(6,)
In [41]:
b = np.array([[0,1,2,3,4], [5,6,7,8,9]])
In [42]:
b.ndim
Out[42]:
2
In [44]:
b
Out[44]:
array([[0, 1, 2, 3, 4],
       [5, 6, 7, 8, 9]])
In [45]:
b.shape
Out[45]:
(2, 5)
In [46]:
# The vertical axis is always the first
# This is second row, third column
b[1,2]
Out[46]:
7
In [47]:
# This is a mistake
b = np.array([[0,1,2,3,4], [5,6,7,8]])
<ipython-input-47-544cf3fda5d7>:1: VisibleDeprecationWarning: Creating an ndarray from ragged nested sequences (which is a list-or-tuple of lists-or-tuples-or ndarrays with different lengths or shapes) is deprecated. If you meant to do this, you must specify 'dtype=object' when creating the ndarray
  b = np.array([[0,1,2,3,4], [5,6,7,8]])
In [50]:
my_zeros = np.zeros((2000,2000))
In [53]:
# top corner
my_zeros[0,0] = 1
my_zeros
Out[53]:
array([[1., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]])
In [54]:
# set first row to 1
my_zeros[0,:] = 1
my_zeros
Out[54]:
array([[1., 1., 1., ..., 1., 1., 1.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]])
In [55]:
# set 3 first elements of second row to 2
my_zeros[1,0:3] = 2
# equivalent is my_zeros[1,:3]
my_zeros
Out[55]:
array([[1., 1., 1., ..., 1., 1., 1.],
       [2., 2., 2., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]])
In [56]:
# set last 2 elements of first column to 6
my_zeros[-2:, 0] = 6
my_zeros
Out[56]:
array([[1., 1., 1., ..., 1., 1., 1.],
       [2., 2., 2., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [6., 0., 0., ..., 0., 0., 0.],
       [6., 0., 0., ..., 0., 0., 0.]])
In [58]:
# set a square 100x100 with top corner at (350, 450) to 10.
my_zeros[350:450, 450:550] = 10
In [60]:
my_piece_of_my_zeros = my_zeros[:2,:2]
In [61]:
my_piece_of_my_zeros
# Tricky: this is a "view" on the original array, not a copy
Out[61]:
array([[1., 1.],
       [2., 2.]])
In [62]:
my_piece_of_my_zeros[0,0] = 5
my_piece_of_my_zeros
Out[62]:
array([[5., 1.],
       [2., 2.]])
In [63]:
my_zeros
Out[63]:
array([[5., 1., 1., ..., 1., 1., 1.],
       [2., 2., 2., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [6., 0., 0., ..., 0., 0., 0.],
       [6., 0., 0., ..., 0., 0., 0.]])
In [82]:
my_zeros.dtype # float64 - also known as double-precision float (8 byte = 64 bit)
Out[82]:
dtype('float64')
In [64]:
# Typical mistake:
first = np.zeros((100,100))
second = first[:40,:50]
first[0,0] = 1
# This would modify 'second' as well!
In [65]:
# solution
first = np.zeros((100,100))
second = first[:40, :50].copy()
# OR
second = first[:40, :50] + 0.
In [66]:
# operations on arrays
first = np.zeros((100,100))
second = np.ones((100,100))
In [69]:
first*second
Out[69]:
array([[0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       ...,
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.],
       [0., 0., 0., ..., 0., 0., 0.]])
In [70]:
i, j = np.indices((100,100))
In [71]:
i
Out[71]:
array([[ 0,  0,  0, ...,  0,  0,  0],
       [ 1,  1,  1, ...,  1,  1,  1],
       [ 2,  2,  2, ...,  2,  2,  2],
       ...,
       [97, 97, 97, ..., 97, 97, 97],
       [98, 98, 98, ..., 98, 98, 98],
       [99, 99, 99, ..., 99, 99, 99]])
In [72]:
j
Out[72]:
array([[ 0,  1,  2, ..., 97, 98, 99],
       [ 0,  1,  2, ..., 97, 98, 99],
       [ 0,  1,  2, ..., 97, 98, 99],
       ...,
       [ 0,  1,  2, ..., 97, 98, 99],
       [ 0,  1,  2, ..., 97, 98, 99],
       [ 0,  1,  2, ..., 97, 98, 99]])
In [73]:
i[34, 78]
Out[73]:
34
In [74]:
j[34,78]
Out[74]:
78
In [75]:
(i - 50)
# (in place operation )
# i -= 50 
# result is same as i = i - 50
Out[75]:
array([[-50, -50, -50, ..., -50, -50, -50],
       [-49, -49, -49, ..., -49, -49, -49],
       [-48, -48, -48, ..., -48, -48, -48],
       ...,
       [ 47,  47,  47, ...,  47,  47,  47],
       [ 48,  48,  48, ...,  48,  48,  48],
       [ 49,  49,  49, ...,  49,  49,  49]])
In [76]:
j - 50
Out[76]:
array([[-50, -49, -48, ...,  47,  48,  49],
       [-50, -49, -48, ...,  47,  48,  49],
       [-50, -49, -48, ...,  47,  48,  49],
       ...,
       [-50, -49, -48, ...,  47,  48,  49],
       [-50, -49, -48, ...,  47,  48,  49],
       [-50, -49, -48, ...,  47,  48,  49]])
In [77]:
r = np.sqrt((i-50)**2 + (j-50)**2)
In [81]:
r[48:52,48:52]
Out[81]:
array([[2.82842712, 2.23606798, 2.        , 2.23606798],
       [2.23606798, 1.41421356, 1.        , 1.41421356],
       [2.        , 1.        , 0.        , 1.        ],
       [2.23606798, 1.41421356, 1.        , 1.41421356]])
In [ ]:
# Some more discussion about memory
r0 = r
r += 1  # will apply to r0
r = r+1 # Now r is a new object different from r0