NumPy Basics

wordcloud

Numpy is the fundamental package for numeric computing with Python. It provides powerful ways to create, store, and/or manipulate data, which makes it able to seamlessly and speedily integrate with a wide variety of databases. This is also the foundation that Pandas is built on, which is a high-performance data-centric package that we will learn later in the course.

We will discuss creating array with certain data types, manipulating array, selecting elements from arrays, and loading dataset into array. Such functions are useful for manipulating data and understanding the functionalities of other common Python data packages.

In [1]:
# Importing numpy
import numpy as np
import math

Array Creation

Arrays are displayed as a list or list of lists and can be created through list as well. When creating an array, we pass in a list as an argument in numpy array

In [2]:
a = np.array([1, 2, 3])
print(a)
# We can print the number of dimensions of a list using the ndim attribute
print(a.ndim)
[1 2 3]
1


If we pass in a list of lists in numpy array, we create a multi-dimensional array, for instance, a matrix

In [3]:
b = np.array([[1,2,3],[4,5,6]])
b
Out[3]:
array([[1, 2, 3],
       [4, 5, 6]])

We can print out the length of each dimension by calling the shape attribute, which returns a tuple
In [4]:
b.shape
Out[4]:
(2, 3)

We can also check the type of items in the array
In [5]:
a.dtype
Out[5]:
dtype('int32')


Besides integers, floats are also accepted in numpy arrays

In [6]:
c = np.array([2.2, 5, 1.1])
c.dtype.name
Out[6]:
'float64'


Let's look at the data in our array

In [7]:
c
Out[7]:
array([2.2, 5. , 1.1])

Note that numpy automatically converts integers, like 5, up to floats, since there is no loss of prescision. Numpy will try and give you the best data type format possible to keep your data types homogeneous, which means all the same, in the array.

Sometimes we know the shape of an array that we want to create, but not what we want to be in it. numpy offers several functions to create arrays with initial placeholders, such as zero's or one's. Lets create two arrays, both the same shape but with different filler values

In [8]:
d = np.zeros((2,3))
print(d)

e = np.ones((2,3))
print(e)
[[0. 0. 0.]
 [0. 0. 0.]]
[[1. 1. 1.]
 [1. 1. 1.]]


We can also generate an array with random numbers

In [9]:
np.random.rand(2,3)
Out[9]:
array([[0.3681332 , 0.7081959 , 0.15639652],
       [0.08662497, 0.66082932, 0.12181075]])


You'll see zeros, ones, and rand used quite often to create example arrays, especially in stack overflow posts and other forums.

We can also create a sequence of numbers in an array with the arrange() function. The fist argument is the starting bound and the second argument is the ending bound, and the third argument is the difference between each consecutive numbers

Let's create an array of every even number from ten (inclusive) to fifty (exclusive)

In [10]:
f = np.arange(10, 50, 2)
f
Out[10]:
array([10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42,
       44, 46, 48])


if we want to generate a sequence of floats, we can use the linspace() function. In this function the third argument isn't the difference between two numbers, but the total number of items you want to generate

In [11]:
np.linspace( 0, 2, 15 ) # 15 numbers from 0 (inclusive) to 2 (inclusive)
Out[11]:
array([0.        , 0.14285714, 0.28571429, 0.42857143, 0.57142857,
       0.71428571, 0.85714286, 1.        , 1.14285714, 1.28571429,
       1.42857143, 1.57142857, 1.71428571, 1.85714286, 2.        ])

[^top]

Array Operations

We can do many things on arrays, such as mathematical manipulation (addition, subtraction, square, exponents) as well as use boolean arrays, which are binary values. We can also do matrix manipulation such as product, transpose, inverse, and so forth.

Arithmetic operators on array apply elementwise.

In [12]:
# Let's create a couple of arrays
a = np.array([10,20,30,40])
b = np.array([1, 2, 3,4])

# Now let's look at a minus b
c = a-b
print(c)

# And let's look at a times b
d = a*b
print(d)
[ 9 18 27 36]
[ 10  40  90 160]


With arithmetic manipulation, we can convert current data to the way we want it to be. Here is an example of a real worls problem. Metric system is a unit system that is adopted by most countries in the world. It is also the the standard unit system for scientific and mathematical research. However, US still uses Imperial units system for some measurements such as distance and volume. Before we work on any such data, we need to first convert it to metric system. Let's convert vehicle mileage from the imperial "Miles per gallon (mpg)" to the metric standard of "Kilometers per litre (kmpl)".

1 mile = 1.609344 kilometers.

1 gallon = 3.785412 liters.

1 mpg = (1.609344/3.785412) kmpl

In [13]:
# Let's create an array of typical car mileage values
mpg = np.array([17,18.8,25.2,22.6,30.4])

# Converting to KMPL
kmpl = mpg * round((1.609344/3.785412),1)
kmpl
Out[13]:
array([ 6.8 ,  7.52, 10.08,  9.04, 12.16])


Another useful and important manipulation is the boolean array. We can apply an operator on an array, and a boolean array will be returned for any element in the original, with True being emitted if it meets the condition and False oetherwise. For instance, if we want to get a boolean array to check mileage greater than 10 kmpl.

In [14]:
kmpl>10
Out[14]:
array([False, False,  True, False,  True])


Besides elementwise manipulation, it is important to know that numpy supports matrix manipulation. Let's look at matrix product. if we want to do elementwise product, we use the "*" sign. Numpy is capable of doing both element-wise operations (the asterix) as well as matrix-level operations (the @ sign).

In [15]:
A = np.array([[1,1],[0,1]])
print("A=\n{}".format(A))
B = np.array([[2,0],[3,4]])
print("\nB=\n{}".format(B))
print("\nElementwise product using *")
print(A*B)

# if we want to do matrix product, we use the "@" sign or use the dot function
print("\nMatrixproduct using @")
print(A@B)
A=
[[1 1]
 [0 1]]

B=
[[2 0]
 [3 4]]

Elementwise product using *
[[2 0]
 [0 4]]

Matrixproduct using @
[[5 4]
 [3 4]]


We can use numpy to quickly see the shape of a matrix:

In [16]:
A.shape
Out[16]:
(2, 2)


When manipulating arrays of different types, the type of the resulting array will correspond to the more general of the two types. This is called upcasting.

In [17]:
# Let's create an array of integers
array1 = np.array([[1, 2, 3], [4, 5, 6]])
print(array1.dtype)

# Now let's create an array of floats
array2 = np.array([[7.1, 8.2, 9.1], [10.4, 11.2, 12.3]])
print(array2.dtype)
int32
float64


Integers (int) are whole numbers only, and Floating point numbers (float) can have a whole number portion and a decimal portion. The 64 in this example refers to the number of bits that the operating system is reserving to represent the number, which determines the size (or precision) of the numbers that can be represented.

In [18]:
# Let's do an addition for the two arrays
array3=array1+array2
print(array3)
print(array3.dtype)
[[ 8.1 10.2 12.1]
 [14.4 16.2 18.3]]
float64

Notice how the items in the resulting array have been upcast into floating point numbers.

Numpy arrays have many interesting aggregation functions on them, such as sum(), max(), min(), and mean()

In [19]:
print(array3.sum())
print(array3.max())
print(array3.min())
print(array3.mean())
79.3
18.3
8.1
13.216666666666667


For two dimensional arrays, we can do the same thing for each row or column let's create an array with 15 elements, ranging from 1 to 15, with a dimension of 3X5

In [20]:
b = np.arange(1,16,1).reshape(3,5)
print(b)
[[ 1  2  3  4  5]
 [ 6  7  8  9 10]
 [11 12 13 14 15]]


Now, we often think about two dimensional arrays being made up of rows and columns, but you can also think of these arrays as just a giant ordered list of numbers, and the shape of the array, the number of rows and columns, is just an abstraction that we have for a particular purpose. Actually, this is exactly how basic images are stored in computer environments.

Let's take a look at an example and see how numpy comes into play.

In [21]:
from PIL import Image
# from IPython.display import display

# Opening an image
img = Image.open('../../files/py/009/CatSketch.jpg')
display(img)
No description has been provided for this image
In [22]:
# Now, we can conver this PIL image to a numpy array
array=np.array(img)
print(array.shape)
array
(640, 360)
Out[22]:
array([[ 83, 124, 144, ...,  80,  69, 101],
       [ 41,  90, 100, ...,   0,   0,  41],
       [ 47,  91,  93, ...,  10,   0,  47],
       ...,
       [ 29,   3,   2, ...,  15,  52,  65],
       [ 29,   0,   0, ...,   3,   9,  48],
       [ 75,  62,  61, ...,  62,  69,  77]], dtype=uint8)


Here we see that we have a 640x360 array and that the values are all uint8. The uint means that they are unsigned integers (so no negative numbers) and the 8 means 8 bits per byte. This means that each value can be up to 2222222*2=256 in size (well, actually 255, because we start at zero). For black and white images black is stored as 0 and white is stored as 255. So if we just wanted to invert this image we could use the numpy array to do so by subtracting each pixel(element of the array) from from 255.

In [23]:
inverse_array = 255-array
inverse_array
Out[23]:
array([[172, 131, 111, ..., 175, 186, 154],
       [214, 165, 155, ..., 255, 255, 214],
       [208, 164, 162, ..., 245, 255, 208],
       ...,
       [226, 252, 253, ..., 240, 203, 190],
       [226, 255, 255, ..., 252, 246, 207],
       [180, 193, 194, ..., 193, 186, 178]], dtype=uint8)


And lastly, lets display this new array. We do this by using the fromarray() function in the python imaging library to convert the numpy array into an object jupyter can render

In [24]:
display(Image.fromarray(inverse_array))
No description has been provided for this image


PIL is interpreting the individual rows as lines, so we can change the number of lines and columns if we want to. Let's reshape the image from 640x360 px to 320x720 px. We need to ensure that the total pixels remain the same for this to work.

In [25]:
reshaped=np.reshape(array,(320,720))
print(reshaped.shape)
display(Image.fromarray(reshaped))
(320, 720)
No description has been provided for this image

By reshaping the array to be only 320 rows high but 720 columns we've essentially doubled the image by taking every other line and stacking them out in width. This makes the image look more stretched out .

[^top]

Indexing, Slicing and Iterating

Indexing, slicing and iterating are extremely important for data manipulation and analysis because these techinques allow us to select data based on conditions, and copy or update data.

Indexing

First we are going to look at integer indexing. A one-dimensional array, works in similar ways as a list - To get an element in a one-dimensional array, we simply use the offset index.

In [26]:
a = np.array([1,3,5,7])
a[2]
Out[26]:
5


For multidimensional array, we need to use integer array indexing, let's create a new multidimensional array

In [27]:
a = np.array([[1,2], [3, 4], [5, 6]])
a
Out[27]:
array([[1, 2],
       [3, 4],
       [5, 6]])


If we want to select one certain element, we can do so by entering the index, which is comprised of two integers the first being the row, and the second the column

In [28]:
a[1,1] # remember in python we start at 0!
Out[28]:
4


If we want to get multiple elements for example, 1, 4, and 6 and put them into a one-dimensional array we can enter the indices directly into an array function

In [29]:
np.array([a[0, 0], a[1, 1], a[2, 1]])
Out[29]:
array([1, 4, 6])


we can also do that by using another form of array indexing, which essentiall "zips" the first list and the second list up

In [30]:
print(a[[0, 1, 2], [0, 1, 1]])
[1 4 6]

Boolean Indexing

Boolean indexing allows us to select arbitrary elements based on conditions. For example, if we want to find elements that are greater than 5, we set up a conditon a >5. This returns a boolean array showing that if the value at the corresponding index is greater than 5

In [31]:
print(a >5)
[[False False]
 [False False]
 [False  True]]


We can then place this array of booleans like a mask over the original array to return a one-dimensional array relating to the true values.

In [32]:
print(a[a>5])
[6]

Slicing


Slicing is a way to create a sub-array based on the original array. For one-dimensional arrays, slicing works in similar ways to a list. To slice, we use the : sign. For instance, if we put :3 in the indexing brackets, we get elements from index 0 to index 3 (excluding index 3)

In [33]:
a = np.array([0,1,2,3,4,5])
print(a[:3])
[0 1 2]


By putting 2:4 in the bracket, we get elements from index 2 to index 4 (excluding index 4)

In [34]:
print(a[2:4])
[2 3]


For multi-dimensional arrays, it works similarly, lets see an example

In [35]:
a = np.array([[1,2,3,4], [5,6,7,8], [9,10,11,12]])
a
Out[35]:
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])


First, if we put one argument in the array, for example a[:2] then we would get all the elements from the first (0th) and second row (1st)

In [36]:
a[:2]
Out[36]:
array([[1, 2, 3, 4],
       [5, 6, 7, 8]])


If we add another argument to the array, for example a[:2, 1:3], we get the first two rows but then the second and third column values only

In [37]:
a[:2, 1:3]
Out[37]:
array([[2, 3],
       [6, 7]])


So, in multidimensional arrays, the first argument is for selecting rows, and the second argument is for selecting columns.

It is important to realize that a slice of an array is a view into the same data. This is called passing by reference. So modifying the sub array will consequently modify the original array.

Here I'll change the element at position [0, 0], which is 2, to 50, then we can see that the value in the original array is changed to 50 as well.

In [38]:
sub_array = a[:2, 1:3]
print("sub array index [0,0] value before change:", sub_array[0,0])
sub_array[0,0] = 50
print("sub array index [0,0] value after change:", sub_array[0,0])
print("original array index [0,1] value after change:", a[0,1])
sub array index [0,0] value before change: 2
sub array index [0,0] value after change: 50
original array index [0,1] value after change: 50

[^top]

Trying Numpy with Datasets

Now that we have learned the essentials of Numpy let's use it on a couple of datasets.

Here we have a very popular dataset on wine quality, and we are going to only look at red wines. The data fields include: fixed acidity, volatile aciditycitric acid, residual sugar, chlorides, free sulfur dioxide, total sulfur dioxidedensity, pH, sulphates, alcohol and quality.

The data file winequality-red.csv is located in the GitLab reporsitory. More information on the GitLabRead function to read files from GitLab is available in my article.

In [39]:
from pyGitLab import gl2StrObj

To load a dataset in Numpy, we can use the genfromtxt() function. We can specify data file name, delimiter (which is optional but often used), and number of rows to skip if we have a header row, hence it is 1 here.

The genfromtxt() function has a parameter called dtype for specifying data types of each column this parameter is optional. Without specifying the types, all types will be casted the same to the more general/precise type.

In [40]:
wines = np.genfromtxt(gl2StrObj('winequality-red.csv',23134556), delimiter=";", skip_header=1)
wines
Out[40]:
array([[ 7.4  ,  0.7  ,  0.   , ...,  0.56 ,  9.4  ,  5.   ],
       [ 7.8  ,  0.88 ,  0.   , ...,  0.68 ,  9.8  ,  5.   ],
       [ 7.8  ,  0.76 ,  0.04 , ...,  0.65 ,  9.8  ,  5.   ],
       ...,
       [ 6.3  ,  0.51 ,  0.13 , ...,  0.75 , 11.   ,  6.   ],
       [ 5.9  ,  0.645,  0.12 , ...,  0.71 , 10.2  ,  5.   ],
       [ 6.   ,  0.31 ,  0.47 , ...,  0.66 , 11.   ,  6.   ]])


Recall that we can use integer indexing to get a certain column or a row. For example, if we want to select the fixed acidity column, which is the first coluumn, we can do so by entering the index into the array. Also remember that for multidimensional arrays, the first argument refers to the row, and the second argument refers to the column, and if we just give one argument then we'll get a single dimensional list back.

So all rows combined but only the first column from them would be

In [41]:
print("one integer 0 for slicing: ", wines[:, 0])
one integer 0 for slicing:  [7.4 7.8 7.8 ... 6.3 5.9 6. ]


But if we wanted the same values but wanted to preserve that they sit in their own rows we would write

In [42]:
print("0 to 1 for slicing: \n", wines[:, 0:1])
0 to 1 for slicing: 
 [[7.4]
 [7.8]
 [7.8]
 ...
 [6.3]
 [5.9]
 [6. ]]


This is another great example of how the shape of the data is an abstraction which we can layer intentionally on top of the data we are working with.

If we want a range of columns in order, say columns 0 through 3 (recall, this means first, second, and third, since we start at zero and don't include the training index value), we can do that too

In [43]:
wines[:, 0:3]
Out[43]:
array([[7.4  , 0.7  , 0.   ],
       [7.8  , 0.88 , 0.   ],
       [7.8  , 0.76 , 0.04 ],
       ...,
       [6.3  , 0.51 , 0.13 ],
       [5.9  , 0.645, 0.12 ],
       [6.   , 0.31 , 0.47 ]])


What if we want several non-consecutive columns? We can place the indices of the columns that we want into an array and pass the array as the second argument. Here's an example

In [44]:
wines[:, [0,2,5]]
Out[44]:
array([[ 7.4 ,  0.  , 11.  ],
       [ 7.8 ,  0.  , 25.  ],
       [ 7.8 ,  0.04, 15.  ],
       ...,
       [ 6.3 ,  0.13, 29.  ],
       [ 5.9 ,  0.12, 32.  ],
       [ 6.  ,  0.47, 18.  ]])


We can also do some basic summarization of this dataset. For example, if we want to find out the average quality of red wine, we can select the quality column. We could do this in a couple of ways, but the most appropriate is to use the -1 value for the index, as negative numbers mean slicing from the back of the list. We can then call the aggregation functions on this data.

In [45]:
wines[:,-1].mean()
Out[45]:
5.6360225140712945


Let's take a look at another dataset, this time on graduate school admissions. It has fields such as GRE score, TOEFL score, university rating, GPA, having research experience or not, and a chance of admission. With this dataset, we can do data manipulation and basic analysis to infer what conditions are associated with higher chance of admission.

The data file Admission_Predict.csv is located in the same GitLab reporsitory.

In [46]:
graduate_admission = np.genfromtxt(gl2StrObj('Admission_Predict.csv',23134556), 
                                   dtype=None, delimiter=',', skip_header=1,
                                   names=('Serial No','GRE Score', 'TOEFL Score', 'University Rating', 'SOP',
                                          'LOR','CGPA','Research', 'Chance of Admit'))
graduate_admission
Out[46]:
array([(  1, 337, 118, 4, 4.5, 4.5, 9.65, 1, 0.92),
       (  2, 324, 107, 4, 4. , 4.5, 8.87, 1, 0.76),
       (  3, 316, 104, 3, 3. , 3.5, 8.  , 1, 0.72),
       (  4, 322, 110, 3, 3.5, 2.5, 8.67, 1, 0.8 ),
       (  5, 314, 103, 2, 2. , 3. , 8.21, 0, 0.65),
       (  6, 330, 115, 5, 4.5, 3. , 9.34, 1, 0.9 ),
       (  7, 321, 109, 3, 3. , 4. , 8.2 , 1, 0.75),
       (  8, 308, 101, 2, 3. , 4. , 7.9 , 0, 0.68),
       (  9, 302, 102, 1, 2. , 1.5, 8.  , 0, 0.5 ),
       ( 10, 323, 108, 3, 3.5, 3. , 8.6 , 0, 0.45),
       ( 11, 325, 106, 3, 3.5, 4. , 8.4 , 1, 0.52),
       ( 12, 327, 111, 4, 4. , 4.5, 9.  , 1, 0.84),
       ( 13, 328, 112, 4, 4. , 4.5, 9.1 , 1, 0.78),
       ( 14, 307, 109, 3, 4. , 3. , 8.  , 1, 0.62),
       ( 15, 311, 104, 3, 3.5, 2. , 8.2 , 1, 0.61),
       ( 16, 314, 105, 3, 3.5, 2.5, 8.3 , 0, 0.54),
       ( 17, 317, 107, 3, 4. , 3. , 8.7 , 0, 0.66),
       ( 18, 319, 106, 3, 4. , 3. , 8.  , 1, 0.65),
       ( 19, 318, 110, 3, 4. , 3. , 8.8 , 0, 0.63),
       ( 20, 303, 102, 3, 3.5, 3. , 8.5 , 0, 0.62),
       ( 21, 312, 107, 3, 3. , 2. , 7.9 , 1, 0.64),
       ( 22, 325, 114, 4, 3. , 2. , 8.4 , 0, 0.7 ),
       ( 23, 328, 116, 5, 5. , 5. , 9.5 , 1, 0.94),
       ( 24, 334, 119, 5, 5. , 4.5, 9.7 , 1, 0.95),
       ( 25, 336, 119, 5, 4. , 3.5, 9.8 , 1, 0.97),
       ( 26, 340, 120, 5, 4.5, 4.5, 9.6 , 1, 0.94),
       ( 27, 322, 109, 5, 4.5, 3.5, 8.8 , 0, 0.76),
       ( 28, 298,  98, 2, 1.5, 2.5, 7.5 , 1, 0.44),
       ( 29, 295,  93, 1, 2. , 2. , 7.2 , 0, 0.46),
       ( 30, 310,  99, 2, 1.5, 2. , 7.3 , 0, 0.54),
       ( 31, 300,  97, 2, 3. , 3. , 8.1 , 1, 0.65),
       ( 32, 327, 103, 3, 4. , 4. , 8.3 , 1, 0.74),
       ( 33, 338, 118, 4, 3. , 4.5, 9.4 , 1, 0.91),
       ( 34, 340, 114, 5, 4. , 4. , 9.6 , 1, 0.9 ),
       ( 35, 331, 112, 5, 4. , 5. , 9.8 , 1, 0.94),
       ( 36, 320, 110, 5, 5. , 5. , 9.2 , 1, 0.88),
       ( 37, 299, 106, 2, 4. , 4. , 8.4 , 0, 0.64),
       ( 38, 300, 105, 1, 1. , 2. , 7.8 , 0, 0.58),
       ( 39, 304, 105, 1, 3. , 1.5, 7.5 , 0, 0.52),
       ( 40, 307, 108, 2, 4. , 3.5, 7.7 , 0, 0.48),
       ( 41, 308, 110, 3, 3.5, 3. , 8.  , 1, 0.46),
       ( 42, 316, 105, 2, 2.5, 2.5, 8.2 , 1, 0.49),
       ( 43, 313, 107, 2, 2.5, 2. , 8.5 , 1, 0.53),
       ( 44, 332, 117, 4, 4.5, 4. , 9.1 , 0, 0.87),
       ( 45, 326, 113, 5, 4.5, 4. , 9.4 , 1, 0.91),
       ( 46, 322, 110, 5, 5. , 4. , 9.1 , 1, 0.88),
       ( 47, 329, 114, 5, 4. , 5. , 9.3 , 1, 0.86),
       ( 48, 339, 119, 5, 4.5, 4. , 9.7 , 0, 0.89),
       ( 49, 321, 110, 3, 3.5, 5. , 8.85, 1, 0.82),
       ( 50, 327, 111, 4, 3. , 4. , 8.4 , 1, 0.78),
       ( 51, 313,  98, 3, 2.5, 4.5, 8.3 , 1, 0.76),
       ( 52, 312, 100, 2, 1.5, 3.5, 7.9 , 1, 0.56),
       ( 53, 334, 116, 4, 4. , 3. , 8.  , 1, 0.78),
       ( 54, 324, 112, 4, 4. , 2.5, 8.1 , 1, 0.72),
       ( 55, 322, 110, 3, 3. , 3.5, 8.  , 0, 0.7 ),
       ( 56, 320, 103, 3, 3. , 3. , 7.7 , 0, 0.64),
       ( 57, 316, 102, 3, 2. , 3. , 7.4 , 0, 0.64),
       ( 58, 298,  99, 2, 4. , 2. , 7.6 , 0, 0.46),
       ( 59, 300,  99, 1, 3. , 2. , 6.8 , 1, 0.36),
       ( 60, 311, 104, 2, 2. , 2. , 8.3 , 0, 0.42),
       ( 61, 309, 100, 2, 3. , 3. , 8.1 , 0, 0.48),
       ( 62, 307, 101, 3, 4. , 3. , 8.2 , 0, 0.47),
       ( 63, 304, 105, 2, 3. , 3. , 8.2 , 1, 0.54),
       ( 64, 315, 107, 2, 4. , 3. , 8.5 , 1, 0.56),
       ( 65, 325, 111, 3, 3. , 3.5, 8.7 , 0, 0.52),
       ( 66, 325, 112, 4, 3.5, 3.5, 8.92, 0, 0.55),
       ( 67, 327, 114, 3, 3. , 3. , 9.02, 0, 0.61),
       ( 68, 316, 107, 2, 3.5, 3.5, 8.64, 1, 0.57),
       ( 69, 318, 109, 3, 3.5, 4. , 9.22, 1, 0.68),
       ( 70, 328, 115, 4, 4.5, 4. , 9.16, 1, 0.78),
       ( 71, 332, 118, 5, 5. , 5. , 9.64, 1, 0.94),
       ( 72, 336, 112, 5, 5. , 5. , 9.76, 1, 0.96),
       ( 73, 321, 111, 5, 5. , 5. , 9.45, 1, 0.93),
       ( 74, 314, 108, 4, 4.5, 4. , 9.04, 1, 0.84),
       ( 75, 314, 106, 3, 3. , 5. , 8.9 , 0, 0.74),
       ( 76, 329, 114, 2, 2. , 4. , 8.56, 1, 0.72),
       ( 77, 327, 112, 3, 3. , 3. , 8.72, 1, 0.74),
       ( 78, 301,  99, 2, 3. , 2. , 8.22, 0, 0.64),
       ( 79, 296,  95, 2, 3. , 2. , 7.54, 1, 0.44),
       ( 80, 294,  93, 1, 1.5, 2. , 7.36, 0, 0.46),
       ( 81, 312, 105, 3, 2. , 3. , 8.02, 1, 0.5 ),
       ( 82, 340, 120, 4, 5. , 5. , 9.5 , 1, 0.96),
       ( 83, 320, 110, 5, 5. , 4.5, 9.22, 1, 0.92),
       ( 84, 322, 115, 5, 4. , 4.5, 9.36, 1, 0.92),
       ( 85, 340, 115, 5, 4.5, 4.5, 9.45, 1, 0.94),
       ( 86, 319, 103, 4, 4.5, 3.5, 8.66, 0, 0.76),
       ( 87, 315, 106, 3, 4.5, 3.5, 8.42, 0, 0.72),
       ( 88, 317, 107, 2, 3.5, 3. , 8.28, 0, 0.66),
       ( 89, 314, 108, 3, 4.5, 3.5, 8.14, 0, 0.64),
       ( 90, 316, 109, 4, 4.5, 3.5, 8.76, 1, 0.74),
       ( 91, 318, 106, 2, 4. , 4. , 7.92, 1, 0.64),
       ( 92, 299,  97, 3, 5. , 3.5, 7.66, 0, 0.38),
       ( 93, 298,  98, 2, 4. , 3. , 8.03, 0, 0.34),
       ( 94, 301,  97, 2, 3. , 3. , 7.88, 1, 0.44),
       ( 95, 303,  99, 3, 2. , 2.5, 7.66, 0, 0.36),
       ( 96, 304, 100, 4, 1.5, 2.5, 7.84, 0, 0.42),
       ( 97, 306, 100, 2, 3. , 3. , 8.  , 0, 0.48),
       ( 98, 331, 120, 3, 4. , 4. , 8.96, 1, 0.86),
       ( 99, 332, 119, 4, 5. , 4.5, 9.24, 1, 0.9 ),
       (100, 323, 113, 3, 4. , 4. , 8.88, 1, 0.79),
       (101, 322, 107, 3, 3.5, 3.5, 8.46, 1, 0.71),
       (102, 312, 105, 2, 2.5, 3. , 8.12, 0, 0.64),
       (103, 314, 106, 2, 4. , 3.5, 8.25, 0, 0.62),
       (104, 317, 104, 2, 4.5, 4. , 8.47, 0, 0.57),
       (105, 326, 112, 3, 3.5, 3. , 9.05, 1, 0.74),
       (106, 316, 110, 3, 4. , 4.5, 8.78, 1, 0.69),
       (107, 329, 111, 4, 4.5, 4.5, 9.18, 1, 0.87),
       (108, 338, 117, 4, 3.5, 4.5, 9.46, 1, 0.91),
       (109, 331, 116, 5, 5. , 5. , 9.38, 1, 0.93),
       (110, 304, 103, 5, 5. , 4. , 8.64, 0, 0.68),
       (111, 305, 108, 5, 3. , 3. , 8.48, 0, 0.61),
       (112, 321, 109, 4, 4. , 4. , 8.68, 1, 0.69),
       (113, 301, 107, 3, 3.5, 3.5, 8.34, 1, 0.62),
       (114, 320, 110, 2, 4. , 3.5, 8.56, 0, 0.72),
       (115, 311, 105, 3, 3.5, 3. , 8.45, 1, 0.59),
       (116, 310, 106, 4, 4.5, 4.5, 9.04, 1, 0.66),
       (117, 299, 102, 3, 4. , 3.5, 8.62, 0, 0.56),
       (118, 290, 104, 4, 2. , 2.5, 7.46, 0, 0.45),
       (119, 296,  99, 2, 3. , 3.5, 7.28, 0, 0.47),
       (120, 327, 104, 5, 3. , 3.5, 8.84, 1, 0.71),
       (121, 335, 117, 5, 5. , 5. , 9.56, 1, 0.94),
       (122, 334, 119, 5, 4.5, 4.5, 9.48, 1, 0.94),
       (123, 310, 106, 4, 1.5, 2.5, 8.36, 0, 0.57),
       (124, 308, 108, 3, 3.5, 3.5, 8.22, 0, 0.61),
       (125, 301, 106, 4, 2.5, 3. , 8.47, 0, 0.57),
       (126, 300, 100, 3, 2. , 3. , 8.66, 1, 0.64),
       (127, 323, 113, 3, 4. , 3. , 9.32, 1, 0.85),
       (128, 319, 112, 3, 2.5, 2. , 8.71, 1, 0.78),
       (129, 326, 112, 3, 3.5, 3. , 9.1 , 1, 0.84),
       (130, 333, 118, 5, 5. , 5. , 9.35, 1, 0.92),
       (131, 339, 114, 5, 4. , 4.5, 9.76, 1, 0.96),
       (132, 303, 105, 5, 5. , 4.5, 8.65, 0, 0.77),
       (133, 309, 105, 5, 3.5, 3.5, 8.56, 0, 0.71),
       (134, 323, 112, 5, 4. , 4.5, 8.78, 0, 0.79),
       (135, 333, 113, 5, 4. , 4. , 9.28, 1, 0.89),
       (136, 314, 109, 4, 3.5, 4. , 8.77, 1, 0.82),
       (137, 312, 103, 3, 5. , 4. , 8.45, 0, 0.76),
       (138, 316, 100, 2, 1.5, 3. , 8.16, 1, 0.71),
       (139, 326, 116, 2, 4.5, 3. , 9.08, 1, 0.8 ),
       (140, 318, 109, 1, 3.5, 3.5, 9.12, 0, 0.78),
       (141, 329, 110, 2, 4. , 3. , 9.15, 1, 0.84),
       (142, 332, 118, 2, 4.5, 3.5, 9.36, 1, 0.9 ),
       (143, 331, 115, 5, 4. , 3.5, 9.44, 1, 0.92),
       (144, 340, 120, 4, 4.5, 4. , 9.92, 1, 0.97),
       (145, 325, 112, 2, 3. , 3.5, 8.96, 1, 0.8 ),
       (146, 320, 113, 2, 2. , 2.5, 8.64, 1, 0.81),
       (147, 315, 105, 3, 2. , 2.5, 8.48, 0, 0.75),
       (148, 326, 114, 3, 3. , 3. , 9.11, 1, 0.83),
       (149, 339, 116, 4, 4. , 3.5, 9.8 , 1, 0.96),
       (150, 311, 106, 2, 3.5, 3. , 8.26, 1, 0.79),
       (151, 334, 114, 4, 4. , 4. , 9.43, 1, 0.93),
       (152, 332, 116, 5, 5. , 5. , 9.28, 1, 0.94),
       (153, 321, 112, 5, 5. , 5. , 9.06, 1, 0.86),
       (154, 324, 105, 3, 3. , 4. , 8.75, 0, 0.79),
       (155, 326, 108, 3, 3. , 3.5, 8.89, 0, 0.8 ),
       (156, 312, 109, 3, 3. , 3. , 8.69, 0, 0.77),
       (157, 315, 105, 3, 2. , 2.5, 8.34, 0, 0.7 ),
       (158, 309, 104, 2, 2. , 2.5, 8.26, 0, 0.65),
       (159, 306, 106, 2, 2. , 2.5, 8.14, 0, 0.61),
       (160, 297, 100, 1, 1.5, 2. , 7.9 , 0, 0.52),
       (161, 315, 103, 1, 1.5, 2. , 7.86, 0, 0.57),
       (162, 298,  99, 1, 1.5, 3. , 7.46, 0, 0.53),
       (163, 318, 109, 3, 3. , 3. , 8.5 , 0, 0.67),
       (164, 317, 105, 3, 3.5, 3. , 8.56, 0, 0.68),
       (165, 329, 111, 4, 4.5, 4. , 9.01, 1, 0.81),
       (166, 322, 110, 5, 4.5, 4. , 8.97, 0, 0.78),
       (167, 302, 102, 3, 3.5, 5. , 8.33, 0, 0.65),
       (168, 313, 102, 3, 2. , 3. , 8.27, 0, 0.64),
       (169, 293,  97, 2, 2. , 4. , 7.8 , 1, 0.64),
       (170, 311,  99, 2, 2.5, 3. , 7.98, 0, 0.65),
       (171, 312, 101, 2, 2.5, 3.5, 8.04, 1, 0.68),
       (172, 334, 117, 5, 4. , 4.5, 9.07, 1, 0.89),
       (173, 322, 110, 4, 4. , 5. , 9.13, 1, 0.86),
       (174, 323, 113, 4, 4. , 4.5, 9.23, 1, 0.89),
       (175, 321, 111, 4, 4. , 4. , 8.97, 1, 0.87),
       (176, 320, 111, 4, 4.5, 3.5, 8.87, 1, 0.85),
       (177, 329, 119, 4, 4.5, 4.5, 9.16, 1, 0.9 ),
       (178, 319, 110, 3, 3.5, 3.5, 9.04, 0, 0.82),
       (179, 309, 108, 3, 2.5, 3. , 8.12, 0, 0.72),
       (180, 307, 102, 3, 3. , 3. , 8.27, 0, 0.73),
       (181, 300, 104, 3, 3.5, 3. , 8.16, 0, 0.71),
       (182, 305, 107, 2, 2.5, 2.5, 8.42, 0, 0.71),
       (183, 299, 100, 2, 3. , 3.5, 7.88, 0, 0.68),
       (184, 314, 110, 3, 4. , 4. , 8.8 , 0, 0.75),
       (185, 316, 106, 2, 2.5, 4. , 8.32, 0, 0.72),
       (186, 327, 113, 4, 4.5, 4.5, 9.11, 1, 0.89),
       (187, 317, 107, 3, 3.5, 3. , 8.68, 1, 0.84),
       (188, 335, 118, 5, 4.5, 3.5, 9.44, 1, 0.93),
       (189, 331, 115, 5, 4.5, 3.5, 9.36, 1, 0.93),
       (190, 324, 112, 5, 5. , 5. , 9.08, 1, 0.88),
       (191, 324, 111, 5, 4.5, 4. , 9.16, 1, 0.9 ),
       (192, 323, 110, 5, 4. , 5. , 8.98, 1, 0.87),
       (193, 322, 114, 5, 4.5, 4. , 8.94, 1, 0.86),
       (194, 336, 118, 5, 4.5, 5. , 9.53, 1, 0.94),
       (195, 316, 109, 3, 3.5, 3. , 8.76, 0, 0.77),
       (196, 307, 107, 2, 3. , 3.5, 8.52, 1, 0.78),
       (197, 306, 105, 2, 3. , 2.5, 8.26, 0, 0.73),
       (198, 310, 106, 2, 3.5, 2.5, 8.33, 0, 0.73),
       (199, 311, 104, 3, 4.5, 4.5, 8.43, 0, 0.7 ),
       (200, 313, 107, 3, 4. , 4.5, 8.69, 0, 0.72),
       (201, 317, 103, 3, 2.5, 3. , 8.54, 1, 0.73),
       (202, 315, 110, 2, 3.5, 3. , 8.46, 1, 0.72),
       (203, 340, 120, 5, 4.5, 4.5, 9.91, 1, 0.97),
       (204, 334, 120, 5, 4. , 5. , 9.87, 1, 0.97),
       (205, 298, 105, 3, 3.5, 4. , 8.54, 0, 0.69),
       (206, 295,  99, 2, 2.5, 3. , 7.65, 0, 0.57),
       (207, 315,  99, 2, 3.5, 3. , 7.89, 0, 0.63),
       (208, 310, 102, 3, 3.5, 4. , 8.02, 1, 0.66),
       (209, 305, 106, 2, 3. , 3. , 8.16, 0, 0.64),
       (210, 301, 104, 3, 3.5, 4. , 8.12, 1, 0.68),
       (211, 325, 108, 4, 4.5, 4. , 9.06, 1, 0.79),
       (212, 328, 110, 4, 5. , 4. , 9.14, 1, 0.82),
       (213, 338, 120, 4, 5. , 5. , 9.66, 1, 0.95),
       (214, 333, 119, 5, 5. , 4.5, 9.78, 1, 0.96),
       (215, 331, 117, 4, 4.5, 5. , 9.42, 1, 0.94),
       (216, 330, 116, 5, 5. , 4.5, 9.36, 1, 0.93),
       (217, 322, 112, 4, 4.5, 4.5, 9.26, 1, 0.91),
       (218, 321, 109, 4, 4. , 4. , 9.13, 1, 0.85),
       (219, 324, 110, 4, 3. , 3.5, 8.97, 1, 0.84),
       (220, 312, 104, 3, 3.5, 3.5, 8.42, 0, 0.74),
       (221, 313, 103, 3, 4. , 4. , 8.75, 0, 0.76),
       (222, 316, 110, 3, 3.5, 4. , 8.56, 0, 0.75),
       (223, 324, 113, 4, 4.5, 4. , 8.79, 0, 0.76),
       (224, 308, 109, 2, 3. , 4. , 8.45, 0, 0.71),
       (225, 305, 105, 2, 3. , 2. , 8.23, 0, 0.67),
       (226, 296,  99, 2, 2.5, 2.5, 8.03, 0, 0.61),
       (227, 306, 110, 2, 3.5, 4. , 8.45, 0, 0.63),
       (228, 312, 110, 2, 3.5, 3. , 8.53, 0, 0.64),
       (229, 318, 112, 3, 4. , 3.5, 8.67, 0, 0.71),
       (230, 324, 111, 4, 3. , 3. , 9.01, 1, 0.82),
       (231, 313, 104, 3, 4. , 4.5, 8.65, 0, 0.73),
       (232, 319, 106, 3, 3.5, 2.5, 8.33, 1, 0.74),
       (233, 312, 107, 2, 2.5, 3.5, 8.27, 0, 0.69),
       (234, 304, 100, 2, 2.5, 3.5, 8.07, 0, 0.64),
       (235, 330, 113, 5, 5. , 4. , 9.31, 1, 0.91),
       (236, 326, 111, 5, 4.5, 4. , 9.23, 1, 0.88),
       (237, 325, 112, 4, 4. , 4.5, 9.17, 1, 0.85),
       (238, 329, 114, 5, 4.5, 5. , 9.19, 1, 0.86),
       (239, 310, 104, 3, 2. , 3.5, 8.37, 0, 0.7 ),
       (240, 299, 100, 1, 1.5, 2. , 7.89, 0, 0.59),
       (241, 296, 101, 1, 2.5, 3. , 7.68, 0, 0.6 ),
       (242, 317, 103, 2, 2.5, 2. , 8.15, 0, 0.65),
       (243, 324, 115, 3, 3.5, 3. , 8.76, 1, 0.7 ),
       (244, 325, 114, 3, 3.5, 3. , 9.04, 1, 0.76),
       (245, 314, 107, 2, 2.5, 4. , 8.56, 0, 0.63),
       (246, 328, 110, 4, 4. , 2.5, 9.02, 1, 0.81),
       (247, 316, 105, 3, 3. , 3.5, 8.73, 0, 0.72),
       (248, 311, 104, 2, 2.5, 3.5, 8.48, 0, 0.71),
       (249, 324, 110, 3, 3.5, 4. , 8.87, 1, 0.8 ),
       (250, 321, 111, 3, 3.5, 4. , 8.83, 1, 0.77),
       (251, 320, 104, 3, 3. , 2.5, 8.57, 1, 0.74),
       (252, 316,  99, 2, 2.5, 3. , 9.  , 0, 0.7 ),
       (253, 318, 100, 2, 2.5, 3.5, 8.54, 1, 0.71),
       (254, 335, 115, 4, 4.5, 4.5, 9.68, 1, 0.93),
       (255, 321, 114, 4, 4. , 5. , 9.12, 0, 0.85),
       (256, 307, 110, 4, 4. , 4.5, 8.37, 0, 0.79),
       (257, 309,  99, 3, 4. , 4. , 8.56, 0, 0.76),
       (258, 324, 100, 3, 4. , 5. , 8.64, 1, 0.78),
       (259, 326, 102, 4, 5. , 5. , 8.76, 1, 0.77),
       (260, 331, 119, 4, 5. , 4.5, 9.34, 1, 0.9 ),
       (261, 327, 108, 5, 5. , 3.5, 9.13, 1, 0.87),
       (262, 312, 104, 3, 3.5, 4. , 8.09, 0, 0.71),
       (263, 308, 103, 2, 2.5, 4. , 8.36, 1, 0.7 ),
       (264, 324, 111, 3, 2.5, 1.5, 8.79, 1, 0.7 ),
       (265, 325, 110, 2, 3. , 2.5, 8.76, 1, 0.75),
       (266, 313, 102, 3, 2.5, 2.5, 8.68, 0, 0.71),
       (267, 312, 105, 2, 2. , 2.5, 8.45, 0, 0.72),
       (268, 314, 107, 3, 3. , 3.5, 8.17, 1, 0.73),
       (269, 327, 113, 4, 4.5, 5. , 9.14, 0, 0.83),
       (270, 308, 108, 4, 4.5, 5. , 8.34, 0, 0.77),
       (271, 306, 105, 2, 2.5, 3. , 8.22, 1, 0.72),
       (272, 299,  96, 2, 1.5, 2. , 7.86, 0, 0.54),
       (273, 294,  95, 1, 1.5, 1.5, 7.64, 0, 0.49),
       (274, 312,  99, 1, 1. , 1.5, 8.01, 1, 0.52),
       (275, 315, 100, 1, 2. , 2.5, 7.95, 0, 0.58),
       (276, 322, 110, 3, 3.5, 3. , 8.96, 1, 0.78),
       (277, 329, 113, 5, 5. , 4.5, 9.45, 1, 0.89),
       (278, 320, 101, 2, 2.5, 3. , 8.62, 0, 0.7 ),
       (279, 308, 103, 2, 3. , 3.5, 8.49, 0, 0.66),
       (280, 304, 102, 2, 3. , 4. , 8.73, 0, 0.67),
       (281, 311, 102, 3, 4.5, 4. , 8.64, 1, 0.68),
       (282, 317, 110, 3, 4. , 4.5, 9.11, 1, 0.8 ),
       (283, 312, 106, 3, 4. , 3.5, 8.79, 1, 0.81),
       (284, 321, 111, 3, 2.5, 3. , 8.9 , 1, 0.8 ),
       (285, 340, 112, 4, 5. , 4.5, 9.66, 1, 0.94),
       (286, 331, 116, 5, 4. , 4. , 9.26, 1, 0.93),
       (287, 336, 118, 5, 4.5, 4. , 9.19, 1, 0.92),
       (288, 324, 114, 5, 5. , 4.5, 9.08, 1, 0.89),
       (289, 314, 104, 4, 5. , 5. , 9.02, 0, 0.82),
       (290, 313, 109, 3, 4. , 3.5, 9.  , 0, 0.79),
       (291, 307, 105, 2, 2.5, 3. , 7.65, 0, 0.58),
       (292, 300, 102, 2, 1.5, 2. , 7.87, 0, 0.56),
       (293, 302,  99, 2, 1. , 2. , 7.97, 0, 0.56),
       (294, 312,  98, 1, 3.5, 3. , 8.18, 1, 0.64),
       (295, 316, 101, 2, 2.5, 2. , 8.32, 1, 0.61),
       (296, 317, 100, 2, 3. , 2.5, 8.57, 0, 0.68),
       (297, 310, 107, 3, 3.5, 3.5, 8.67, 0, 0.76),
       (298, 320, 120, 3, 4. , 4.5, 9.11, 0, 0.86),
       (299, 330, 114, 3, 4.5, 4.5, 9.24, 1, 0.9 ),
       (300, 305, 112, 3, 3. , 3.5, 8.65, 0, 0.71),
       (301, 309, 106, 2, 2.5, 2.5, 8.  , 0, 0.62),
       (302, 319, 108, 2, 2.5, 3. , 8.76, 0, 0.66),
       (303, 322, 105, 2, 3. , 3. , 8.45, 1, 0.65),
       (304, 323, 107, 3, 3.5, 3.5, 8.55, 1, 0.73),
       (305, 313, 106, 2, 2.5, 2. , 8.43, 0, 0.62),
       (306, 321, 109, 3, 3.5, 3.5, 8.8 , 1, 0.74),
       (307, 323, 110, 3, 4. , 3.5, 9.1 , 1, 0.79),
       (308, 325, 112, 4, 4. , 4. , 9.  , 1, 0.8 ),
       (309, 312, 108, 3, 3.5, 3. , 8.53, 0, 0.69),
       (310, 308, 110, 4, 3.5, 3. , 8.6 , 0, 0.7 ),
       (311, 320, 104, 3, 3. , 3.5, 8.74, 1, 0.76),
       (312, 328, 108, 4, 4.5, 4. , 9.18, 1, 0.84),
       (313, 311, 107, 4, 4.5, 4.5, 9.  , 1, 0.78),
       (314, 301, 100, 3, 3.5, 3. , 8.04, 0, 0.67),
       (315, 305, 105, 2, 3. , 4. , 8.13, 0, 0.66),
       (316, 308, 104, 2, 2.5, 3. , 8.07, 0, 0.65),
       (317, 298, 101, 2, 1.5, 2. , 7.86, 0, 0.54),
       (318, 300,  99, 1, 1. , 2.5, 8.01, 0, 0.58),
       (319, 324, 111, 3, 2.5, 2. , 8.8 , 1, 0.79),
       (320, 327, 113, 4, 3.5, 3. , 8.69, 1, 0.8 ),
       (321, 317, 106, 3, 4. , 3.5, 8.5 , 1, 0.75),
       (322, 323, 104, 3, 4. , 4. , 8.44, 1, 0.73),
       (323, 314, 107, 2, 2.5, 4. , 8.27, 0, 0.72),
       (324, 305, 102, 2, 2. , 2.5, 8.18, 0, 0.62),
       (325, 315, 104, 3, 3. , 2.5, 8.33, 0, 0.67),
       (326, 326, 116, 3, 3.5, 4. , 9.14, 1, 0.81),
       (327, 299, 100, 3, 2. , 2. , 8.02, 0, 0.63),
       (328, 295, 101, 2, 2.5, 2. , 7.86, 0, 0.69),
       (329, 324, 112, 4, 4. , 3.5, 8.77, 1, 0.8 ),
       (330, 297,  96, 2, 2.5, 1.5, 7.89, 0, 0.43),
       (331, 327, 113, 3, 3.5, 3. , 8.66, 1, 0.8 ),
       (332, 311, 105, 2, 3. , 2. , 8.12, 1, 0.73),
       (333, 308, 106, 3, 3.5, 2.5, 8.21, 1, 0.75),
       (334, 319, 108, 3, 3. , 3.5, 8.54, 1, 0.71),
       (335, 312, 107, 4, 4.5, 4. , 8.65, 1, 0.73),
       (336, 325, 111, 4, 4. , 4.5, 9.11, 1, 0.83),
       (337, 319, 110, 3, 3. , 2.5, 8.79, 0, 0.72),
       (338, 332, 118, 5, 5. , 5. , 9.47, 1, 0.94),
       (339, 323, 108, 5, 4. , 4. , 8.74, 1, 0.81),
       (340, 324, 107, 5, 3.5, 4. , 8.66, 1, 0.81),
       (341, 312, 107, 3, 3. , 3. , 8.46, 1, 0.75),
       (342, 326, 110, 3, 3.5, 3.5, 8.76, 1, 0.79),
       (343, 308, 106, 3, 3. , 3. , 8.24, 0, 0.58),
       (344, 305, 103, 2, 2.5, 3.5, 8.13, 0, 0.59),
       (345, 295,  96, 2, 1.5, 2. , 7.34, 0, 0.47),
       (346, 316,  98, 1, 1.5, 2. , 7.43, 0, 0.49),
       (347, 304,  97, 2, 1.5, 2. , 7.64, 0, 0.47),
       (348, 299,  94, 1, 1. , 1. , 7.34, 0, 0.42),
       (349, 302,  99, 1, 2. , 2. , 7.25, 0, 0.57),
       (350, 313, 101, 3, 2.5, 3. , 8.04, 0, 0.62),
       (351, 318, 107, 3, 3. , 3.5, 8.27, 1, 0.74),
       (352, 325, 110, 4, 3.5, 4. , 8.67, 1, 0.73),
       (353, 303, 100, 2, 3. , 3.5, 8.06, 1, 0.64),
       (354, 300, 102, 3, 3.5, 2.5, 8.17, 0, 0.63),
       (355, 297,  98, 2, 2.5, 3. , 7.67, 0, 0.59),
       (356, 317, 106, 2, 2. , 3.5, 8.12, 0, 0.73),
       (357, 327, 109, 3, 3.5, 4. , 8.77, 1, 0.79),
       (358, 301, 104, 2, 3.5, 3.5, 7.89, 1, 0.68),
       (359, 314, 105, 2, 2.5, 2. , 7.64, 0, 0.7 ),
       (360, 321, 107, 2, 2. , 1.5, 8.44, 0, 0.81),
       (361, 322, 110, 3, 4. , 5. , 8.64, 1, 0.85),
       (362, 334, 116, 4, 4. , 3.5, 9.54, 1, 0.93),
       (363, 338, 115, 5, 4.5, 5. , 9.23, 1, 0.91),
       (364, 306, 103, 2, 2.5, 3. , 8.36, 0, 0.69),
       (365, 313, 102, 3, 3.5, 4. , 8.9 , 1, 0.77),
       (366, 330, 114, 4, 4.5, 3. , 9.17, 1, 0.86),
       (367, 320, 104, 3, 3.5, 4.5, 8.34, 1, 0.74),
       (368, 311,  98, 1, 1. , 2.5, 7.46, 0, 0.57),
       (369, 298,  92, 1, 2. , 2. , 7.88, 0, 0.51),
       (370, 301,  98, 1, 2. , 3. , 8.03, 1, 0.67),
       (371, 310, 103, 2, 2.5, 2.5, 8.24, 0, 0.72),
       (372, 324, 110, 3, 3.5, 3. , 9.22, 1, 0.89),
       (373, 336, 119, 4, 4.5, 4. , 9.62, 1, 0.95),
       (374, 321, 109, 3, 3. , 3. , 8.54, 1, 0.79),
       (375, 315, 105, 2, 2. , 2.5, 7.65, 0, 0.39),
       (376, 304, 101, 2, 2. , 2.5, 7.66, 0, 0.38),
       (377, 297,  96, 2, 2.5, 2. , 7.43, 0, 0.34),
       (378, 290, 100, 1, 1.5, 2. , 7.56, 0, 0.47),
       (379, 303,  98, 1, 2. , 2.5, 7.65, 0, 0.56),
       (380, 311,  99, 1, 2.5, 3. , 8.43, 1, 0.71),
       (381, 322, 104, 3, 3.5, 4. , 8.84, 1, 0.78),
       (382, 319, 105, 3, 3. , 3.5, 8.67, 1, 0.73),
       (383, 324, 110, 4, 4.5, 4. , 9.15, 1, 0.82),
       (384, 300, 100, 3, 3. , 3.5, 8.26, 0, 0.62),
       (385, 340, 113, 4, 5. , 5. , 9.74, 1, 0.96),
       (386, 335, 117, 5, 5. , 5. , 9.82, 1, 0.96),
       (387, 302, 101, 2, 2.5, 3.5, 7.96, 0, 0.46),
       (388, 307, 105, 2, 2. , 3.5, 8.1 , 0, 0.53),
       (389, 296,  97, 2, 1.5, 2. , 7.8 , 0, 0.49),
       (390, 320, 108, 3, 3.5, 4. , 8.44, 1, 0.76),
       (391, 314, 102, 2, 2. , 2.5, 8.24, 0, 0.64),
       (392, 318, 106, 3, 2. , 3. , 8.65, 0, 0.71),
       (393, 326, 112, 4, 4. , 3.5, 9.12, 1, 0.84),
       (394, 317, 104, 2, 3. , 3. , 8.76, 0, 0.77),
       (395, 329, 111, 4, 4.5, 4. , 9.23, 1, 0.89),
       (396, 324, 110, 3, 3.5, 3.5, 9.04, 1, 0.82),
       (397, 325, 107, 3, 3. , 3.5, 9.11, 1, 0.84),
       (398, 330, 116, 4, 5. , 4.5, 9.45, 1, 0.91),
       (399, 312, 103, 3, 3.5, 4. , 8.78, 0, 0.67),
       (400, 333, 117, 4, 5. , 4. , 9.66, 1, 0.95)],
      dtype=[('Serial_No', '<i4'), ('GRE_Score', '<i4'), ('TOEFL_Score', '<i4'), ('University_Rating', '<i4'), ('SOP', '<f8'), ('LOR', '<f8'), ('CGPA', '<f8'), ('Research', '<i4'), ('Chance_of_Admit', '<f8')])


Notice that the resulting array is actually a one-dimensional array with 400 tuples

In [47]:
graduate_admission.shape
Out[47]:
(400,)


We can retrieve a column from the array using the column's name for example, let's get the CGPA column and only the first five values.

In [48]:
graduate_admission['CGPA'][0:5]
Out[48]:
array([9.65, 8.87, 8.  , 8.67, 8.21])


Since the GPA in the dataset range from 1 to 10, and in the US it's more common to use a scale of up to 4, a common task might be to convert the GPA by dividing by 10 and then multiplying by 4

In [49]:
graduate_admission['CGPA'] = graduate_admission['CGPA'] /10 *4
graduate_admission['CGPA'][0:20] #let's get 20 values
Out[49]:
array([3.86 , 3.548, 3.2  , 3.468, 3.284, 3.736, 3.28 , 3.16 , 3.2  ,
       3.44 , 3.36 , 3.6  , 3.64 , 3.2  , 3.28 , 3.32 , 3.48 , 3.2  ,
       3.52 , 3.4  ])


Recall boolean masking. We can use this to find out how many students have had research experience by creating a boolean mask and passing it to the array indexing operator

In [50]:
len(graduate_admission[graduate_admission['Research'] == 1])
Out[50]:
219


Since we have the data field chance of admission, which ranges from 0 to 1, we can try to see if students with high chance of admission (>0.8) on average have higher GRE score than those with lower chance of admission (<0.4). When we do the boolean masking we are left with an array with tuples in it still, and numpy holds underneath this a list of the columns we specified and their name and indexes

In [51]:
graduate_admission[graduate_admission['Chance_of_Admit'] > 0.8]
Out[51]:
array([(  1, 337, 118, 4, 4.5, 4.5, 3.86 , 1, 0.92),
       (  6, 330, 115, 5, 4.5, 3. , 3.736, 1, 0.9 ),
       ( 12, 327, 111, 4, 4. , 4.5, 3.6  , 1, 0.84),
       ( 23, 328, 116, 5, 5. , 5. , 3.8  , 1, 0.94),
       ( 24, 334, 119, 5, 5. , 4.5, 3.88 , 1, 0.95),
       ( 25, 336, 119, 5, 4. , 3.5, 3.92 , 1, 0.97),
       ( 26, 340, 120, 5, 4.5, 4.5, 3.84 , 1, 0.94),
       ( 33, 338, 118, 4, 3. , 4.5, 3.76 , 1, 0.91),
       ( 34, 340, 114, 5, 4. , 4. , 3.84 , 1, 0.9 ),
       ( 35, 331, 112, 5, 4. , 5. , 3.92 , 1, 0.94),
       ( 36, 320, 110, 5, 5. , 5. , 3.68 , 1, 0.88),
       ( 44, 332, 117, 4, 4.5, 4. , 3.64 , 0, 0.87),
       ( 45, 326, 113, 5, 4.5, 4. , 3.76 , 1, 0.91),
       ( 46, 322, 110, 5, 5. , 4. , 3.64 , 1, 0.88),
       ( 47, 329, 114, 5, 4. , 5. , 3.72 , 1, 0.86),
       ( 48, 339, 119, 5, 4.5, 4. , 3.88 , 0, 0.89),
       ( 49, 321, 110, 3, 3.5, 5. , 3.54 , 1, 0.82),
       ( 71, 332, 118, 5, 5. , 5. , 3.856, 1, 0.94),
       ( 72, 336, 112, 5, 5. , 5. , 3.904, 1, 0.96),
       ( 73, 321, 111, 5, 5. , 5. , 3.78 , 1, 0.93),
       ( 74, 314, 108, 4, 4.5, 4. , 3.616, 1, 0.84),
       ( 82, 340, 120, 4, 5. , 5. , 3.8  , 1, 0.96),
       ( 83, 320, 110, 5, 5. , 4.5, 3.688, 1, 0.92),
       ( 84, 322, 115, 5, 4. , 4.5, 3.744, 1, 0.92),
       ( 85, 340, 115, 5, 4.5, 4.5, 3.78 , 1, 0.94),
       ( 98, 331, 120, 3, 4. , 4. , 3.584, 1, 0.86),
       ( 99, 332, 119, 4, 5. , 4.5, 3.696, 1, 0.9 ),
       (107, 329, 111, 4, 4.5, 4.5, 3.672, 1, 0.87),
       (108, 338, 117, 4, 3.5, 4.5, 3.784, 1, 0.91),
       (109, 331, 116, 5, 5. , 5. , 3.752, 1, 0.93),
       (121, 335, 117, 5, 5. , 5. , 3.824, 1, 0.94),
       (122, 334, 119, 5, 4.5, 4.5, 3.792, 1, 0.94),
       (127, 323, 113, 3, 4. , 3. , 3.728, 1, 0.85),
       (129, 326, 112, 3, 3.5, 3. , 3.64 , 1, 0.84),
       (130, 333, 118, 5, 5. , 5. , 3.74 , 1, 0.92),
       (131, 339, 114, 5, 4. , 4.5, 3.904, 1, 0.96),
       (135, 333, 113, 5, 4. , 4. , 3.712, 1, 0.89),
       (136, 314, 109, 4, 3.5, 4. , 3.508, 1, 0.82),
       (141, 329, 110, 2, 4. , 3. , 3.66 , 1, 0.84),
       (142, 332, 118, 2, 4.5, 3.5, 3.744, 1, 0.9 ),
       (143, 331, 115, 5, 4. , 3.5, 3.776, 1, 0.92),
       (144, 340, 120, 4, 4.5, 4. , 3.968, 1, 0.97),
       (146, 320, 113, 2, 2. , 2.5, 3.456, 1, 0.81),
       (148, 326, 114, 3, 3. , 3. , 3.644, 1, 0.83),
       (149, 339, 116, 4, 4. , 3.5, 3.92 , 1, 0.96),
       (151, 334, 114, 4, 4. , 4. , 3.772, 1, 0.93),
       (152, 332, 116, 5, 5. , 5. , 3.712, 1, 0.94),
       (153, 321, 112, 5, 5. , 5. , 3.624, 1, 0.86),
       (165, 329, 111, 4, 4.5, 4. , 3.604, 1, 0.81),
       (172, 334, 117, 5, 4. , 4.5, 3.628, 1, 0.89),
       (173, 322, 110, 4, 4. , 5. , 3.652, 1, 0.86),
       (174, 323, 113, 4, 4. , 4.5, 3.692, 1, 0.89),
       (175, 321, 111, 4, 4. , 4. , 3.588, 1, 0.87),
       (176, 320, 111, 4, 4.5, 3.5, 3.548, 1, 0.85),
       (177, 329, 119, 4, 4.5, 4.5, 3.664, 1, 0.9 ),
       (178, 319, 110, 3, 3.5, 3.5, 3.616, 0, 0.82),
       (186, 327, 113, 4, 4.5, 4.5, 3.644, 1, 0.89),
       (187, 317, 107, 3, 3.5, 3. , 3.472, 1, 0.84),
       (188, 335, 118, 5, 4.5, 3.5, 3.776, 1, 0.93),
       (189, 331, 115, 5, 4.5, 3.5, 3.744, 1, 0.93),
       (190, 324, 112, 5, 5. , 5. , 3.632, 1, 0.88),
       (191, 324, 111, 5, 4.5, 4. , 3.664, 1, 0.9 ),
       (192, 323, 110, 5, 4. , 5. , 3.592, 1, 0.87),
       (193, 322, 114, 5, 4.5, 4. , 3.576, 1, 0.86),
       (194, 336, 118, 5, 4.5, 5. , 3.812, 1, 0.94),
       (203, 340, 120, 5, 4.5, 4.5, 3.964, 1, 0.97),
       (204, 334, 120, 5, 4. , 5. , 3.948, 1, 0.97),
       (212, 328, 110, 4, 5. , 4. , 3.656, 1, 0.82),
       (213, 338, 120, 4, 5. , 5. , 3.864, 1, 0.95),
       (214, 333, 119, 5, 5. , 4.5, 3.912, 1, 0.96),
       (215, 331, 117, 4, 4.5, 5. , 3.768, 1, 0.94),
       (216, 330, 116, 5, 5. , 4.5, 3.744, 1, 0.93),
       (217, 322, 112, 4, 4.5, 4.5, 3.704, 1, 0.91),
       (218, 321, 109, 4, 4. , 4. , 3.652, 1, 0.85),
       (219, 324, 110, 4, 3. , 3.5, 3.588, 1, 0.84),
       (230, 324, 111, 4, 3. , 3. , 3.604, 1, 0.82),
       (235, 330, 113, 5, 5. , 4. , 3.724, 1, 0.91),
       (236, 326, 111, 5, 4.5, 4. , 3.692, 1, 0.88),
       (237, 325, 112, 4, 4. , 4.5, 3.668, 1, 0.85),
       (238, 329, 114, 5, 4.5, 5. , 3.676, 1, 0.86),
       (246, 328, 110, 4, 4. , 2.5, 3.608, 1, 0.81),
       (254, 335, 115, 4, 4.5, 4.5, 3.872, 1, 0.93),
       (255, 321, 114, 4, 4. , 5. , 3.648, 0, 0.85),
       (260, 331, 119, 4, 5. , 4.5, 3.736, 1, 0.9 ),
       (261, 327, 108, 5, 5. , 3.5, 3.652, 1, 0.87),
       (269, 327, 113, 4, 4.5, 5. , 3.656, 0, 0.83),
       (277, 329, 113, 5, 5. , 4.5, 3.78 , 1, 0.89),
       (283, 312, 106, 3, 4. , 3.5, 3.516, 1, 0.81),
       (285, 340, 112, 4, 5. , 4.5, 3.864, 1, 0.94),
       (286, 331, 116, 5, 4. , 4. , 3.704, 1, 0.93),
       (287, 336, 118, 5, 4.5, 4. , 3.676, 1, 0.92),
       (288, 324, 114, 5, 5. , 4.5, 3.632, 1, 0.89),
       (289, 314, 104, 4, 5. , 5. , 3.608, 0, 0.82),
       (298, 320, 120, 3, 4. , 4.5, 3.644, 0, 0.86),
       (299, 330, 114, 3, 4.5, 4.5, 3.696, 1, 0.9 ),
       (312, 328, 108, 4, 4.5, 4. , 3.672, 1, 0.84),
       (326, 326, 116, 3, 3.5, 4. , 3.656, 1, 0.81),
       (336, 325, 111, 4, 4. , 4.5, 3.644, 1, 0.83),
       (338, 332, 118, 5, 5. , 5. , 3.788, 1, 0.94),
       (339, 323, 108, 5, 4. , 4. , 3.496, 1, 0.81),
       (340, 324, 107, 5, 3.5, 4. , 3.464, 1, 0.81),
       (360, 321, 107, 2, 2. , 1.5, 3.376, 0, 0.81),
       (361, 322, 110, 3, 4. , 5. , 3.456, 1, 0.85),
       (362, 334, 116, 4, 4. , 3.5, 3.816, 1, 0.93),
       (363, 338, 115, 5, 4.5, 5. , 3.692, 1, 0.91),
       (366, 330, 114, 4, 4.5, 3. , 3.668, 1, 0.86),
       (372, 324, 110, 3, 3.5, 3. , 3.688, 1, 0.89),
       (373, 336, 119, 4, 4.5, 4. , 3.848, 1, 0.95),
       (383, 324, 110, 4, 4.5, 4. , 3.66 , 1, 0.82),
       (385, 340, 113, 4, 5. , 5. , 3.896, 1, 0.96),
       (386, 335, 117, 5, 5. , 5. , 3.928, 1, 0.96),
       (393, 326, 112, 4, 4. , 3.5, 3.648, 1, 0.84),
       (395, 329, 111, 4, 4.5, 4. , 3.692, 1, 0.89),
       (396, 324, 110, 3, 3.5, 3.5, 3.616, 1, 0.82),
       (397, 325, 107, 3, 3. , 3.5, 3.644, 1, 0.84),
       (398, 330, 116, 4, 5. , 4.5, 3.78 , 1, 0.91),
       (400, 333, 117, 4, 5. , 4. , 3.864, 1, 0.95)],
      dtype=[('Serial_No', '<i4'), ('GRE_Score', '<i4'), ('TOEFL_Score', '<i4'), ('University_Rating', '<i4'), ('SOP', '<f8'), ('LOR', '<f8'), ('CGPA', '<f8'), ('Research', '<i4'), ('Chance_of_Admit', '<f8')])


So first we use boolean masking to pull out only those students we are interested in based on their chance of admission, then we pull out only their GPA scores, then we print the mean values.

In [52]:
print(graduate_admission[graduate_admission['Chance_of_Admit'] > 0.8]['GRE_Score'].mean())
print(graduate_admission[graduate_admission['Chance_of_Admit'] < 0.4]['GRE_Score'].mean())
328.7350427350427
302.2857142857143


Let's also do this with CGPA.

In [53]:
print(graduate_admission[graduate_admission['Chance_of_Admit'] > 0.8]['CGPA'].mean())
print(graduate_admission[graduate_admission['Chance_of_Admit'] < 0.4]['CGPA'].mean())
3.7106666666666666
3.0222857142857142

The GPA and GRE for students who have a higher chance of being admitted seems to be higher.

[^top]

Last updated 2020-12-16 16:09:16.280676 IST

Sentiment Analysis of Indian Print Media News

wordcloud

Podcast

Press play and let my words come alive!

Abstract

Newspapers or the print media is still one of the significant news publishing medium in several parts of the world. India has the second-largest newspaper market in the world, with daily newspapers reporting a combined circulation of over 240 million copies as of 2018. The overall sentimental pulse of a location (example, a city) can be determined by the news published in the location on any given day. It would be interesting to observe the variation in the sentiment across different cities on a particular day or over a period of time.

Problem Statement

The project aims to identify any variations in the sentiment of newspaper articles published across various geographical locations in India.

Objectives

  1. Identify overall sentiment of news published in a location.
  2. Identify variation in sentiments across multiple locations.

Constraints

  1. Sometimes various news agencies may print the same news differently (i.e., positively or negatively based on their perspectives). To mitigate this issue, news articles from different locations publshed by a single news agency will be used for analysys.

[^top]

Analytical Approach

Workflow

  1. Data source: News clippings or paper cuttings of articles from a newspaper company that has publication and distribution centers at more than one location is selected as a data source to minimize the constraint mentioned above.
  2. Optical Character Recognition (OCR): The news clippings are passed through an OCR to convert them in to text.
  3. Sentiment Analysis: The text output from OCR is analysed using NLTK sentiment analysis to identify the overall sentiment of the news published in the location.
  4. Sentiment Variation: Steps 1 through 3 are repeated for various locations and variations in sentiments are measured.

Packages and Statistical tools

  • zipfile to uncompress and access images from a zip file.
  • PIL Python Image Library to read images.
  • pytesseract A Python wrapper for Tesseract to perform Optical Character Recognition and convert images to texts.
  • nltk Python Natural Language Took Kit library to perform sentiment analysis. wordnet for stopwords and punkt for lemmatization.
  • matplotlib library to plot wordclouds and bar graphs for variation in sentiments across cities.
  • Bar plot is used to compare sentiments of cities

[^top]

Data Preperation and Cleansing

Data Collection

Newspaper clippings are collected from Deccan Chronicle newspaper(dated 2020-09-18) for the cities of Hyderabad and Chennai. The images are stored in two seperate zip files (hyderabad.zip, chennai.zip) corresponding to each city.

Data source: http://epaper.deccanchronicle.com/epaper_main.aspx

Datasets: https://gitlab.com/datasets_a/sentiment-analysis-of-indian-print-media-news

[^top]

Image to text conversion using OCR

In [89]:
# Importing libraries
import zipfile as z
from PIL import Image
import pytesseract

# txtDB is a list of list of texts from each location.
# For example, txtDB[0] is a list of texts from Hyderabad
# and txtDB[1} is a list of texts from Chennai
# When news from more locations are added, they will 
# be appended to this list
txtDB=[]
locations=["Hyderabad","Chennai"]
zipfiles=[location.lower()+".zip" for location in locations] # List of file paths of zip files
for filepath in zipfiles: # for each location's zip file
    txtList=[] # initializing empty text list to add OCR output
    with z.ZipFile(filepath) as myZip: # access the zip file
        for archive in myZip.infolist(): # access archive
            with myZip.open(archive) as imagefile: # access each image file
                image = Image.open(imagefile) # reading each file into image
                ocrText=pytesseract.image_to_string(image) # Image to text
                txtList.append(ocrText) # append text to list
    txtDB.append(txtList) # append text list to main list
In [90]:
# We have news from two locations so txtDB should have two elements
print(len(txtDB))
2
In [91]:
# Location 1 Hyderabad had 24 news clippings and 
# Location 2 Chennai had 35 news clippings.
# Checking if all news clippings are converted to texts
for i in txtDB:
    print(len(i))
24
35
In [92]:
# Checking a sample text output. 
#Example: Hyderabad first news clipping
print(txtDB[0][0])
 

Battleground Srinagar
J aOR

   

Kashmiri protesters clash with the police after a gun battle between mi
security forces at Batamaloo of Srinagar on Thursday. Police used tear gas shells and
pellet guns to disperse protesters. — H.U. NAQASH

 

In [93]:
#Example: Chennai last news clipping
print(txtDB[1][-1])
Old trick: PLA borrows leaf
from 2,200 years old battle

Chinese troops play Punjabi songs on loudspeakers at the LAC

Men have decided to stay
back and assist the Army

PAWAN BALI | DC
NEW DELHI, SEPT. 17:

While Indians are amused
over Chinese troops play-
ing Punjabi songs on loud-
speakers at Line of Actual
Control (LAC) at Eastern
Ladakh where for the first
time in 45 years shots
have been fired, its seems
PLA is using the
employed by Chinese Han
generals some 2,200 years
ago during so called
“Battle of Gaixia”.

In this battle, Han King
Liu Bang beat his Chu
rival Xiang Yu and estab-
lished the Han Dynasty in
China.

Chinese state run Global

  

  

playing Punjabi
LAC said that the Indian
army is in a situation of
“hearing the Chu songs on
four sides.”

‘The Global Times said
that the move of playing
Punjabi songs sends a
message to India that the
Indian army is isolated
and besieged on all sides.

“Hearing the Chu songs
on four sides” is a Chinese
idiom, which is said to
have originated from the
supposed “Battle of,
Gaixia”. After the fall
the Qin'Dyn
of Chu and the State of
Han fought for control of
China around 206 BC to
202 BC.

‘As per the legends
around 202 BC, Chu king

  

 

 

 

    

 

© IT SEEMS foolish if
PLA assumes that Punjabi
songs played at the LAC
will have the same impact
‘on a professional and bat-
tle hardened Indian Army
as what happened with
Chu soldiers some thou-
sands of years back.

Xiang Yu was trapped and
surrounded by the rival
Han forces in hills at Ga
Xia, The legends say to
weaken the morale of the
and King Xiang
ferocious fight:
er, Han soldiers started
singing Chu songs from all
sides.

After listening to these
songs, Chu" soldiers
thought that Han people
had captured their home-
land and brought Chu peo-
ple to the battlefield.

‘As per these stories, Chu
soldiers became worried
about their family mem-
bers, homesick and lost
the will to fight.

Many — Chu’ soldie
deserted, Even Chu King
is said to have become des:
perate after listening to
the Chu songs

 

   

  

  

 

 

 

committed suicide after
his forces tried to break
the trap.

However, it seems foolish
if the PLA assumes that
Punjabi songs played at
the LAC will have the
same impact on a profes:
sional and battle hardened
Indian Army as what hap-

 

FROM PG 1

‘These villages used to be
pit stops for
tourists and tho
ling to Adi Kailash;
would be offered home:
tays by the locals. Due to
the Covid-19 pandemic,
the people have been hit
hard. Most of them sell
various products includ
ing herbs which they
painstakingly collect from
mountains at the annual
trade between India and
China but even that did
not take place this year.
“Our main earnings are
through the trade every
year. ‘When we return
from China, we buy some
products which we sell
when we go down to the
town. This time around,
we do not know how to
survive,” said a local.

‘The villagers are’ wor-
ried that if tensions con-
tinue to rise between India
and China, they will pe
manently lose their sou
of income and in the
worst scenario, even their

    

 

   

 

 

 

 

    

© OF THE FIVE villages
in Dharchula of Pithoragarh district of Uttarakhand,
Kuti has a population of about 365 people living in
15

houses.

© NABHI HAS 78 people and 32 houses, Raung Kong
about 120 living in 35 houses, Napalachchu 74 in 25
houses and

Gunji about 335 in 194 houses.

© LOCATED AT an elevation of about 10,000 feet,
locals stay there for
six months every year and then migrate to the plains

© ALL THE villages are few kilometres away
from the tri-junction between India, China and Nepal

© CHINA HAS deployed surface-to-air missile near
Mount Kailash — not very far away from the villages

© ABOUT 975 people including 395 females reside
across the five border villages, leading tough lives.

houses. About 975 people gave our rations to them
including 395 females and transported their
reside across the five bor- equipment, arms and
der villages, leading tough ammunition on our backs.
lives . “During the 1962 We will do the same even
war, our ancestors assist- now if there is a repeat of
ed the Indian Army and 1962,” Virendra Singh
stood by them in the most Nabiyal, a local of Nabi
difficult times. We even

  

 

  

  

 

 

pened with Chu soldiers
some thousands of years
back. Only last week
Indian army's Sikh

Regiment observed the fought thousands of
123rd_Saragarhi_ Day Pathans in North West
where 22 soldiers of 4Sikh Frontier Province on.
in a famous ‘last-stand’ September 12, 1897.

   

[^top]

Sentiment Analysys using NLTK

In [94]:
# Importing libraries
import nltk
nltk.download('punkt')
nltk.download('stopwords')
nltk.download('wordnet')
from nltk.corpus import stopwords 
from wordcloud import WordCloud
import re
import matplotlib.pyplot as plt
[nltk_data] Downloading package punkt to /root/nltk_data...
[nltk_data]   Package punkt is already up-to-date!
[nltk_data] Downloading package stopwords to /root/nltk_data...
[nltk_data]   Package stopwords is already up-to-date!
[nltk_data] Downloading package wordnet to /root/nltk_data...
[nltk_data]   Package wordnet is already up-to-date!
In [99]:
stop_words = set(stopwords.words('english'))
sentiment_scores=[]
for Location,LocationText in zip(locations,txtDB):
    print("------------------\nLocation: {}\n------------------".format(Location))
    txt=" ".join(LocationText).lower()
    print("Initial text length:",len(txt))
    # remove single quotes
    txt = txt.replace("'", "")
    # Tokenization
    tokens = nltk.word_tokenize(txt)
    # Remove extra characters and remove stop words.
    txt = [''.join(re.split("[ =—.,;:!?‘’``''@#$%^_&*()<>{}~\n\t\\\-]", word)) for word in nltk.Text(tokens)]
    # Filter stop words and empty entries
    txt=[w for w in txt if not w in stop_words and len(w) != 0] 
    # Lemmatization
    lemmatizer=nltk.WordNetLemmatizer()
    txt=[lemmatizer.lemmatize(w) for w in txt]
    print("Reduced text length after removing stop words: {}\n".format(len(txt)))
    # Plots
    (w,h,f)=(1000,800,(10,10)) # word cloud width and height
    # Plot word frequency
    freq = nltk.FreqDist(txt)
    plt.figure(figsize = (10, 4))
    freq.plot(20, cumulative=False, title=Location+" Word Frequency")
    plt.show()
    # Plot word cloud
    print("\n------------------------------------------------------------------")
    plt.figure(figsize = f,edgecolor="black")
    wordcloud=WordCloud(background_color='White',colormap='seismic',width=w,height=h).generate(" ".join(txt))
    plt.imshow(wordcloud)
    plt.axis("off") 
    plt.title(Location+" Word Cloud",fontsize=16)
    plt.show()
    # Positive words
    print("\n------------------------------------------------------------------")
    with open("positive-words.txt","r") as pos:
        poswords = pos.read().split("\n")
    txtpos=[w for w in txt if w in poswords]
    plt.figure(figsize = f)
    wordcloud=WordCloud(background_color='White',colormap='seismic',width=w,height=h).generate(" ".join(txtpos))
    plt.imshow(wordcloud)
    plt.axis("off") 
    plt.title(Location+" Positive Word Cloud",fontsize=16)
    plt.show()
    # Negative words
    print("\n------------------------------------------------------------------")
    with open("negative-words.txt","r") as neg:
        negwords = neg.read().split("\n")
    txtneg=[w for w in txt if w in negwords]
    plt.figure(figsize = f)
    wordcloud=WordCloud(background_color='White',colormap='seismic',width=w,height=h).generate(" ".join(txtneg))
    plt.imshow(wordcloud)
    plt.axis("off") 
    plt.title(Location+" Negative Word Cloud",fontsize=16)
    plt.show()
    sentiment_scores.append([len(txtpos),len(txtneg)])
------------------
Location: Hyderabad
------------------
Initial text length: 43686
Reduced text length after removing stop words: 4550

No description has been provided for this image
------------------------------------------------------------------
No description has been provided for this image
------------------------------------------------------------------
No description has been provided for this image
------------------------------------------------------------------
No description has been provided for this image
------------------
Location: Chennai
------------------
Initial text length: 59661
Reduced text length after removing stop words: 6147

No description has been provided for this image
------------------------------------------------------------------
No description has been provided for this image
------------------------------------------------------------------
No description has been provided for this image
------------------------------------------------------------------
No description has been provided for this image

[^top]

Variation in sentimental scores

Overall sentiment is calculated as (Number of positive words - Number of negative words)/(Sum of number of positive and negative words)

Variation of sentiment across locations is observed by plotting a bar graph of their overall sentiments.

In [100]:
import pandas as pd
df=pd.DataFrame(sentiment_scores,locations,["Pos","Neg"])
df["Sentiment"]=(df.Pos-df.Neg)/(df.Pos+df.Neg)
print(df)
           Pos  Neg  Sentiment
Hyderabad  126  151  -0.090253
Chennai    179  235  -0.135266
In [106]:
ax=df.plot.bar(y=["Pos","Neg"],color=["lightblue","red"],edgecolor="black")
plt.title("Variation in Pos/Neg news across different locations",fontsize=14)
plt.ylabel('Word count',fontsize=12)
for p in ax.patches:
    ax.annotate(str(p.get_height()), (p.get_x()+0.07, p.get_height()*0.9),
                fontsize=12)
plt.xticks(rotation=0)
plt.show()
No description has been provided for this image
In [108]:
ax=df.plot.bar(y="Sentiment",color="darkred",edgecolor="black")
plt.title("Variation in Overall Sentiment across different locations",fontsize=14)
plt.ylabel('Sentiment score',fontsize=12)
plt.xticks(rotation=0)
for p in ax.patches:
    ax.annotate(str(round(p.get_height(),2)), (p.get_x()+0.15, p.get_height() * 0.95),
                fontsize=12,color="white")
ax.get_legend().remove()
ax.xaxis.tick_top()
plt.show()
No description has been provided for this image

[^top]

Conclusions

  • The overall sentiment of news articles published today in Hyderabad and Chennai is negative.
  • There is a variation in the level of negative sentiment in news published in both cities. Today, Chennai newspaper had more negative articles than Hyderabad.

[^top]

Future Directions

  • A time series analysis could be done using historical data to understand changes in sentiments.
  • This study can be expanded to all the locations to create a nationwide or global heat map of news sentiment.
  • Multiple newspapers can be compared to classify how positive or negative a news agency is in the overall spectrum.

[^top]

Notes:

I did this project on 2020-09-18 when I attended the Artificial Intelligence workshop conducted by SASTRA in September 2020, however, it's published three months later, so the data for sentiment analysis is from September and not from December 2020.

Last updated 2020-12-11 22:04:46.917359 IST

Convert videos from H265/x265 to H264/x264 in Python with ffmpy

wordcloud

Background

There are times when we need to convert audio and/or video files from one format to another. May be you found an old VHS tape and want to convert it to a digital format, or want to compress high quality audio files to smaller sizes to fit in your portable device, or want to experiment with different AV formats.

A quick internet search will bring up numerous links to several audio/video conversion tools, some free, some paid, some with adware and some with spyware or malware too. My first preference is always to look for opensource solutions and that's when I came across FFmpeg codecs.

FFmpeg

If you happened to listen to music a couple of decades ago, you'll remember that some of the audio files were available in Real Media format and the files had an extension .rm. These files played only Real Media Player and I was not a huge fan of their media player. I preferred the universal MP3 audio format and was a fan of Winamp because it really whips the llama's ass (Winamp users will get this! Play the clip below for nostalgia.).

I wanted to convert my Real Media audio files to MP3, and that is when I came across FFmpeg. FFmpeg is a free and open-source software project consisting of a large suite of libraries and programs for handling video, audio, and other multimedia files and streams. At its core is the FFmpeg program itself, designed for command-line-based processing of video and audio files. Most of the A/V converter tools use the free FFmpeg program in the background. If you are familiar with basic command line concepts, you can download FFmpeg and use it to convert audio and video files. Once I got the hang of it, I was able to write a batch file and convert my Real Media audio library to MP3. FFmpeg also offers another free command-line program called ffplay that is capable of playing almost every kind of audio or video file.

ffmpeg-python

The FFmpeg CLI is extremely powerful and works brilliantly if you can manage to write its somewhat complex code. If you're like me, you might at times prefer doing things in Python instead as I find it both powerful and easily readable. ffmpeg-python is a Python FFmpeg wrapper that supports simple as well as complex signal graphs and makes it easier to write code.

ffmpy

Can it get even more convenient and readable? The answer is yes. ffmpy is another Python FFmpeg wrapper that, in my opinion, is much easier to use than ffmpeg-python. Since I have used FFmpeg CLI before, I was looking for a wrapper that is closest to it in syntax and ffmpy is the best I could find so far.

In layman terms, an FFmpeg command can be thought of consisting of three parts - an input file, a set of arguments, and an output file. The arguments are optional for simple conversions as FFmpeg is clever enough to process coversions based on file extensions.

For example, the command for converting an AVI video file named 'input.avi' to an MP4 video with the name 'output.mp4' is simply the following. FFmpeg knows from the file extensions that it has to convert an AVI file to an MP4 file.

ffmpeg -i input.avi output.mp4

When performing complex conversions that require specific codecs, quality, etc we will need to pass necessary arguments as well. In the example below, the arguments specify that the video codec to be used is x264, that the FFmpeg preset is set to slow for better video quality, that another quality parameter of crf 19 is passed and that the audio is encoded with AAC with a bitrate of 128K. The FFmpeg documentation has more information on arguments, APIs and libraries.

ffmpeg -i input.avi -c:v libx264 -preset slow -crf 19 -c:a libvo_aacenc -b:a 128k output.mp4

ffmpy's syntax has similar components with a different layout. The input/output files and their arguments are passed in the form of a dictionary instead of a string.

ffmpy.FFmpeg(
    inputs={'input.avi': None},
    outputs={'output.mp4': None}
    )

None in the outputs dictionary can be replaced with arguments if any.

ffmpy: converting videos from H265 to H264 format

H265 is the one the latest video formats that provides high compression but also requires more powerful processors to play them. x265 is a common codec that can play an H265 video. H265 encoded video files are comparitively smaller in size than those encoded with H264, which is a predecessor of H265. If you try to play H265 videos, especially the ones in HD and above in an older or a slower PC, you may notice considerable amount of lag and pixelation. The video appears choppy and pauses intermittently waiting for the processor to decode. However, most of these older or slower computers can play H264 files very smoothly even in full HD.

In this example, I will attempt to convert my Star Wars Rebels video collection from H265 video format to H264 format with ffmpy wrapper. My starwars directory contains subdirectories for each season, namely S01, S02, S03 and S04. Each season directory then contains its episodes in H265 encoded MP4 files.

starwars
    |__ S01
    |__ S02
    |__ S03
    |__ S04

I would like to traverse files in each subdirectory (or season), convert them to H264 videos and place them in a new directory for that season as below. The new subdirectories are already created.

starwars
    |__ S01
    |__ S01_264
    |__ S02
    |__ S02_264
    |__ S03
    |__ S03_264
    |__ S04
    |__ S04_264

I will use Python's glob module to traverse through files and get their filenames.

Convert 10-bit H.265 to 10-bit H.264

The FFmpeg command to convert a 10-bit H.265 to a 10-bit H.264 video file is

ffmpeg -i input -c:v libx264 -crf 18 -c:a copy output.mkv

This conversion is almost lossless and maintains equivalent audio/video quality as the source file. If you want true lossless conversion, use -crf 0 instead but also be wary of the output file size.

Install the ffmpy package.

In [1]:
!pip install ffmpy
Collecting ffmpy
  Downloading https://files.pythonhosted.org/packages/9e/12/896dbb507a02a46eb6488fefc0b74a8c33eec59257ee3c35a2f41563c48e/ffmpy-0.2.3.tar.gz
Building wheels for collected packages: ffmpy
  Building wheel for ffmpy (setup.py) ... done
  Created wheel for ffmpy: filename=ffmpy-0.2.3-cp36-none-any.whl size=4623 sha256=be1a48cc4c3e4375dee1a71c997845755593fd5e842a04cfacec472c3b5fa50f
  Stored in directory: /root/.cache/pip/wheels/99/51/33/ca9d92c9fa38a196ad8647f5fcc9eadbca8a96bd5f8a2b5f7d
Successfully built ffmpy
Installing collected packages: ffmpy
Successfully installed ffmpy-0.2.3
In [2]:
# Importing libraries
from ffmpy import FFmpeg
from glob import glob
In [3]:
# Input the season number to be converted.
season=input("Season:")
# Get the full directory path for the season.
# If you're running this on Google Colab, don't forget to mount the drive first.
dirpath='/content/drive/MyDrive/starwars/S0'+season+'/'
# For each .mkv file in the given directory
for infile in sorted(glob(dirpath+'*.mkv')):
    # Create an output filename and path using string replacements.  
    outfile=infile.replace('265-HETeam','264').replace('/S0'+season+'/','/S0'+season+'_264/')
    # Define ffmpy parameters  
    ff=FFmpeg(
      inputs={infile:None},
      outputs={outfile:['-c:v', 'libx264', '-crf', '18', '-c:a','copy']}
    )
    # Convert
    ff.run()
    # If successful, print full output filename
    print(outfile)
Season: 1
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E01.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E02.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E03.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E04.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E05.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E06.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E07.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E08.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E09.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E10.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E11.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E12.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E13.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E14.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S01_264/Star.Wars.Rebels.S01E15.720p.BluRay.x264.mkv
  • In the above example, 'infile' refers to each input filename sorted in alphabetical order. glob returns the filename along with its full path, so there is no need to add path again.

    for infile in sorted(glob(dirpath+'*.mkv'))

  • The output filename 'outfile' is created from 'infile' by two string replacements. First the '265-HETeam' part of the filename is replaced with '264', then the directory name 'S01' in the path is replaced with 'S01_264'.

    outfile=infile.replace('265-HETeam','264').replace('/S0'+season+'/','/S0'+season+'_264/')

  • It is important to pass the FFmpeg arguments in the form of a list of strings and not as a single string. outputs={outfile:['-c:v', 'libx264', '-crf', '18', '-c:a','copy']}

I have successfully converted all videos in my S01 directory to H264 format. If I have to convert another season, let's say season 2, then I run the same code block from above and enter '2' when prompted.

In [4]:
# Input the season number to be converted.
season=input("Season:")
# Get the full directory path for the season.
# If you're running this on Google Colab, don't forget to mount the drive first.
dirpath='/content/drive/MyDrive/starwars/S0'+season+'/'
# For each .mkv file in the given directory
for infile in sorted(glob(dirpath+'*.mkv')):
    # Create an output filename and path using string replacements.  
    outfile=infile.replace('265-HETeam','264').replace('/S0'+season+'/','/S0'+season+'_264/')
    # Define ffmpy parameters  
    ff=FFmpeg(
      inputs={infile:None},
      outputs={outfile:['-c:v', 'libx264', '-crf', '18', '-c:a','copy']}
    )
    # Convert
    ff.run()
    # If successful, print full output filename
    print(outfile)
Season: 2
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E01.Part1.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E01.Part2.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E02.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E03.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E04.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E05.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E06.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E07.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E08.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E09.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E10.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E11.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E12.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E13.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E14.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E15.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E16.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E17.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E18.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E19.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E20.Part1.720p.BluRay.x264.mkv
/content/drive/MyDrive/starwars/S02_264/Star.Wars.Rebels.S02E20.Part2.720p.BluRay.x264.mkv

Convert 10-bit H.265 to 8-bit H.264

Following is the FFmpeg command to convert an H265 video to an H264 video with a smaller file size.

ffmpeg -i input -c:v libx264 -crf 18 -vf format=yuv420p -c:a copy output.mkv

8-bit output can be obtained by chosing the yuv420p pixel format. As discussed earlier, for a true lossless conversion, use -crf 0 instead.

The output arguments for the ffmpy wrapper would be

outputs={outfile:['-c:v', 'libx264', '-crf', '18', '-vf', 'format=yuv420p', '-c:a','copy']}

Last updated 2020-12-09 22:59:49.140846 IST

Reading, Writing CSV files & Basic Data Analysis without Pandas

wordcloud

Let's import our datafile mpg.csv, which contains fuel economy data for 234 cars.

  • mpg : miles per gallon
  • class : car classification
  • cty : city mpg
  • cyl : # of cylinders
  • displ : engine displacement in liters
  • drv : f = front-wheel drive, r = rear wheel drive, 4 = 4wd
  • fl : fuel (e = ethanol E85, d = diesel, r = regular, p = premium, c = CNG)
  • hwy : highway mpg
  • manufacturer : automobile manufacturer
  • model : model of car
  • trans : type of transmission
  • year : model year

Reading a CSV file

The datafile mpg.csv is located in my GitLab public repository at https://gitlab.com/datasets_a/mpg-data. The URL for accessing the raw file is https://gitlab.com/datasets_a/mpg-data/-/raw/master/mpg.csv

In this example, we will be using Python's native csv module to read and write CSV files. The csv module offers the following functions to read/write files:

  • Reading
    • csv.reader
    • csv.DictReader
  • Writing
    • csv.writer
    • csv.DictWriter

If you are interested in different ways of reading CSV files from GitLab, especially using the python-gitlab package, I tried to illustrate them here

csv.reader
In [1]:
import csv, requests
from io import StringIO

url = "https://gitlab.com/datasets_a/mpg-data/-/raw/master/mpg.csv"
# Reading URL data
s = requests.get(url).content
# Decoding and formatting
csvdata = list(csv.reader(StringIO(s.decode('utf-8'))))
# Printing the first 5 rows
for row in csvdata[:5]:
    print(row)
['', 'manufacturer', 'model', 'displ', 'year', 'cyl', 'trans', 'drv', 'cty', 'hwy', 'fl', 'class']
['1', 'audi', 'a4', '1.8', '1999', '4', 'auto(l5)', 'f', '18', '29', 'p', 'compact']
['2', 'audi', 'a4', '1.8', '1999', '4', 'manual(m5)', 'f', '21', '29', 'p', 'compact']
['3', 'audi', 'a4', '2', '2008', '4', 'manual(m6)', 'f', '20', '31', 'p', 'compact']
['4', 'audi', 'a4', '2', '2008', '4', 'auto(av)', 'f', '21', '30', 'p', 'compact']
csv.DictReader

The data can also be read into a Python dictionary format using the csv.DictReader function.

In [2]:
dictdata = list(csv.DictReader(StringIO(s.decode('utf-8'))))
# Printing the first 2 rows
dictdata[:2]
Out[2]:
[{'': '1',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'auto(l5)',
  'drv': 'f',
  'cty': '18',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'},
 {'': '2',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'manual(m5)',
  'drv': 'f',
  'cty': '21',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'}]

[^top]

Writing a CSV file

csv.writer
In [3]:
filepath='../../files/py/007/mpg.csv'
In [4]:
with open(filepath,'w',newline='') as f:
    # Creating a csv writer object
    fwriter=csv.writer(f)
    # writing data
    fwriter.writerows(csvdata)


Screenshot of the output file:

output


In case, the fields and records are not available on one place, they can be written seperately. Let's seperate the fields and records from csvdata and write them to a file.

In [5]:
fields=csvdata[0] # The first element of the list
print(fields)
['', 'manufacturer', 'model', 'displ', 'year', 'cyl', 'trans', 'drv', 'cty', 'hwy', 'fl', 'class']
In [6]:
records=csvdata[1:] # This is rest of the data
#printing the first 5 records
for record in records[:5]:
    print(record)
['1', 'audi', 'a4', '1.8', '1999', '4', 'auto(l5)', 'f', '18', '29', 'p', 'compact']
['2', 'audi', 'a4', '1.8', '1999', '4', 'manual(m5)', 'f', '21', '29', 'p', 'compact']
['3', 'audi', 'a4', '2', '2008', '4', 'manual(m6)', 'f', '20', '31', 'p', 'compact']
['4', 'audi', 'a4', '2', '2008', '4', 'auto(av)', 'f', '21', '30', 'p', 'compact']
['5', 'audi', 'a4', '2.8', '1999', '6', 'auto(l5)', 'f', '16', '26', 'p', 'compact']
In [7]:
# Writing to a csv file
with open(filepath,'w',newline='') as f:
    # Creating a csv writer object
    fwriter=csv.writer(f)
    # Writing the fields
    fwriter.writerow(fields)
    # writing data (records)
    fwriter.writerows(records)


Screenshot of the output file:

output
csv.DictWriter

csv.DictWriter operates like a regular writer but maps dictionaries onto output rows.

In [8]:
fields=list(dictdata[0].keys())
print(fields)
['', 'manufacturer', 'model', 'displ', 'year', 'cyl', 'trans', 'drv', 'cty', 'hwy', 'fl', 'class']
In [9]:
with open(filepath,'w',newline='') as f:
    # Creating a csv DictWriter object
    fwriter=csv.DictWriter(f,fieldnames=fields)
    # Writing fields
    fwriter.writeheader()
    # writing records
    fwriter.writerows(dictdata)


Screenshot of the output file:

output

[^top]

Basic Data Analysis

In [10]:
import csv 

with open('../../files/py/007/mpg.csv') as csvfile:
    mpg = list(csv.DictReader(csvfile))
    
mpg[:2]
Out[10]:
[{'': '1',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'auto(l5)',
  'drv': 'f',
  'cty': '18',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'},
 {'': '2',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'manual(m5)',
  'drv': 'f',
  'cty': '21',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'}]


csv.DictReader has read in each row of our csv file as a dictionary. len shows that our list is comprised of 234 dictionaries.

In [11]:
len(mpg)
Out[11]:
234

*keys* gives us the column names of our csv.
In [12]:
mpg[0].keys()
Out[12]:
dict_keys(['', 'manufacturer', 'model', 'displ', 'year', 'cyl', 'trans', 'drv', 'cty', 'hwy', 'fl', 'class'])

This is how to find the average cty fuel economy across all cars. All values in the dictionaries are strings, so we need to convert to float.
In [13]:
total_mpg=0
for record in mpg:
    total_mpg+=float(record['cty'])
avg_mpg=total_mpg/len(mpg)
print(avg_mpg)
16.858974358974358


The same can be performed using list comprehension.

In [14]:
avg_mpg=sum(float(record['cty']) for record in mpg) / len(mpg)
print(avg_mpg)
16.858974358974358


The number of decimal points displayed in the output can be controlled by the magic function %precision. Let's limit the precision to two decimals. Note that this magic function does not work if we use the print function.

In [15]:
%precision 2
avg_mpg
Out[15]:
16.86

Similarly this is how to find the average hwy fuel economy across all cars.
In [16]:
sum(float(d['hwy']) for d in mpg) / len(mpg)
Out[16]:
23.44

Use `set` to return the unique values for the number of cylinders the cars in our dataset have.
In [17]:
cylinders = set(d['cyl'] for d in mpg)
print(cylinders)
{'5', '8', '4', '6'}

Here's a more complex example where we are grouping the cars by number of cylinder, and finding the average cty mpg for each group.
In [18]:
CtyMpgByCyl = []

for c in cylinders: # iterate over all the cylinder levels
    summpg = 0
    cyltypecount = 0
    for d in mpg: # iterate over all dictionaries
        if d['cyl'] == c: # if the cylinder level type matches,
            summpg += float(d['cty']) # add the cty mpg
            cyltypecount += 1 # increment the count
    CtyMpgByCyl.append((c, summpg / cyltypecount)) # append the tuple ('cylinder', 'avg mpg')

CtyMpgByCyl.sort(key=lambda x: x[0])
CtyMpgByCyl
Out[18]:
[('4', 21.01), ('5', 20.50), ('6', 16.22), ('8', 12.57)]

Use `set` to return the unique values for the class types in our dataset.
In [19]:
vehicleclass = set(d['class'] for d in mpg) # what are the class types
vehicleclass
Out[19]:
{'2seater', 'compact', 'midsize', 'minivan', 'pickup', 'subcompact', 'suv'}

And here's an example of how to find the average hwy mpg for each class of vehicle in our dataset.
In [20]:
HwyMpgByClass = []

for t in vehicleclass: # iterate over all the vehicle classes
    summpg = 0
    vclasscount = 0
    for d in mpg: # iterate over all dictionaries
        if d['class'] == t: # if the cylinder amount type matches,
            summpg += float(d['hwy']) # add the hwy mpg
            vclasscount += 1 # increment the count
    HwyMpgByClass.append((t, summpg / vclasscount)) # append the tuple ('class', 'avg mpg')

HwyMpgByClass.sort(key=lambda x: x[1])
HwyMpgByClass
Out[20]:
[('pickup', 16.88),
 ('suv', 18.13),
 ('minivan', 22.36),
 ('2seater', 24.80),
 ('midsize', 27.29),
 ('subcompact', 28.14),
 ('compact', 28.30)]

[^top]

Last updated 2020-12-07 18:23:55.089159 IST

Reading CSV files from GitLab with csv, pandas and python-gitlab

wordcloud

Why I moved from GitHub to GitLab

I started learning Git with GitHub and used it for quite a while. Then Microsoft acquired GitHub in 2016 or so. I was not very comfortable with it considering how I feel about Microsoft's sneaky data collection policies (for example, Windows 10 appears to be one big data mining engine when you dig deeper into its processes that the first thing you need to do after installing Windows 10 is debloat it, i.e., remove bloatware, disable telemetry and tighten your privacy settings) and how the company that was once openly against Linux is now trying to influence open source software by buying its way into The Free Software Foundation (FSF). I was looking some alternatives and stumbled upon GitLab.

It did not take much time to realize that GitLab offers much more than GitHub. It offered a complete development to deployment service until GitHub. Back when GitHub used a third party Travis CI, GitLab already had its own CI/CD system available for all users. It offered better private repo features and free CI/CD even for free users. Since a chunk of open source loving developers migrated from GitHub to GitLab after the acquisition, Microsoft had increased GitHub features for free users and recently developed its own CI, but in my opinion GitLab is still far ahead.

With added security and features, also comes a bit of complexity. Firstly, GitLab blocks any requests without a user-agent possible considering them to be crawlers or bots. So, sometimes we need to explicitly specify a user-agent like Mozilla or Gecko, etc. Secondly, GitLab uses base64 encryption on all it's content. It's always not enough just to be able to access the file as it's encrypted. We need to decode it to use it. I didn't find much documentation online on reading a csv file from a GitLab repository and had to spend some time figuring it out, so this page might be useful for some.

[^top]

Reading a CSV file from GitLab with csv or pandas

CSV stands for Comma Seperated Values. A CSV file typically contains data values seperated by comma, or rarely by other delimeters like a semi-colon. The file I am trying to read is called 'mpg.csv' located in my GitLab public repository https://gitlab.com/datasets_a/mpg-data.

Step 1

We can use either of the following Python packages to read the URL. Both are built-in packages in Python and need not be installed seperately.

Step 2

The data from the URL is returned in the form of a text string, which will be decoded using the StringIO function of Python io module.

Step 3

The data read from the URL will be in raw format and needs to be converted to a structured format. We can use either of the following to do that.

  • Python's default csv module. The csv.Reader() function is used to convert data into delimited strings, whereas the csv.Dictreader() function can be used to convert data into a Python dictionary format.
  • pandas (short for panel data) library. The pandas.read_csv module is specifically what we will use here.

Method 1: Using requests and csv

with csv.Reader
In [1]:
import csv, requests
from io import StringIO

url = "https://gitlab.com/datasets_a/mpg-data/-/raw/master/mpg.csv"
# Reading URL data
s = requests.get(url).content
# Decoding & formatting
data=csv.reader(StringIO(s.decode('utf-8')))
#Printing the first 5 rows
for row in list(data)[:5]:
    print(row)
['', 'manufacturer', 'model', 'displ', 'year', 'cyl', 'trans', 'drv', 'cty', 'hwy', 'fl', 'class']
['1', 'audi', 'a4', '1.8', '1999', '4', 'auto(l5)', 'f', '18', '29', 'p', 'compact']
['2', 'audi', 'a4', '1.8', '1999', '4', 'manual(m5)', 'f', '21', '29', 'p', 'compact']
['3', 'audi', 'a4', '2', '2008', '4', 'manual(m6)', 'f', '20', '31', 'p', 'compact']
['4', 'audi', 'a4', '2', '2008', '4', 'auto(av)', 'f', '21', '30', 'p', 'compact']
with csv.DictReader
In [2]:
# Decoding and formatting
data=list(csv.DictReader(StringIO(s.decode('utf-8'))))
# Printing the first 2 rows
data[:2]
Out[2]:
[{'': '1',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'auto(l5)',
  'drv': 'f',
  'cty': '18',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'},
 {'': '2',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'manual(m5)',
  'drv': 'f',
  'cty': '21',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'}]

Method 2: Using urllib and csv

with csv.Reader
In [3]:
import csv
from urllib.request import Request, urlopen
from io import StringIO

url = "https://gitlab.com/datasets_a/mpg-data/-/raw/master/mpg.csv"
# Reading URL data. 
myHeaders = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)'} # Even some random text works as headers
url_request  = Request(url, headers=myHeaders)
response = urlopen(url_request).read()
# Decoding and formatting
data=csv.reader(StringIO(response.decode('utf-8')))
#Printing first 5 rows
for row in list(data)[:5]:
    print(row)
['', 'manufacturer', 'model', 'displ', 'year', 'cyl', 'trans', 'drv', 'cty', 'hwy', 'fl', 'class']
['1', 'audi', 'a4', '1.8', '1999', '4', 'auto(l5)', 'f', '18', '29', 'p', 'compact']
['2', 'audi', 'a4', '1.8', '1999', '4', 'manual(m5)', 'f', '21', '29', 'p', 'compact']
['3', 'audi', 'a4', '2', '2008', '4', 'manual(m6)', 'f', '20', '31', 'p', 'compact']
['4', 'audi', 'a4', '2', '2008', '4', 'auto(av)', 'f', '21', '30', 'p', 'compact']
In [4]:
import csv
from urllib.request import Request, urlopen
from io import StringIO

url = "https://gitlab.com/datasets_a/mpg-data/-/raw/master/mpg.csv"
# Reading URL data
myHeaders = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)'} # Even some random text works as headers
url_request  = Request(url, headers=myHeaders)
response = urlopen(url_request).read()
data=list(csv.DictReader(StringIO(response.decode('utf-8'))))
# Printing the first 2 rows
data[:2]
Out[4]:
[{'': '1',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'auto(l5)',
  'drv': 'f',
  'cty': '18',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'},
 {'': '2',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'manual(m5)',
  'drv': 'f',
  'cty': '21',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'}]

Method 3: Using requests and pandas

In [5]:
import requests
from io import StringIO
import pandas as pd

url = "https://gitlab.com/datasets_a/mpg-data/-/raw/master/mpg.csv"
# Reading URL, decoding and converting it to pandas dataframe using read_csv
df = pd.read_csv(StringIO(requests.get(url).text))
# Printing the first 5 rows of the dataframe
df.head()
Out[5]:
Unnamed: 0 manufacturer model displ year cyl trans drv cty hwy fl class
0 1 audi a4 1.8 1999 4 auto(l5) f 18 29 p compact
1 2 audi a4 1.8 1999 4 manual(m5) f 21 29 p compact
2 3 audi a4 2.0 2008 4 manual(m6) f 20 31 p compact
3 4 audi a4 2.0 2008 4 auto(av) f 21 30 p compact
4 5 audi a4 2.8 1999 6 auto(l5) f 16 26 p compact

Method 4: Using urllib and pandas

In [6]:
from urllib.request import Request, urlopen
from io import StringIO
import pandas as pd

url = "https://gitlab.com/datasets_a/mpg-data/-/raw/master/mpg.csv"
# Reading URL data
myHeaders = {'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64)'} # Even some random text works as headers
url_request  = Request(url, headers=myHeaders)
response = urlopen(url_request).read()
# Decoding and converting it to pandas dataframe using read_csv
df = pd.read_csv(StringIO(response.decode('utf-8')))
# Printing the first 5 rows of the dataframe
df.head()
Out[6]:
Unnamed: 0 manufacturer model displ year cyl trans drv cty hwy fl class
0 1 audi a4 1.8 1999 4 auto(l5) f 18 29 p compact
1 2 audi a4 1.8 1999 4 manual(m5) f 21 29 p compact
2 3 audi a4 2.0 2008 4 manual(m6) f 20 31 p compact
3 4 audi a4 2.0 2008 4 auto(av) f 21 30 p compact
4 5 audi a4 2.8 1999 6 auto(l5) f 16 26 p compact

[^top]

Reading a CSV file from GitLab with python-gitlab

python-gitlab is a Python package providing access to the GitLab server API.

Install with Anaconda

conda install -c conda-forge python-gitlab

Let's explore the package a little.

In [7]:
# Importing library
import gitlab 


Next, we will use the gitlab.Gitlab class to create a Gitlab object gl. The URL in question belongs to my public repository, so we don't need to pass any authentication tokens to access it. However, if we were to access a private repository, we will need to pass a personal token, an oauth token or a job token for authentication.

In [8]:
# anonymous gitlab instance, read-only for public resources
gl=gitlab.Gitlab('https://gitlab.com/')


A Gitlab account typically consists of groups and projects. A group may contain sub-groups or projects, and each sub-group may have more projects or its own sub-groups.

Group
|___ Project
|___ Project
|___ Sub-group
      |___ Project
      |___ Sub-group
            |___ Project

Each group or project in GitLab has a unique ID. Let's get a list of projects and their information under one of my public groups with group id 9799560

In [9]:
# get the group with id == 9799560
group = gl.groups.get(9799560)
for project in group.projects.list():
    print('-----------------------')
    print(project)
-----------------------
<class 'gitlab.v4.objects.GroupProject'> => {'id': 23134556, 'description': '', 'name': 'Python for Data Science', 'name_with_namespace': 'datasets / Python for Data Science', 'path': 'python-for-data-science', 'path_with_namespace': 'datasets_a/python-for-data-science', 'created_at': '2020-12-16T05:31:29.818Z', 'default_branch': 'master', 'tag_list': [], 'ssh_url_to_repo': '[email protected]:datasets_a/python-for-data-science.git', 'http_url_to_repo': 'https://gitlab.com/datasets_a/python-for-data-science.git', 'web_url': 'https://gitlab.com/datasets_a/python-for-data-science', 'readme_url': 'https://gitlab.com/datasets_a/python-for-data-science/-/blob/master/README.md', 'avatar_url': None, 'forks_count': 0, 'star_count': 0, 'last_activity_at': '2020-12-17T13:08:27.730Z', 'namespace': {'id': 9799560, 'name': 'datasets', 'path': 'datasets_a', 'kind': 'group', 'full_path': 'datasets_a', 'parent_id': None, 'avatar_url': None, 'web_url': 'https://gitlab.com/groups/datasets_a'}, '_links': {'self': 'https://gitlab.com/api/v4/projects/23134556', 'issues': 'https://gitlab.com/api/v4/projects/23134556/issues', 'merge_requests': 'https://gitlab.com/api/v4/projects/23134556/merge_requests', 'repo_branches': 'https://gitlab.com/api/v4/projects/23134556/repository/branches', 'labels': 'https://gitlab.com/api/v4/projects/23134556/labels', 'events': 'https://gitlab.com/api/v4/projects/23134556/events', 'members': 'https://gitlab.com/api/v4/projects/23134556/members'}, 'packages_enabled': True, 'empty_repo': False, 'archived': False, 'visibility': 'public', 'resolve_outdated_diff_discussions': False, 'container_registry_enabled': True, 'container_expiration_policy': {'cadence': '1d', 'enabled': False, 'keep_n': 10, 'older_than': '90d', 'name_regex': '.*', 'name_regex_keep': None, 'next_run_at': '2020-12-17T05:31:29.841Z'}, 'issues_enabled': True, 'merge_requests_enabled': True, 'wiki_enabled': True, 'jobs_enabled': True, 'snippets_enabled': True, 'service_desk_enabled': True, 'service_desk_address': 'incoming+datasets-a-python-for-data-science-23134556-issue-@incoming.gitlab.com', 'can_create_merge_request_in': False, 'issues_access_level': 'enabled', 'repository_access_level': 'enabled', 'merge_requests_access_level': 'enabled', 'forking_access_level': 'enabled', 'wiki_access_level': 'enabled', 'builds_access_level': 'enabled', 'snippets_access_level': 'enabled', 'pages_access_level': 'enabled', 'operations_access_level': 'enabled', 'analytics_access_level': 'enabled', 'emails_disabled': None, 'shared_runners_enabled': True, 'lfs_enabled': True, 'creator_id': 4094213, 'import_status': 'none', 'open_issues_count': 0, 'ci_default_git_depth': 50, 'ci_forward_deployment_enabled': True, 'public_jobs': True, 'build_timeout': 3600, 'auto_cancel_pending_pipelines': 'enabled', 'build_coverage_regex': None, 'ci_config_path': '', 'shared_with_groups': [], 'only_allow_merge_if_pipeline_succeeds': False, 'allow_merge_on_skipped_pipeline': None, 'request_access_enabled': True, 'only_allow_merge_if_all_discussions_are_resolved': False, 'remove_source_branch_after_merge': True, 'printing_merge_request_link_enabled': True, 'merge_method': 'merge', 'suggestion_commit_message': None, 'auto_devops_enabled': False, 'auto_devops_deploy_strategy': 'continuous', 'autoclose_referenced_issues': True, 'approvals_before_merge': 0, 'mirror': False, 'external_authorization_classification_label': '', 'marked_for_deletion_at': None, 'marked_for_deletion_on': None, 'requirements_enabled': True, 'compliance_frameworks': []}
-----------------------
<class 'gitlab.v4.objects.GroupProject'> => {'id': 23052125, 'description': '', 'name': 'Sentiment Analysis of Indian Print Media News', 'name_with_namespace': 'datasets / Sentiment Analysis of Indian Print Media News', 'path': 'sentiment-analysis-of-indian-print-media-news', 'path_with_namespace': 'datasets_a/sentiment-analysis-of-indian-print-media-news', 'created_at': '2020-12-11T17:16:27.339Z', 'default_branch': 'master', 'tag_list': [], 'ssh_url_to_repo': '[email protected]:datasets_a/sentiment-analysis-of-indian-print-media-news.git', 'http_url_to_repo': 'https://gitlab.com/datasets_a/sentiment-analysis-of-indian-print-media-news.git', 'web_url': 'https://gitlab.com/datasets_a/sentiment-analysis-of-indian-print-media-news', 'readme_url': None, 'avatar_url': None, 'forks_count': 0, 'star_count': 0, 'last_activity_at': '2020-12-11T17:16:27.339Z', 'namespace': {'id': 9799560, 'name': 'datasets', 'path': 'datasets_a', 'kind': 'group', 'full_path': 'datasets_a', 'parent_id': None, 'avatar_url': None, 'web_url': 'https://gitlab.com/groups/datasets_a'}, '_links': {'self': 'https://gitlab.com/api/v4/projects/23052125', 'issues': 'https://gitlab.com/api/v4/projects/23052125/issues', 'merge_requests': 'https://gitlab.com/api/v4/projects/23052125/merge_requests', 'repo_branches': 'https://gitlab.com/api/v4/projects/23052125/repository/branches', 'labels': 'https://gitlab.com/api/v4/projects/23052125/labels', 'events': 'https://gitlab.com/api/v4/projects/23052125/events', 'members': 'https://gitlab.com/api/v4/projects/23052125/members'}, 'packages_enabled': True, 'empty_repo': False, 'archived': False, 'visibility': 'public', 'resolve_outdated_diff_discussions': False, 'container_registry_enabled': True, 'container_expiration_policy': {'cadence': '1d', 'enabled': False, 'keep_n': 10, 'older_than': '90d', 'name_regex': '.*', 'name_regex_keep': None, 'next_run_at': '2020-12-12T17:16:27.355Z'}, 'issues_enabled': True, 'merge_requests_enabled': True, 'wiki_enabled': True, 'jobs_enabled': True, 'snippets_enabled': True, 'service_desk_enabled': True, 'service_desk_address': 'incoming+datasets-a-sentiment-analysis-of-indian-print-media-news-23052125-issue-@incoming.gitlab.com', 'can_create_merge_request_in': False, 'issues_access_level': 'enabled', 'repository_access_level': 'enabled', 'merge_requests_access_level': 'enabled', 'forking_access_level': 'enabled', 'wiki_access_level': 'enabled', 'builds_access_level': 'enabled', 'snippets_access_level': 'enabled', 'pages_access_level': 'enabled', 'operations_access_level': 'enabled', 'analytics_access_level': 'enabled', 'emails_disabled': False, 'shared_runners_enabled': True, 'lfs_enabled': True, 'creator_id': 4094213, 'import_status': 'none', 'open_issues_count': 0, 'ci_default_git_depth': 50, 'ci_forward_deployment_enabled': True, 'public_jobs': True, 'build_timeout': 3600, 'auto_cancel_pending_pipelines': 'enabled', 'build_coverage_regex': None, 'ci_config_path': '', 'shared_with_groups': [], 'only_allow_merge_if_pipeline_succeeds': False, 'allow_merge_on_skipped_pipeline': None, 'request_access_enabled': True, 'only_allow_merge_if_all_discussions_are_resolved': False, 'remove_source_branch_after_merge': True, 'printing_merge_request_link_enabled': True, 'merge_method': 'merge', 'suggestion_commit_message': None, 'auto_devops_enabled': False, 'auto_devops_deploy_strategy': 'continuous', 'autoclose_referenced_issues': True, 'approvals_before_merge': 0, 'mirror': False, 'external_authorization_classification_label': '', 'marked_for_deletion_at': None, 'marked_for_deletion_on': None, 'requirements_enabled': True, 'compliance_frameworks': []}
-----------------------
<class 'gitlab.v4.objects.GroupProject'> => {'id': 22838171, 'description': '', 'name': 'MPG data', 'name_with_namespace': 'datasets / MPG data', 'path': 'mpg-data', 'path_with_namespace': 'datasets_a/mpg-data', 'created_at': '2020-12-02T11:42:59.430Z', 'default_branch': 'master', 'tag_list': [], 'ssh_url_to_repo': '[email protected]:datasets_a/mpg-data.git', 'http_url_to_repo': 'https://gitlab.com/datasets_a/mpg-data.git', 'web_url': 'https://gitlab.com/datasets_a/mpg-data', 'readme_url': None, 'avatar_url': None, 'forks_count': 0, 'star_count': 0, 'last_activity_at': '2020-12-02T13:14:44.828Z', 'namespace': {'id': 9799560, 'name': 'datasets', 'path': 'datasets_a', 'kind': 'group', 'full_path': 'datasets_a', 'parent_id': None, 'avatar_url': None, 'web_url': 'https://gitlab.com/groups/datasets_a'}, '_links': {'self': 'https://gitlab.com/api/v4/projects/22838171', 'issues': 'https://gitlab.com/api/v4/projects/22838171/issues', 'merge_requests': 'https://gitlab.com/api/v4/projects/22838171/merge_requests', 'repo_branches': 'https://gitlab.com/api/v4/projects/22838171/repository/branches', 'labels': 'https://gitlab.com/api/v4/projects/22838171/labels', 'events': 'https://gitlab.com/api/v4/projects/22838171/events', 'members': 'https://gitlab.com/api/v4/projects/22838171/members'}, 'packages_enabled': True, 'empty_repo': False, 'archived': False, 'visibility': 'public', 'resolve_outdated_diff_discussions': False, 'container_registry_enabled': True, 'container_expiration_policy': {'cadence': '1d', 'enabled': False, 'keep_n': 10, 'older_than': '90d', 'name_regex': '.*', 'name_regex_keep': None, 'next_run_at': '2020-12-03T11:42:59.473Z'}, 'issues_enabled': True, 'merge_requests_enabled': True, 'wiki_enabled': True, 'jobs_enabled': True, 'snippets_enabled': True, 'service_desk_enabled': True, 'service_desk_address': '[email protected]', 'can_create_merge_request_in': False, 'issues_access_level': 'enabled', 'repository_access_level': 'enabled', 'merge_requests_access_level': 'enabled', 'forking_access_level': 'enabled', 'wiki_access_level': 'enabled', 'builds_access_level': 'enabled', 'snippets_access_level': 'enabled', 'pages_access_level': 'enabled', 'operations_access_level': 'enabled', 'analytics_access_level': 'enabled', 'emails_disabled': False, 'shared_runners_enabled': True, 'lfs_enabled': True, 'creator_id': 4094213, 'import_status': 'none', 'open_issues_count': 0, 'ci_default_git_depth': 50, 'ci_forward_deployment_enabled': True, 'public_jobs': True, 'build_timeout': 3600, 'auto_cancel_pending_pipelines': 'enabled', 'build_coverage_regex': None, 'ci_config_path': '', 'shared_with_groups': [], 'only_allow_merge_if_pipeline_succeeds': False, 'allow_merge_on_skipped_pipeline': None, 'request_access_enabled': False, 'only_allow_merge_if_all_discussions_are_resolved': False, 'remove_source_branch_after_merge': True, 'printing_merge_request_link_enabled': True, 'merge_method': 'merge', 'suggestion_commit_message': None, 'auto_devops_enabled': False, 'auto_devops_deploy_strategy': 'continuous', 'autoclose_referenced_issues': True, 'approvals_before_merge': 0, 'mirror': False, 'external_authorization_classification_label': '', 'marked_for_deletion_at': None, 'marked_for_deletion_on': None, 'requirements_enabled': True, 'compliance_frameworks': []}
-----------------------
<class 'gitlab.v4.objects.GroupProject'> => {'id': 22473676, 'description': 'This dataset contains about 1006 equally distributed images of 2 distinct types.', 'name': 'COVID Face Mask Detection Dataset', 'name_with_namespace': 'datasets / COVID Face Mask Detection Dataset', 'path': 'covid-face-mask-detection-dataset', 'path_with_namespace': 'datasets_a/covid-face-mask-detection-dataset', 'created_at': '2020-11-16T06:02:17.171Z', 'default_branch': 'master', 'tag_list': [], 'ssh_url_to_repo': '[email protected]:datasets_a/covid-face-mask-detection-dataset.git', 'http_url_to_repo': 'https://gitlab.com/datasets_a/covid-face-mask-detection-dataset.git', 'web_url': 'https://gitlab.com/datasets_a/covid-face-mask-detection-dataset', 'readme_url': 'https://gitlab.com/datasets_a/covid-face-mask-detection-dataset/-/blob/master/README.md', 'avatar_url': None, 'forks_count': 0, 'star_count': 0, 'last_activity_at': '2020-11-16T06:02:17.171Z', 'namespace': {'id': 9799560, 'name': 'datasets', 'path': 'datasets_a', 'kind': 'group', 'full_path': 'datasets_a', 'parent_id': None, 'avatar_url': None, 'web_url': 'https://gitlab.com/groups/datasets_a'}, '_links': {'self': 'https://gitlab.com/api/v4/projects/22473676', 'issues': 'https://gitlab.com/api/v4/projects/22473676/issues', 'merge_requests': 'https://gitlab.com/api/v4/projects/22473676/merge_requests', 'repo_branches': 'https://gitlab.com/api/v4/projects/22473676/repository/branches', 'labels': 'https://gitlab.com/api/v4/projects/22473676/labels', 'events': 'https://gitlab.com/api/v4/projects/22473676/events', 'members': 'https://gitlab.com/api/v4/projects/22473676/members'}, 'packages_enabled': True, 'empty_repo': False, 'archived': False, 'visibility': 'public', 'resolve_outdated_diff_discussions': False, 'container_registry_enabled': True, 'container_expiration_policy': {'cadence': '1d', 'enabled': False, 'keep_n': 10, 'older_than': '90d', 'name_regex': '.*', 'name_regex_keep': None, 'next_run_at': '2020-11-17T06:02:17.200Z'}, 'issues_enabled': True, 'merge_requests_enabled': True, 'wiki_enabled': True, 'jobs_enabled': True, 'snippets_enabled': True, 'service_desk_enabled': True, 'service_desk_address': 'incoming+datasets-a-covid-face-mask-detection-dataset-22473676-issue-@incoming.gitlab.com', 'can_create_merge_request_in': False, 'issues_access_level': 'enabled', 'repository_access_level': 'enabled', 'merge_requests_access_level': 'enabled', 'forking_access_level': 'enabled', 'wiki_access_level': 'enabled', 'builds_access_level': 'enabled', 'snippets_access_level': 'enabled', 'pages_access_level': 'enabled', 'operations_access_level': 'enabled', 'analytics_access_level': 'enabled', 'emails_disabled': None, 'shared_runners_enabled': True, 'lfs_enabled': True, 'creator_id': 4094213, 'import_status': 'none', 'open_issues_count': 0, 'ci_default_git_depth': 50, 'ci_forward_deployment_enabled': True, 'public_jobs': True, 'build_timeout': 3600, 'auto_cancel_pending_pipelines': 'enabled', 'build_coverage_regex': None, 'ci_config_path': '', 'shared_with_groups': [], 'only_allow_merge_if_pipeline_succeeds': False, 'allow_merge_on_skipped_pipeline': None, 'request_access_enabled': True, 'only_allow_merge_if_all_discussions_are_resolved': False, 'remove_source_branch_after_merge': True, 'printing_merge_request_link_enabled': True, 'merge_method': 'merge', 'suggestion_commit_message': None, 'auto_devops_enabled': False, 'auto_devops_deploy_strategy': 'continuous', 'autoclose_referenced_issues': True, 'approvals_before_merge': 0, 'mirror': False, 'external_authorization_classification_label': '', 'marked_for_deletion_at': None, 'marked_for_deletion_on': None, 'requirements_enabled': True, 'compliance_frameworks': []}
-----------------------
<class 'gitlab.v4.objects.GroupProject'> => {'id': 21864811, 'description': '', 'name': 'Computer Vision in Python - Face Detection and Image Recognition', 'name_with_namespace': 'datasets / Computer Vision in Python - Face Detection and Image Recognition', 'path': 'computer-vision-in-python-face-detection-and-image-recognition', 'path_with_namespace': 'datasets_a/computer-vision-in-python-face-detection-and-image-recognition', 'created_at': '2020-10-19T04:57:30.429Z', 'default_branch': 'master', 'tag_list': [], 'ssh_url_to_repo': '[email protected]:datasets_a/computer-vision-in-python-face-detection-and-image-recognition.git', 'http_url_to_repo': 'https://gitlab.com/datasets_a/computer-vision-in-python-face-detection-and-image-recognition.git', 'web_url': 'https://gitlab.com/datasets_a/computer-vision-in-python-face-detection-and-image-recognition', 'readme_url': None, 'avatar_url': None, 'forks_count': 0, 'star_count': 0, 'last_activity_at': '2020-10-26T13:15:32.005Z', 'namespace': {'id': 9799560, 'name': 'datasets', 'path': 'datasets_a', 'kind': 'group', 'full_path': 'datasets_a', 'parent_id': None, 'avatar_url': None, 'web_url': 'https://gitlab.com/groups/datasets_a'}, '_links': {'self': 'https://gitlab.com/api/v4/projects/21864811', 'repo_branches': 'https://gitlab.com/api/v4/projects/21864811/repository/branches', 'labels': 'https://gitlab.com/api/v4/projects/21864811/labels', 'events': 'https://gitlab.com/api/v4/projects/21864811/events', 'members': 'https://gitlab.com/api/v4/projects/21864811/members'}, 'packages_enabled': False, 'empty_repo': False, 'archived': False, 'visibility': 'public', 'resolve_outdated_diff_discussions': False, 'container_registry_enabled': False, 'container_expiration_policy': {'cadence': '1d', 'enabled': True, 'keep_n': 10, 'older_than': '90d', 'name_regex': None, 'name_regex_keep': None, 'next_run_at': '2020-10-21T07:31:06.778Z'}, 'issues_enabled': False, 'merge_requests_enabled': None, 'wiki_enabled': False, 'jobs_enabled': None, 'snippets_enabled': False, 'service_desk_enabled': True, 'service_desk_address': 'incoming+datasets-a-computer-vision-in-python-face-detection-and-image-r-21864811-issue-@incoming.gitlab.com', 'can_create_merge_request_in': False, 'issues_access_level': 'disabled', 'repository_access_level': 'enabled', 'merge_requests_access_level': 'private', 'forking_access_level': 'private', 'wiki_access_level': 'disabled', 'builds_access_level': 'private', 'snippets_access_level': 'disabled', 'pages_access_level': 'disabled', 'operations_access_level': 'enabled', 'analytics_access_level': 'enabled', 'emails_disabled': False, 'shared_runners_enabled': True, 'lfs_enabled': True, 'creator_id': 4094213, 'import_status': 'none', 'ci_default_git_depth': 50, 'ci_forward_deployment_enabled': True, 'public_jobs': True, 'build_timeout': 3600, 'auto_cancel_pending_pipelines': 'enabled', 'build_coverage_regex': None, 'ci_config_path': '', 'shared_with_groups': [], 'only_allow_merge_if_pipeline_succeeds': False, 'allow_merge_on_skipped_pipeline': None, 'request_access_enabled': True, 'only_allow_merge_if_all_discussions_are_resolved': False, 'remove_source_branch_after_merge': True, 'printing_merge_request_link_enabled': True, 'merge_method': 'merge', 'suggestion_commit_message': None, 'auto_devops_enabled': False, 'auto_devops_deploy_strategy': 'continuous', 'autoclose_referenced_issues': True, 'approvals_before_merge': 0, 'mirror': False, 'external_authorization_classification_label': '', 'marked_for_deletion_at': None, 'marked_for_deletion_on': None, 'requirements_enabled': True, 'compliance_frameworks': []}


The above output displayed information about three projects in the group. The project we are interested is the first one with project id 22838171

In [10]:
project = gl.projects.get(22838171)


Let's view the items in the project.

In [11]:
items = project.repository_tree()
items
Out[11]:
[{'id': '2485ed68ee2388aab629c070c9b624b08b5bbd2f',
  'name': 'mpg.csv',
  'type': 'blob',
  'path': 'mpg.csv',
  'mode': '100644'}]


The project has only one item and it the mpg.csv file we are looking for. Projects usually have more than one items. We can retrieve file information using its file id.

In [12]:
file_info = project.repository_blob(items[0]['id'])
file_info
Out[12]:
{'size': 17345,
 'encoding': 'base64',
 'content': 'IiIsIm1hbnVmYWN0dXJlciIsIm1vZGVsIiwiZGlzcGwiLCJ5ZWFyIiwiY3lsIiwidHJhbnMiLCJkcnYiLCJjdHkiLCJod3kiLCJmbCIsImNsYXNzIgoiMSIsImF1ZGkiLCJhNCIsMS44LDE5OTksNCwiYXV0byhsNSkiLCJmIiwxOCwyOSwicCIsImNvbXBhY3QiCiIyIiwiYXVkaSIsImE0IiwxLjgsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMjEsMjksInAiLCJjb21wYWN0IgoiMyIsImF1ZGkiLCJhNCIsMiwyMDA4LDQsIm1hbnVhbChtNikiLCJmIiwyMCwzMSwicCIsImNvbXBhY3QiCiI0IiwiYXVkaSIsImE0IiwyLDIwMDgsNCwiYXV0byhhdikiLCJmIiwyMSwzMCwicCIsImNvbXBhY3QiCiI1IiwiYXVkaSIsImE0IiwyLjgsMTk5OSw2LCJhdXRvKGw1KSIsImYiLDE2LDI2LCJwIiwiY29tcGFjdCIKIjYiLCJhdWRpIiwiYTQiLDIuOCwxOTk5LDYsIm1hbnVhbChtNSkiLCJmIiwxOCwyNiwicCIsImNvbXBhY3QiCiI3IiwiYXVkaSIsImE0IiwzLjEsMjAwOCw2LCJhdXRvKGF2KSIsImYiLDE4LDI3LCJwIiwiY29tcGFjdCIKIjgiLCJhdWRpIiwiYTQgcXVhdHRybyIsMS44LDE5OTksNCwibWFudWFsKG01KSIsIjQiLDE4LDI2LCJwIiwiY29tcGFjdCIKIjkiLCJhdWRpIiwiYTQgcXVhdHRybyIsMS44LDE5OTksNCwiYXV0byhsNSkiLCI0IiwxNiwyNSwicCIsImNvbXBhY3QiCiIxMCIsImF1ZGkiLCJhNCBxdWF0dHJvIiwyLDIwMDgsNCwibWFudWFsKG02KSIsIjQiLDIwLDI4LCJwIiwiY29tcGFjdCIKIjExIiwiYXVkaSIsImE0IHF1YXR0cm8iLDIsMjAwOCw0LCJhdXRvKHM2KSIsIjQiLDE5LDI3LCJwIiwiY29tcGFjdCIKIjEyIiwiYXVkaSIsImE0IHF1YXR0cm8iLDIuOCwxOTk5LDYsImF1dG8obDUpIiwiNCIsMTUsMjUsInAiLCJjb21wYWN0IgoiMTMiLCJhdWRpIiwiYTQgcXVhdHRybyIsMi44LDE5OTksNiwibWFudWFsKG01KSIsIjQiLDE3LDI1LCJwIiwiY29tcGFjdCIKIjE0IiwiYXVkaSIsImE0IHF1YXR0cm8iLDMuMSwyMDA4LDYsImF1dG8oczYpIiwiNCIsMTcsMjUsInAiLCJjb21wYWN0IgoiMTUiLCJhdWRpIiwiYTQgcXVhdHRybyIsMy4xLDIwMDgsNiwibWFudWFsKG02KSIsIjQiLDE1LDI1LCJwIiwiY29tcGFjdCIKIjE2IiwiYXVkaSIsImE2IHF1YXR0cm8iLDIuOCwxOTk5LDYsImF1dG8obDUpIiwiNCIsMTUsMjQsInAiLCJtaWRzaXplIgoiMTciLCJhdWRpIiwiYTYgcXVhdHRybyIsMy4xLDIwMDgsNiwiYXV0byhzNikiLCI0IiwxNywyNSwicCIsIm1pZHNpemUiCiIxOCIsImF1ZGkiLCJhNiBxdWF0dHJvIiw0LjIsMjAwOCw4LCJhdXRvKHM2KSIsIjQiLDE2LDIzLCJwIiwibWlkc2l6ZSIKIjE5IiwiY2hldnJvbGV0IiwiYzE1MDAgc3VidXJiYW4gMndkIiw1LjMsMjAwOCw4LCJhdXRvKGw0KSIsInIiLDE0LDIwLCJyIiwic3V2IgoiMjAiLCJjaGV2cm9sZXQiLCJjMTUwMCBzdWJ1cmJhbiAyd2QiLDUuMywyMDA4LDgsImF1dG8obDQpIiwiciIsMTEsMTUsImUiLCJzdXYiCiIyMSIsImNoZXZyb2xldCIsImMxNTAwIHN1YnVyYmFuIDJ3ZCIsNS4zLDIwMDgsOCwiYXV0byhsNCkiLCJyIiwxNCwyMCwiciIsInN1diIKIjIyIiwiY2hldnJvbGV0IiwiYzE1MDAgc3VidXJiYW4gMndkIiw1LjcsMTk5OSw4LCJhdXRvKGw0KSIsInIiLDEzLDE3LCJyIiwic3V2IgoiMjMiLCJjaGV2cm9sZXQiLCJjMTUwMCBzdWJ1cmJhbiAyd2QiLDYsMjAwOCw4LCJhdXRvKGw0KSIsInIiLDEyLDE3LCJyIiwic3V2IgoiMjQiLCJjaGV2cm9sZXQiLCJjb3J2ZXR0ZSIsNS43LDE5OTksOCwibWFudWFsKG02KSIsInIiLDE2LDI2LCJwIiwiMnNlYXRlciIKIjI1IiwiY2hldnJvbGV0IiwiY29ydmV0dGUiLDUuNywxOTk5LDgsImF1dG8obDQpIiwiciIsMTUsMjMsInAiLCIyc2VhdGVyIgoiMjYiLCJjaGV2cm9sZXQiLCJjb3J2ZXR0ZSIsNi4yLDIwMDgsOCwibWFudWFsKG02KSIsInIiLDE2LDI2LCJwIiwiMnNlYXRlciIKIjI3IiwiY2hldnJvbGV0IiwiY29ydmV0dGUiLDYuMiwyMDA4LDgsImF1dG8oczYpIiwiciIsMTUsMjUsInAiLCIyc2VhdGVyIgoiMjgiLCJjaGV2cm9sZXQiLCJjb3J2ZXR0ZSIsNywyMDA4LDgsIm1hbnVhbChtNikiLCJyIiwxNSwyNCwicCIsIjJzZWF0ZXIiCiIyOSIsImNoZXZyb2xldCIsImsxNTAwIHRhaG9lIDR3ZCIsNS4zLDIwMDgsOCwiYXV0byhsNCkiLCI0IiwxNCwxOSwiciIsInN1diIKIjMwIiwiY2hldnJvbGV0IiwiazE1MDAgdGFob2UgNHdkIiw1LjMsMjAwOCw4LCJhdXRvKGw0KSIsIjQiLDExLDE0LCJlIiwic3V2IgoiMzEiLCJjaGV2cm9sZXQiLCJrMTUwMCB0YWhvZSA0d2QiLDUuNywxOTk5LDgsImF1dG8obDQpIiwiNCIsMTEsMTUsInIiLCJzdXYiCiIzMiIsImNoZXZyb2xldCIsImsxNTAwIHRhaG9lIDR3ZCIsNi41LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxNCwxNywiZCIsInN1diIKIjMzIiwiY2hldnJvbGV0IiwibWFsaWJ1IiwyLjQsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDE5LDI3LCJyIiwibWlkc2l6ZSIKIjM0IiwiY2hldnJvbGV0IiwibWFsaWJ1IiwyLjQsMjAwOCw0LCJhdXRvKGw0KSIsImYiLDIyLDMwLCJyIiwibWlkc2l6ZSIKIjM1IiwiY2hldnJvbGV0IiwibWFsaWJ1IiwzLjEsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE4LDI2LCJyIiwibWlkc2l6ZSIKIjM2IiwiY2hldnJvbGV0IiwibWFsaWJ1IiwzLjUsMjAwOCw2LCJhdXRvKGw0KSIsImYiLDE4LDI5LCJyIiwibWlkc2l6ZSIKIjM3IiwiY2hldnJvbGV0IiwibWFsaWJ1IiwzLjYsMjAwOCw2LCJhdXRvKHM2KSIsImYiLDE3LDI2LCJyIiwibWlkc2l6ZSIKIjM4IiwiZG9kZ2UiLCJjYXJhdmFuIDJ3ZCIsMi40LDE5OTksNCwiYXV0byhsMykiLCJmIiwxOCwyNCwiciIsIm1pbml2YW4iCiIzOSIsImRvZGdlIiwiY2FyYXZhbiAyd2QiLDMsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE3LDI0LCJyIiwibWluaXZhbiIKIjQwIiwiZG9kZ2UiLCJjYXJhdmFuIDJ3ZCIsMy4zLDE5OTksNiwiYXV0byhsNCkiLCJmIiwxNiwyMiwiciIsIm1pbml2YW4iCiI0MSIsImRvZGdlIiwiY2FyYXZhbiAyd2QiLDMuMywxOTk5LDYsImF1dG8obDQpIiwiZiIsMTYsMjIsInIiLCJtaW5pdmFuIgoiNDIiLCJkb2RnZSIsImNhcmF2YW4gMndkIiwzLjMsMjAwOCw2LCJhdXRvKGw0KSIsImYiLDE3LDI0LCJyIiwibWluaXZhbiIKIjQzIiwiZG9kZ2UiLCJjYXJhdmFuIDJ3ZCIsMy4zLDIwMDgsNiwiYXV0byhsNCkiLCJmIiwxNywyNCwiciIsIm1pbml2YW4iCiI0NCIsImRvZGdlIiwiY2FyYXZhbiAyd2QiLDMuMywyMDA4LDYsImF1dG8obDQpIiwiZiIsMTEsMTcsImUiLCJtaW5pdmFuIgoiNDUiLCJkb2RnZSIsImNhcmF2YW4gMndkIiwzLjgsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE1LDIyLCJyIiwibWluaXZhbiIKIjQ2IiwiZG9kZ2UiLCJjYXJhdmFuIDJ3ZCIsMy44LDE5OTksNiwiYXV0byhsNCkiLCJmIiwxNSwyMSwiciIsIm1pbml2YW4iCiI0NyIsImRvZGdlIiwiY2FyYXZhbiAyd2QiLDMuOCwyMDA4LDYsImF1dG8obDYpIiwiZiIsMTYsMjMsInIiLCJtaW5pdmFuIgoiNDgiLCJkb2RnZSIsImNhcmF2YW4gMndkIiw0LDIwMDgsNiwiYXV0byhsNikiLCJmIiwxNiwyMywiciIsIm1pbml2YW4iCiI0OSIsImRvZGdlIiwiZGFrb3RhIHBpY2t1cCA0d2QiLDMuNywyMDA4LDYsIm1hbnVhbChtNikiLCI0IiwxNSwxOSwiciIsInBpY2t1cCIKIjUwIiwiZG9kZ2UiLCJkYWtvdGEgcGlja3VwIDR3ZCIsMy43LDIwMDgsNiwiYXV0byhsNCkiLCI0IiwxNCwxOCwiciIsInBpY2t1cCIKIjUxIiwiZG9kZ2UiLCJkYWtvdGEgcGlja3VwIDR3ZCIsMy45LDE5OTksNiwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInBpY2t1cCIKIjUyIiwiZG9kZ2UiLCJkYWtvdGEgcGlja3VwIDR3ZCIsMy45LDE5OTksNiwibWFudWFsKG01KSIsIjQiLDE0LDE3LCJyIiwicGlja3VwIgoiNTMiLCJkb2RnZSIsImRha290YSBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDE0LDE5LCJyIiwicGlja3VwIgoiNTQiLCJkb2RnZSIsImRha290YSBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDE0LDE5LCJyIiwicGlja3VwIgoiNTUiLCJkb2RnZSIsImRha290YSBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDksMTIsImUiLCJwaWNrdXAiCiI1NiIsImRvZGdlIiwiZGFrb3RhIHBpY2t1cCA0d2QiLDUuMiwxOTk5LDgsIm1hbnVhbChtNSkiLCI0IiwxMSwxNywiciIsInBpY2t1cCIKIjU3IiwiZG9kZ2UiLCJkYWtvdGEgcGlja3VwIDR3ZCIsNS4yLDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMSwxNSwiciIsInBpY2t1cCIKIjU4IiwiZG9kZ2UiLCJkdXJhbmdvIDR3ZCIsMy45LDE5OTksNiwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInN1diIKIjU5IiwiZG9kZ2UiLCJkdXJhbmdvIDR3ZCIsNC43LDIwMDgsOCwiYXV0byhsNSkiLCI0IiwxMywxNywiciIsInN1diIKIjYwIiwiZG9kZ2UiLCJkdXJhbmdvIDR3ZCIsNC43LDIwMDgsOCwiYXV0byhsNSkiLCI0Iiw5LDEyLCJlIiwic3V2IgoiNjEiLCJkb2RnZSIsImR1cmFuZ28gNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDEzLDE3LCJyIiwic3V2IgoiNjIiLCJkb2RnZSIsImR1cmFuZ28gNHdkIiw1LjIsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE2LCJyIiwic3V2IgoiNjMiLCJkb2RnZSIsImR1cmFuZ28gNHdkIiw1LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDEzLDE4LCJyIiwic3V2IgoiNjQiLCJkb2RnZSIsImR1cmFuZ28gNHdkIiw1LjksMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE1LCJyIiwic3V2IgoiNjUiLCJkb2RnZSIsInJhbSAxNTAwIHBpY2t1cCA0d2QiLDQuNywyMDA4LDgsIm1hbnVhbChtNikiLCI0IiwxMiwxNiwiciIsInBpY2t1cCIKIjY2IiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDksMTIsImUiLCJwaWNrdXAiCiI2NyIsImRvZGdlIiwicmFtIDE1MDAgcGlja3VwIDR3ZCIsNC43LDIwMDgsOCwiYXV0byhsNSkiLCI0IiwxMywxNywiciIsInBpY2t1cCIKIjY4IiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDEzLDE3LCJyIiwicGlja3VwIgoiNjkiLCJkb2RnZSIsInJhbSAxNTAwIHBpY2t1cCA0d2QiLDQuNywyMDA4LDgsIm1hbnVhbChtNikiLCI0IiwxMiwxNiwiciIsInBpY2t1cCIKIjcwIiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJtYW51YWwobTYpIiwiNCIsOSwxMiwiZSIsInBpY2t1cCIKIjcxIiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw1LjIsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE1LCJyIiwicGlja3VwIgoiNzIiLCJkb2RnZSIsInJhbSAxNTAwIHBpY2t1cCA0d2QiLDUuMiwxOTk5LDgsIm1hbnVhbChtNSkiLCI0IiwxMSwxNiwiciIsInBpY2t1cCIKIjczIiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw1LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDEzLDE3LCJyIiwicGlja3VwIgoiNzQiLCJkb2RnZSIsInJhbSAxNTAwIHBpY2t1cCA0d2QiLDUuOSwxOTk5LDgsImF1dG8obDQpIiwiNCIsMTEsMTUsInIiLCJwaWNrdXAiCiI3NSIsImZvcmQiLCJleHBlZGl0aW9uIDJ3ZCIsNC42LDE5OTksOCwiYXV0byhsNCkiLCJyIiwxMSwxNywiciIsInN1diIKIjc2IiwiZm9yZCIsImV4cGVkaXRpb24gMndkIiw1LjQsMTk5OSw4LCJhdXRvKGw0KSIsInIiLDExLDE3LCJyIiwic3V2IgoiNzciLCJmb3JkIiwiZXhwZWRpdGlvbiAyd2QiLDUuNCwyMDA4LDgsImF1dG8obDYpIiwiciIsMTIsMTgsInIiLCJzdXYiCiI3OCIsImZvcmQiLCJleHBsb3JlciA0d2QiLDQsMTk5OSw2LCJhdXRvKGw1KSIsIjQiLDE0LDE3LCJyIiwic3V2IgoiNzkiLCJmb3JkIiwiZXhwbG9yZXIgNHdkIiw0LDE5OTksNiwibWFudWFsKG01KSIsIjQiLDE1LDE5LCJyIiwic3V2IgoiODAiLCJmb3JkIiwiZXhwbG9yZXIgNHdkIiw0LDE5OTksNiwiYXV0byhsNSkiLCI0IiwxNCwxNywiciIsInN1diIKIjgxIiwiZm9yZCIsImV4cGxvcmVyIDR3ZCIsNCwyMDA4LDYsImF1dG8obDUpIiwiNCIsMTMsMTksInIiLCJzdXYiCiI4MiIsImZvcmQiLCJleHBsb3JlciA0d2QiLDQuNiwyMDA4LDgsImF1dG8obDYpIiwiNCIsMTMsMTksInIiLCJzdXYiCiI4MyIsImZvcmQiLCJleHBsb3JlciA0d2QiLDUsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDEzLDE3LCJyIiwic3V2IgoiODQiLCJmb3JkIiwiZjE1MCBwaWNrdXAgNHdkIiw0LjIsMTk5OSw2LCJhdXRvKGw0KSIsIjQiLDE0LDE3LCJyIiwicGlja3VwIgoiODUiLCJmb3JkIiwiZjE1MCBwaWNrdXAgNHdkIiw0LjIsMTk5OSw2LCJtYW51YWwobTUpIiwiNCIsMTQsMTcsInIiLCJwaWNrdXAiCiI4NiIsImZvcmQiLCJmMTUwIHBpY2t1cCA0d2QiLDQuNiwxOTk5LDgsIm1hbnVhbChtNSkiLCI0IiwxMywxNiwiciIsInBpY2t1cCIKIjg3IiwiZm9yZCIsImYxNTAgcGlja3VwIDR3ZCIsNC42LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMywxNiwiciIsInBpY2t1cCIKIjg4IiwiZm9yZCIsImYxNTAgcGlja3VwIDR3ZCIsNC42LDIwMDgsOCwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInBpY2t1cCIKIjg5IiwiZm9yZCIsImYxNTAgcGlja3VwIDR3ZCIsNS40LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMSwxNSwiciIsInBpY2t1cCIKIjkwIiwiZm9yZCIsImYxNTAgcGlja3VwIDR3ZCIsNS40LDIwMDgsOCwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInBpY2t1cCIKIjkxIiwiZm9yZCIsIm11c3RhbmciLDMuOCwxOTk5LDYsIm1hbnVhbChtNSkiLCJyIiwxOCwyNiwiciIsInN1YmNvbXBhY3QiCiI5MiIsImZvcmQiLCJtdXN0YW5nIiwzLjgsMTk5OSw2LCJhdXRvKGw0KSIsInIiLDE4LDI1LCJyIiwic3ViY29tcGFjdCIKIjkzIiwiZm9yZCIsIm11c3RhbmciLDQsMjAwOCw2LCJtYW51YWwobTUpIiwiciIsMTcsMjYsInIiLCJzdWJjb21wYWN0IgoiOTQiLCJmb3JkIiwibXVzdGFuZyIsNCwyMDA4LDYsImF1dG8obDUpIiwiciIsMTYsMjQsInIiLCJzdWJjb21wYWN0IgoiOTUiLCJmb3JkIiwibXVzdGFuZyIsNC42LDE5OTksOCwiYXV0byhsNCkiLCJyIiwxNSwyMSwiciIsInN1YmNvbXBhY3QiCiI5NiIsImZvcmQiLCJtdXN0YW5nIiw0LjYsMTk5OSw4LCJtYW51YWwobTUpIiwiciIsMTUsMjIsInIiLCJzdWJjb21wYWN0IgoiOTciLCJmb3JkIiwibXVzdGFuZyIsNC42LDIwMDgsOCwibWFudWFsKG01KSIsInIiLDE1LDIzLCJyIiwic3ViY29tcGFjdCIKIjk4IiwiZm9yZCIsIm11c3RhbmciLDQuNiwyMDA4LDgsImF1dG8obDUpIiwiciIsMTUsMjIsInIiLCJzdWJjb21wYWN0IgoiOTkiLCJmb3JkIiwibXVzdGFuZyIsNS40LDIwMDgsOCwibWFudWFsKG02KSIsInIiLDE0LDIwLCJwIiwic3ViY29tcGFjdCIKIjEwMCIsImhvbmRhIiwiY2l2aWMiLDEuNiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyOCwzMywiciIsInN1YmNvbXBhY3QiCiIxMDEiLCJob25kYSIsImNpdmljIiwxLjYsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDI0LDMyLCJyIiwic3ViY29tcGFjdCIKIjEwMiIsImhvbmRhIiwiY2l2aWMiLDEuNiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyNSwzMiwiciIsInN1YmNvbXBhY3QiCiIxMDMiLCJob25kYSIsImNpdmljIiwxLjYsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMjMsMjksInAiLCJzdWJjb21wYWN0IgoiMTA0IiwiaG9uZGEiLCJjaXZpYyIsMS42LDE5OTksNCwiYXV0byhsNCkiLCJmIiwyNCwzMiwiciIsInN1YmNvbXBhY3QiCiIxMDUiLCJob25kYSIsImNpdmljIiwxLjgsMjAwOCw0LCJtYW51YWwobTUpIiwiZiIsMjYsMzQsInIiLCJzdWJjb21wYWN0IgoiMTA2IiwiaG9uZGEiLCJjaXZpYyIsMS44LDIwMDgsNCwiYXV0byhsNSkiLCJmIiwyNSwzNiwiciIsInN1YmNvbXBhY3QiCiIxMDciLCJob25kYSIsImNpdmljIiwxLjgsMjAwOCw0LCJhdXRvKGw1KSIsImYiLDI0LDM2LCJjIiwic3ViY29tcGFjdCIKIjEwOCIsImhvbmRhIiwiY2l2aWMiLDIsMjAwOCw0LCJtYW51YWwobTYpIiwiZiIsMjEsMjksInAiLCJzdWJjb21wYWN0IgoiMTA5IiwiaHl1bmRhaSIsInNvbmF0YSIsMi40LDE5OTksNCwiYXV0byhsNCkiLCJmIiwxOCwyNiwiciIsIm1pZHNpemUiCiIxMTAiLCJoeXVuZGFpIiwic29uYXRhIiwyLjQsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMTgsMjcsInIiLCJtaWRzaXplIgoiMTExIiwiaHl1bmRhaSIsInNvbmF0YSIsMi40LDIwMDgsNCwiYXV0byhsNCkiLCJmIiwyMSwzMCwiciIsIm1pZHNpemUiCiIxMTIiLCJoeXVuZGFpIiwic29uYXRhIiwyLjQsMjAwOCw0LCJtYW51YWwobTUpIiwiZiIsMjEsMzEsInIiLCJtaWRzaXplIgoiMTEzIiwiaHl1bmRhaSIsInNvbmF0YSIsMi41LDE5OTksNiwiYXV0byhsNCkiLCJmIiwxOCwyNiwiciIsIm1pZHNpemUiCiIxMTQiLCJoeXVuZGFpIiwic29uYXRhIiwyLjUsMTk5OSw2LCJtYW51YWwobTUpIiwiZiIsMTgsMjYsInIiLCJtaWRzaXplIgoiMTE1IiwiaHl1bmRhaSIsInNvbmF0YSIsMy4zLDIwMDgsNiwiYXV0byhsNSkiLCJmIiwxOSwyOCwiciIsIm1pZHNpemUiCiIxMTYiLCJoeXVuZGFpIiwidGlidXJvbiIsMiwxOTk5LDQsImF1dG8obDQpIiwiZiIsMTksMjYsInIiLCJzdWJjb21wYWN0IgoiMTE3IiwiaHl1bmRhaSIsInRpYnVyb24iLDIsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMTksMjksInIiLCJzdWJjb21wYWN0IgoiMTE4IiwiaHl1bmRhaSIsInRpYnVyb24iLDIsMjAwOCw0LCJtYW51YWwobTUpIiwiZiIsMjAsMjgsInIiLCJzdWJjb21wYWN0IgoiMTE5IiwiaHl1bmRhaSIsInRpYnVyb24iLDIsMjAwOCw0LCJhdXRvKGw0KSIsImYiLDIwLDI3LCJyIiwic3ViY29tcGFjdCIKIjEyMCIsImh5dW5kYWkiLCJ0aWJ1cm9uIiwyLjcsMjAwOCw2LCJhdXRvKGw0KSIsImYiLDE3LDI0LCJyIiwic3ViY29tcGFjdCIKIjEyMSIsImh5dW5kYWkiLCJ0aWJ1cm9uIiwyLjcsMjAwOCw2LCJtYW51YWwobTYpIiwiZiIsMTYsMjQsInIiLCJzdWJjb21wYWN0IgoiMTIyIiwiaHl1bmRhaSIsInRpYnVyb24iLDIuNywyMDA4LDYsIm1hbnVhbChtNSkiLCJmIiwxNywyNCwiciIsInN1YmNvbXBhY3QiCiIxMjMiLCJqZWVwIiwiZ3JhbmQgY2hlcm9rZWUgNHdkIiwzLDIwMDgsNiwiYXV0byhsNSkiLCI0IiwxNywyMiwiZCIsInN1diIKIjEyNCIsImplZXAiLCJncmFuZCBjaGVyb2tlZSA0d2QiLDMuNywyMDA4LDYsImF1dG8obDUpIiwiNCIsMTUsMTksInIiLCJzdXYiCiIxMjUiLCJqZWVwIiwiZ3JhbmQgY2hlcm9rZWUgNHdkIiw0LDE5OTksNiwiYXV0byhsNCkiLCI0IiwxNSwyMCwiciIsInN1diIKIjEyNiIsImplZXAiLCJncmFuZCBjaGVyb2tlZSA0d2QiLDQuNywxOTk5LDgsImF1dG8obDQpIiwiNCIsMTQsMTcsInIiLCJzdXYiCiIxMjciLCJqZWVwIiwiZ3JhbmQgY2hlcm9rZWUgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDksMTIsImUiLCJzdXYiCiIxMjgiLCJqZWVwIiwiZ3JhbmQgY2hlcm9rZWUgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDE0LDE5LCJyIiwic3V2IgoiMTI5IiwiamVlcCIsImdyYW5kIGNoZXJva2VlIDR3ZCIsNS43LDIwMDgsOCwiYXV0byhsNSkiLCI0IiwxMywxOCwiciIsInN1diIKIjEzMCIsImplZXAiLCJncmFuZCBjaGVyb2tlZSA0d2QiLDYuMSwyMDA4LDgsImF1dG8obDUpIiwiNCIsMTEsMTQsInAiLCJzdXYiCiIxMzEiLCJsYW5kIHJvdmVyIiwicmFuZ2Ugcm92ZXIiLDQsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE1LCJwIiwic3V2IgoiMTMyIiwibGFuZCByb3ZlciIsInJhbmdlIHJvdmVyIiw0LjIsMjAwOCw4LCJhdXRvKHM2KSIsIjQiLDEyLDE4LCJyIiwic3V2IgoiMTMzIiwibGFuZCByb3ZlciIsInJhbmdlIHJvdmVyIiw0LjQsMjAwOCw4LCJhdXRvKHM2KSIsIjQiLDEyLDE4LCJyIiwic3V2IgoiMTM0IiwibGFuZCByb3ZlciIsInJhbmdlIHJvdmVyIiw0LjYsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE1LCJwIiwic3V2IgoiMTM1IiwibGluY29sbiIsIm5hdmlnYXRvciAyd2QiLDUuNCwxOTk5LDgsImF1dG8obDQpIiwiciIsMTEsMTcsInIiLCJzdXYiCiIxMzYiLCJsaW5jb2xuIiwibmF2aWdhdG9yIDJ3ZCIsNS40LDE5OTksOCwiYXV0byhsNCkiLCJyIiwxMSwxNiwicCIsInN1diIKIjEzNyIsImxpbmNvbG4iLCJuYXZpZ2F0b3IgMndkIiw1LjQsMjAwOCw4LCJhdXRvKGw2KSIsInIiLDEyLDE4LCJyIiwic3V2IgoiMTM4IiwibWVyY3VyeSIsIm1vdW50YWluZWVyIDR3ZCIsNCwxOTk5LDYsImF1dG8obDUpIiwiNCIsMTQsMTcsInIiLCJzdXYiCiIxMzkiLCJtZXJjdXJ5IiwibW91bnRhaW5lZXIgNHdkIiw0LDIwMDgsNiwiYXV0byhsNSkiLCI0IiwxMywxOSwiciIsInN1diIKIjE0MCIsIm1lcmN1cnkiLCJtb3VudGFpbmVlciA0d2QiLDQuNiwyMDA4LDgsImF1dG8obDYpIiwiNCIsMTMsMTksInIiLCJzdXYiCiIxNDEiLCJtZXJjdXJ5IiwibW91bnRhaW5lZXIgNHdkIiw1LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInN1diIKIjE0MiIsIm5pc3NhbiIsImFsdGltYSIsMi40LDE5OTksNCwibWFudWFsKG01KSIsImYiLDIxLDI5LCJyIiwiY29tcGFjdCIKIjE0MyIsIm5pc3NhbiIsImFsdGltYSIsMi40LDE5OTksNCwiYXV0byhsNCkiLCJmIiwxOSwyNywiciIsImNvbXBhY3QiCiIxNDQiLCJuaXNzYW4iLCJhbHRpbWEiLDIuNSwyMDA4LDQsImF1dG8oYXYpIiwiZiIsMjMsMzEsInIiLCJtaWRzaXplIgoiMTQ1Iiwibmlzc2FuIiwiYWx0aW1hIiwyLjUsMjAwOCw0LCJtYW51YWwobTYpIiwiZiIsMjMsMzIsInIiLCJtaWRzaXplIgoiMTQ2Iiwibmlzc2FuIiwiYWx0aW1hIiwzLjUsMjAwOCw2LCJtYW51YWwobTYpIiwiZiIsMTksMjcsInAiLCJtaWRzaXplIgoiMTQ3Iiwibmlzc2FuIiwiYWx0aW1hIiwzLjUsMjAwOCw2LCJhdXRvKGF2KSIsImYiLDE5LDI2LCJwIiwibWlkc2l6ZSIKIjE0OCIsIm5pc3NhbiIsIm1heGltYSIsMywxOTk5LDYsImF1dG8obDQpIiwiZiIsMTgsMjYsInIiLCJtaWRzaXplIgoiMTQ5Iiwibmlzc2FuIiwibWF4aW1hIiwzLDE5OTksNiwibWFudWFsKG01KSIsImYiLDE5LDI1LCJyIiwibWlkc2l6ZSIKIjE1MCIsIm5pc3NhbiIsIm1heGltYSIsMy41LDIwMDgsNiwiYXV0byhhdikiLCJmIiwxOSwyNSwicCIsIm1pZHNpemUiCiIxNTEiLCJuaXNzYW4iLCJwYXRoZmluZGVyIDR3ZCIsMy4zLDE5OTksNiwiYXV0byhsNCkiLCI0IiwxNCwxNywiciIsInN1diIKIjE1MiIsIm5pc3NhbiIsInBhdGhmaW5kZXIgNHdkIiwzLjMsMTk5OSw2LCJtYW51YWwobTUpIiwiNCIsMTUsMTcsInIiLCJzdXYiCiIxNTMiLCJuaXNzYW4iLCJwYXRoZmluZGVyIDR3ZCIsNCwyMDA4LDYsImF1dG8obDUpIiwiNCIsMTQsMjAsInAiLCJzdXYiCiIxNTQiLCJuaXNzYW4iLCJwYXRoZmluZGVyIDR3ZCIsNS42LDIwMDgsOCwiYXV0byhzNSkiLCI0IiwxMiwxOCwicCIsInN1diIKIjE1NSIsInBvbnRpYWMiLCJncmFuZCBwcml4IiwzLjEsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE4LDI2LCJyIiwibWlkc2l6ZSIKIjE1NiIsInBvbnRpYWMiLCJncmFuZCBwcml4IiwzLjgsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE2LDI2LCJwIiwibWlkc2l6ZSIKIjE1NyIsInBvbnRpYWMiLCJncmFuZCBwcml4IiwzLjgsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE3LDI3LCJyIiwibWlkc2l6ZSIKIjE1OCIsInBvbnRpYWMiLCJncmFuZCBwcml4IiwzLjgsMjAwOCw2LCJhdXRvKGw0KSIsImYiLDE4LDI4LCJyIiwibWlkc2l6ZSIKIjE1OSIsInBvbnRpYWMiLCJncmFuZCBwcml4Iiw1LjMsMjAwOCw4LCJhdXRvKHM0KSIsImYiLDE2LDI1LCJwIiwibWlkc2l6ZSIKIjE2MCIsInN1YmFydSIsImZvcmVzdGVyIGF3ZCIsMi41LDE5OTksNCwibWFudWFsKG01KSIsIjQiLDE4LDI1LCJyIiwic3V2IgoiMTYxIiwic3ViYXJ1IiwiZm9yZXN0ZXIgYXdkIiwyLjUsMTk5OSw0LCJhdXRvKGw0KSIsIjQiLDE4LDI0LCJyIiwic3V2IgoiMTYyIiwic3ViYXJ1IiwiZm9yZXN0ZXIgYXdkIiwyLjUsMjAwOCw0LCJtYW51YWwobTUpIiwiNCIsMjAsMjcsInIiLCJzdXYiCiIxNjMiLCJzdWJhcnUiLCJmb3Jlc3RlciBhd2QiLDIuNSwyMDA4LDQsIm1hbnVhbChtNSkiLCI0IiwxOSwyNSwicCIsInN1diIKIjE2NCIsInN1YmFydSIsImZvcmVzdGVyIGF3ZCIsMi41LDIwMDgsNCwiYXV0byhsNCkiLCI0IiwyMCwyNiwiciIsInN1diIKIjE2NSIsInN1YmFydSIsImZvcmVzdGVyIGF3ZCIsMi41LDIwMDgsNCwiYXV0byhsNCkiLCI0IiwxOCwyMywicCIsInN1diIKIjE2NiIsInN1YmFydSIsImltcHJlemEgYXdkIiwyLjIsMTk5OSw0LCJhdXRvKGw0KSIsIjQiLDIxLDI2LCJyIiwic3ViY29tcGFjdCIKIjE2NyIsInN1YmFydSIsImltcHJlemEgYXdkIiwyLjIsMTk5OSw0LCJtYW51YWwobTUpIiwiNCIsMTksMjYsInIiLCJzdWJjb21wYWN0IgoiMTY4Iiwic3ViYXJ1IiwiaW1wcmV6YSBhd2QiLDIuNSwxOTk5LDQsIm1hbnVhbChtNSkiLCI0IiwxOSwyNiwiciIsInN1YmNvbXBhY3QiCiIxNjkiLCJzdWJhcnUiLCJpbXByZXphIGF3ZCIsMi41LDE5OTksNCwiYXV0byhsNCkiLCI0IiwxOSwyNiwiciIsInN1YmNvbXBhY3QiCiIxNzAiLCJzdWJhcnUiLCJpbXByZXphIGF3ZCIsMi41LDIwMDgsNCwiYXV0byhzNCkiLCI0IiwyMCwyNSwicCIsImNvbXBhY3QiCiIxNzEiLCJzdWJhcnUiLCJpbXByZXphIGF3ZCIsMi41LDIwMDgsNCwiYXV0byhzNCkiLCI0IiwyMCwyNywiciIsImNvbXBhY3QiCiIxNzIiLCJzdWJhcnUiLCJpbXByZXphIGF3ZCIsMi41LDIwMDgsNCwibWFudWFsKG01KSIsIjQiLDE5LDI1LCJwIiwiY29tcGFjdCIKIjE3MyIsInN1YmFydSIsImltcHJlemEgYXdkIiwyLjUsMjAwOCw0LCJtYW51YWwobTUpIiwiNCIsMjAsMjcsInIiLCJjb21wYWN0IgoiMTc0IiwidG95b3RhIiwiNHJ1bm5lciA0d2QiLDIuNywxOTk5LDQsIm1hbnVhbChtNSkiLCI0IiwxNSwyMCwiciIsInN1diIKIjE3NSIsInRveW90YSIsIjRydW5uZXIgNHdkIiwyLjcsMTk5OSw0LCJhdXRvKGw0KSIsIjQiLDE2LDIwLCJyIiwic3V2IgoiMTc2IiwidG95b3RhIiwiNHJ1bm5lciA0d2QiLDMuNCwxOTk5LDYsImF1dG8obDQpIiwiNCIsMTUsMTksInIiLCJzdXYiCiIxNzciLCJ0b3lvdGEiLCI0cnVubmVyIDR3ZCIsMy40LDE5OTksNiwibWFudWFsKG01KSIsIjQiLDE1LDE3LCJyIiwic3V2IgoiMTc4IiwidG95b3RhIiwiNHJ1bm5lciA0d2QiLDQsMjAwOCw2LCJhdXRvKGw1KSIsIjQiLDE2LDIwLCJyIiwic3V2IgoiMTc5IiwidG95b3RhIiwiNHJ1bm5lciA0d2QiLDQuNywyMDA4LDgsImF1dG8obDUpIiwiNCIsMTQsMTcsInIiLCJzdXYiCiIxODAiLCJ0b3lvdGEiLCJjYW1yeSIsMi4yLDE5OTksNCwibWFudWFsKG01KSIsImYiLDIxLDI5LCJyIiwibWlkc2l6ZSIKIjE4MSIsInRveW90YSIsImNhbXJ5IiwyLjIsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDIxLDI3LCJyIiwibWlkc2l6ZSIKIjE4MiIsInRveW90YSIsImNhbXJ5IiwyLjQsMjAwOCw0LCJtYW51YWwobTUpIiwiZiIsMjEsMzEsInIiLCJtaWRzaXplIgoiMTgzIiwidG95b3RhIiwiY2FtcnkiLDIuNCwyMDA4LDQsImF1dG8obDUpIiwiZiIsMjEsMzEsInIiLCJtaWRzaXplIgoiMTg0IiwidG95b3RhIiwiY2FtcnkiLDMsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE4LDI2LCJyIiwibWlkc2l6ZSIKIjE4NSIsInRveW90YSIsImNhbXJ5IiwzLDE5OTksNiwibWFudWFsKG01KSIsImYiLDE4LDI2LCJyIiwibWlkc2l6ZSIKIjE4NiIsInRveW90YSIsImNhbXJ5IiwzLjUsMjAwOCw2LCJhdXRvKHM2KSIsImYiLDE5LDI4LCJyIiwibWlkc2l6ZSIKIjE4NyIsInRveW90YSIsImNhbXJ5IHNvbGFyYSIsMi4yLDE5OTksNCwiYXV0byhsNCkiLCJmIiwyMSwyNywiciIsImNvbXBhY3QiCiIxODgiLCJ0b3lvdGEiLCJjYW1yeSBzb2xhcmEiLDIuMiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyMSwyOSwiciIsImNvbXBhY3QiCiIxODkiLCJ0b3lvdGEiLCJjYW1yeSBzb2xhcmEiLDIuNCwyMDA4LDQsIm1hbnVhbChtNSkiLCJmIiwyMSwzMSwiciIsImNvbXBhY3QiCiIxOTAiLCJ0b3lvdGEiLCJjYW1yeSBzb2xhcmEiLDIuNCwyMDA4LDQsImF1dG8oczUpIiwiZiIsMjIsMzEsInIiLCJjb21wYWN0IgoiMTkxIiwidG95b3RhIiwiY2Ftcnkgc29sYXJhIiwzLDE5OTksNiwiYXV0byhsNCkiLCJmIiwxOCwyNiwiciIsImNvbXBhY3QiCiIxOTIiLCJ0b3lvdGEiLCJjYW1yeSBzb2xhcmEiLDMsMTk5OSw2LCJtYW51YWwobTUpIiwiZiIsMTgsMjYsInIiLCJjb21wYWN0IgoiMTkzIiwidG95b3RhIiwiY2Ftcnkgc29sYXJhIiwzLjMsMjAwOCw2LCJhdXRvKHM1KSIsImYiLDE4LDI3LCJyIiwiY29tcGFjdCIKIjE5NCIsInRveW90YSIsImNvcm9sbGEiLDEuOCwxOTk5LDQsImF1dG8obDMpIiwiZiIsMjQsMzAsInIiLCJjb21wYWN0IgoiMTk1IiwidG95b3RhIiwiY29yb2xsYSIsMS44LDE5OTksNCwiYXV0byhsNCkiLCJmIiwyNCwzMywiciIsImNvbXBhY3QiCiIxOTYiLCJ0b3lvdGEiLCJjb3JvbGxhIiwxLjgsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMjYsMzUsInIiLCJjb21wYWN0IgoiMTk3IiwidG95b3RhIiwiY29yb2xsYSIsMS44LDIwMDgsNCwibWFudWFsKG01KSIsImYiLDI4LDM3LCJyIiwiY29tcGFjdCIKIjE5OCIsInRveW90YSIsImNvcm9sbGEiLDEuOCwyMDA4LDQsImF1dG8obDQpIiwiZiIsMjYsMzUsInIiLCJjb21wYWN0IgoiMTk5IiwidG95b3RhIiwibGFuZCBjcnVpc2VyIHdhZ29uIDR3ZCIsNC43LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMSwxNSwiciIsInN1diIKIjIwMCIsInRveW90YSIsImxhbmQgY3J1aXNlciB3YWdvbiA0d2QiLDUuNywyMDA4LDgsImF1dG8oczYpIiwiNCIsMTMsMTgsInIiLCJzdXYiCiIyMDEiLCJ0b3lvdGEiLCJ0b3lvdGEgdGFjb21hIDR3ZCIsMi43LDE5OTksNCwibWFudWFsKG01KSIsIjQiLDE1LDIwLCJyIiwicGlja3VwIgoiMjAyIiwidG95b3RhIiwidG95b3RhIHRhY29tYSA0d2QiLDIuNywxOTk5LDQsImF1dG8obDQpIiwiNCIsMTYsMjAsInIiLCJwaWNrdXAiCiIyMDMiLCJ0b3lvdGEiLCJ0b3lvdGEgdGFjb21hIDR3ZCIsMi43LDIwMDgsNCwibWFudWFsKG01KSIsIjQiLDE3LDIyLCJyIiwicGlja3VwIgoiMjA0IiwidG95b3RhIiwidG95b3RhIHRhY29tYSA0d2QiLDMuNCwxOTk5LDYsIm1hbnVhbChtNSkiLCI0IiwxNSwxNywiciIsInBpY2t1cCIKIjIwNSIsInRveW90YSIsInRveW90YSB0YWNvbWEgNHdkIiwzLjQsMTk5OSw2LCJhdXRvKGw0KSIsIjQiLDE1LDE5LCJyIiwicGlja3VwIgoiMjA2IiwidG95b3RhIiwidG95b3RhIHRhY29tYSA0d2QiLDQsMjAwOCw2LCJtYW51YWwobTYpIiwiNCIsMTUsMTgsInIiLCJwaWNrdXAiCiIyMDciLCJ0b3lvdGEiLCJ0b3lvdGEgdGFjb21hIDR3ZCIsNCwyMDA4LDYsImF1dG8obDUpIiwiNCIsMTYsMjAsInIiLCJwaWNrdXAiCiIyMDgiLCJ2b2xrc3dhZ2VuIiwiZ3RpIiwyLDE5OTksNCwibWFudWFsKG01KSIsImYiLDIxLDI5LCJyIiwiY29tcGFjdCIKIjIwOSIsInZvbGtzd2FnZW4iLCJndGkiLDIsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDE5LDI2LCJyIiwiY29tcGFjdCIKIjIxMCIsInZvbGtzd2FnZW4iLCJndGkiLDIsMjAwOCw0LCJtYW51YWwobTYpIiwiZiIsMjEsMjksInAiLCJjb21wYWN0IgoiMjExIiwidm9sa3N3YWdlbiIsImd0aSIsMiwyMDA4LDQsImF1dG8oczYpIiwiZiIsMjIsMjksInAiLCJjb21wYWN0IgoiMjEyIiwidm9sa3N3YWdlbiIsImd0aSIsMi44LDE5OTksNiwibWFudWFsKG01KSIsImYiLDE3LDI0LCJyIiwiY29tcGFjdCIKIjIxMyIsInZvbGtzd2FnZW4iLCJqZXR0YSIsMS45LDE5OTksNCwibWFudWFsKG01KSIsImYiLDMzLDQ0LCJkIiwiY29tcGFjdCIKIjIxNCIsInZvbGtzd2FnZW4iLCJqZXR0YSIsMiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyMSwyOSwiciIsImNvbXBhY3QiCiIyMTUiLCJ2b2xrc3dhZ2VuIiwiamV0dGEiLDIsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDE5LDI2LCJyIiwiY29tcGFjdCIKIjIxNiIsInZvbGtzd2FnZW4iLCJqZXR0YSIsMiwyMDA4LDQsImF1dG8oczYpIiwiZiIsMjIsMjksInAiLCJjb21wYWN0IgoiMjE3Iiwidm9sa3N3YWdlbiIsImpldHRhIiwyLDIwMDgsNCwibWFudWFsKG02KSIsImYiLDIxLDI5LCJwIiwiY29tcGFjdCIKIjIxOCIsInZvbGtzd2FnZW4iLCJqZXR0YSIsMi41LDIwMDgsNSwiYXV0byhzNikiLCJmIiwyMSwyOSwiciIsImNvbXBhY3QiCiIyMTkiLCJ2b2xrc3dhZ2VuIiwiamV0dGEiLDIuNSwyMDA4LDUsIm1hbnVhbChtNSkiLCJmIiwyMSwyOSwiciIsImNvbXBhY3QiCiIyMjAiLCJ2b2xrc3dhZ2VuIiwiamV0dGEiLDIuOCwxOTk5LDYsImF1dG8obDQpIiwiZiIsMTYsMjMsInIiLCJjb21wYWN0IgoiMjIxIiwidm9sa3N3YWdlbiIsImpldHRhIiwyLjgsMTk5OSw2LCJtYW51YWwobTUpIiwiZiIsMTcsMjQsInIiLCJjb21wYWN0IgoiMjIyIiwidm9sa3N3YWdlbiIsIm5ldyBiZWV0bGUiLDEuOSwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwzNSw0NCwiZCIsInN1YmNvbXBhY3QiCiIyMjMiLCJ2b2xrc3dhZ2VuIiwibmV3IGJlZXRsZSIsMS45LDE5OTksNCwiYXV0byhsNCkiLCJmIiwyOSw0MSwiZCIsInN1YmNvbXBhY3QiCiIyMjQiLCJ2b2xrc3dhZ2VuIiwibmV3IGJlZXRsZSIsMiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyMSwyOSwiciIsInN1YmNvbXBhY3QiCiIyMjUiLCJ2b2xrc3dhZ2VuIiwibmV3IGJlZXRsZSIsMiwxOTk5LDQsImF1dG8obDQpIiwiZiIsMTksMjYsInIiLCJzdWJjb21wYWN0IgoiMjI2Iiwidm9sa3N3YWdlbiIsIm5ldyBiZWV0bGUiLDIuNSwyMDA4LDUsIm1hbnVhbChtNSkiLCJmIiwyMCwyOCwiciIsInN1YmNvbXBhY3QiCiIyMjciLCJ2b2xrc3dhZ2VuIiwibmV3IGJlZXRsZSIsMi41LDIwMDgsNSwiYXV0byhzNikiLCJmIiwyMCwyOSwiciIsInN1YmNvbXBhY3QiCiIyMjgiLCJ2b2xrc3dhZ2VuIiwicGFzc2F0IiwxLjgsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMjEsMjksInAiLCJtaWRzaXplIgoiMjI5Iiwidm9sa3N3YWdlbiIsInBhc3NhdCIsMS44LDE5OTksNCwiYXV0byhsNSkiLCJmIiwxOCwyOSwicCIsIm1pZHNpemUiCiIyMzAiLCJ2b2xrc3dhZ2VuIiwicGFzc2F0IiwyLDIwMDgsNCwiYXV0byhzNikiLCJmIiwxOSwyOCwicCIsIm1pZHNpemUiCiIyMzEiLCJ2b2xrc3dhZ2VuIiwicGFzc2F0IiwyLDIwMDgsNCwibWFudWFsKG02KSIsImYiLDIxLDI5LCJwIiwibWlkc2l6ZSIKIjIzMiIsInZvbGtzd2FnZW4iLCJwYXNzYXQiLDIuOCwxOTk5LDYsImF1dG8obDUpIiwiZiIsMTYsMjYsInAiLCJtaWRzaXplIgoiMjMzIiwidm9sa3N3YWdlbiIsInBhc3NhdCIsMi44LDE5OTksNiwibWFudWFsKG01KSIsImYiLDE4LDI2LCJwIiwibWlkc2l6ZSIKIjIzNCIsInZvbGtzd2FnZW4iLCJwYXNzYXQiLDMuNiwyMDA4LDYsImF1dG8oczYpIiwiZiIsMTcsMjYsInAiLCJtaWRzaXplIgo=',
 'sha': '2485ed68ee2388aab629c070c9b624b08b5bbd2f'}


We notice that the file is encoded and is of no use to us as it is unless we decode it. The encoding used in GitLab by default is base64 as also mentioned in the file information above. base64 is already a built-in package in Python.

In [13]:
import base64
# Decoding using base64
content = base64.b64decode(file_info['content'])
content
Out[13]:
b'"","manufacturer","model","displ","year","cyl","trans","drv","cty","hwy","fl","class"\n"1","audi","a4",1.8,1999,4,"auto(l5)","f",18,29,"p","compact"\n"2","audi","a4",1.8,1999,4,"manual(m5)","f",21,29,"p","compact"\n"3","audi","a4",2,2008,4,"manual(m6)","f",20,31,"p","compact"\n"4","audi","a4",2,2008,4,"auto(av)","f",21,30,"p","compact"\n"5","audi","a4",2.8,1999,6,"auto(l5)","f",16,26,"p","compact"\n"6","audi","a4",2.8,1999,6,"manual(m5)","f",18,26,"p","compact"\n"7","audi","a4",3.1,2008,6,"auto(av)","f",18,27,"p","compact"\n"8","audi","a4 quattro",1.8,1999,4,"manual(m5)","4",18,26,"p","compact"\n"9","audi","a4 quattro",1.8,1999,4,"auto(l5)","4",16,25,"p","compact"\n"10","audi","a4 quattro",2,2008,4,"manual(m6)","4",20,28,"p","compact"\n"11","audi","a4 quattro",2,2008,4,"auto(s6)","4",19,27,"p","compact"\n"12","audi","a4 quattro",2.8,1999,6,"auto(l5)","4",15,25,"p","compact"\n"13","audi","a4 quattro",2.8,1999,6,"manual(m5)","4",17,25,"p","compact"\n"14","audi","a4 quattro",3.1,2008,6,"auto(s6)","4",17,25,"p","compact"\n"15","audi","a4 quattro",3.1,2008,6,"manual(m6)","4",15,25,"p","compact"\n"16","audi","a6 quattro",2.8,1999,6,"auto(l5)","4",15,24,"p","midsize"\n"17","audi","a6 quattro",3.1,2008,6,"auto(s6)","4",17,25,"p","midsize"\n"18","audi","a6 quattro",4.2,2008,8,"auto(s6)","4",16,23,"p","midsize"\n"19","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",14,20,"r","suv"\n"20","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",11,15,"e","suv"\n"21","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",14,20,"r","suv"\n"22","chevrolet","c1500 suburban 2wd",5.7,1999,8,"auto(l4)","r",13,17,"r","suv"\n"23","chevrolet","c1500 suburban 2wd",6,2008,8,"auto(l4)","r",12,17,"r","suv"\n"24","chevrolet","corvette",5.7,1999,8,"manual(m6)","r",16,26,"p","2seater"\n"25","chevrolet","corvette",5.7,1999,8,"auto(l4)","r",15,23,"p","2seater"\n"26","chevrolet","corvette",6.2,2008,8,"manual(m6)","r",16,26,"p","2seater"\n"27","chevrolet","corvette",6.2,2008,8,"auto(s6)","r",15,25,"p","2seater"\n"28","chevrolet","corvette",7,2008,8,"manual(m6)","r",15,24,"p","2seater"\n"29","chevrolet","k1500 tahoe 4wd",5.3,2008,8,"auto(l4)","4",14,19,"r","suv"\n"30","chevrolet","k1500 tahoe 4wd",5.3,2008,8,"auto(l4)","4",11,14,"e","suv"\n"31","chevrolet","k1500 tahoe 4wd",5.7,1999,8,"auto(l4)","4",11,15,"r","suv"\n"32","chevrolet","k1500 tahoe 4wd",6.5,1999,8,"auto(l4)","4",14,17,"d","suv"\n"33","chevrolet","malibu",2.4,1999,4,"auto(l4)","f",19,27,"r","midsize"\n"34","chevrolet","malibu",2.4,2008,4,"auto(l4)","f",22,30,"r","midsize"\n"35","chevrolet","malibu",3.1,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"36","chevrolet","malibu",3.5,2008,6,"auto(l4)","f",18,29,"r","midsize"\n"37","chevrolet","malibu",3.6,2008,6,"auto(s6)","f",17,26,"r","midsize"\n"38","dodge","caravan 2wd",2.4,1999,4,"auto(l3)","f",18,24,"r","minivan"\n"39","dodge","caravan 2wd",3,1999,6,"auto(l4)","f",17,24,"r","minivan"\n"40","dodge","caravan 2wd",3.3,1999,6,"auto(l4)","f",16,22,"r","minivan"\n"41","dodge","caravan 2wd",3.3,1999,6,"auto(l4)","f",16,22,"r","minivan"\n"42","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",17,24,"r","minivan"\n"43","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",17,24,"r","minivan"\n"44","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",11,17,"e","minivan"\n"45","dodge","caravan 2wd",3.8,1999,6,"auto(l4)","f",15,22,"r","minivan"\n"46","dodge","caravan 2wd",3.8,1999,6,"auto(l4)","f",15,21,"r","minivan"\n"47","dodge","caravan 2wd",3.8,2008,6,"auto(l6)","f",16,23,"r","minivan"\n"48","dodge","caravan 2wd",4,2008,6,"auto(l6)","f",16,23,"r","minivan"\n"49","dodge","dakota pickup 4wd",3.7,2008,6,"manual(m6)","4",15,19,"r","pickup"\n"50","dodge","dakota pickup 4wd",3.7,2008,6,"auto(l4)","4",14,18,"r","pickup"\n"51","dodge","dakota pickup 4wd",3.9,1999,6,"auto(l4)","4",13,17,"r","pickup"\n"52","dodge","dakota pickup 4wd",3.9,1999,6,"manual(m5)","4",14,17,"r","pickup"\n"53","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","pickup"\n"54","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","pickup"\n"55","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","pickup"\n"56","dodge","dakota pickup 4wd",5.2,1999,8,"manual(m5)","4",11,17,"r","pickup"\n"57","dodge","dakota pickup 4wd",5.2,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"58","dodge","durango 4wd",3.9,1999,6,"auto(l4)","4",13,17,"r","suv"\n"59","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","suv"\n"60","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","suv"\n"61","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","suv"\n"62","dodge","durango 4wd",5.2,1999,8,"auto(l4)","4",11,16,"r","suv"\n"63","dodge","durango 4wd",5.7,2008,8,"auto(l5)","4",13,18,"r","suv"\n"64","dodge","durango 4wd",5.9,1999,8,"auto(l4)","4",11,15,"r","suv"\n"65","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",12,16,"r","pickup"\n"66","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","pickup"\n"67","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"68","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"69","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",12,16,"r","pickup"\n"70","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",9,12,"e","pickup"\n"71","dodge","ram 1500 pickup 4wd",5.2,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"72","dodge","ram 1500 pickup 4wd",5.2,1999,8,"manual(m5)","4",11,16,"r","pickup"\n"73","dodge","ram 1500 pickup 4wd",5.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"74","dodge","ram 1500 pickup 4wd",5.9,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"75","ford","expedition 2wd",4.6,1999,8,"auto(l4)","r",11,17,"r","suv"\n"76","ford","expedition 2wd",5.4,1999,8,"auto(l4)","r",11,17,"r","suv"\n"77","ford","expedition 2wd",5.4,2008,8,"auto(l6)","r",12,18,"r","suv"\n"78","ford","explorer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"79","ford","explorer 4wd",4,1999,6,"manual(m5)","4",15,19,"r","suv"\n"80","ford","explorer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"81","ford","explorer 4wd",4,2008,6,"auto(l5)","4",13,19,"r","suv"\n"82","ford","explorer 4wd",4.6,2008,8,"auto(l6)","4",13,19,"r","suv"\n"83","ford","explorer 4wd",5,1999,8,"auto(l4)","4",13,17,"r","suv"\n"84","ford","f150 pickup 4wd",4.2,1999,6,"auto(l4)","4",14,17,"r","pickup"\n"85","ford","f150 pickup 4wd",4.2,1999,6,"manual(m5)","4",14,17,"r","pickup"\n"86","ford","f150 pickup 4wd",4.6,1999,8,"manual(m5)","4",13,16,"r","pickup"\n"87","ford","f150 pickup 4wd",4.6,1999,8,"auto(l4)","4",13,16,"r","pickup"\n"88","ford","f150 pickup 4wd",4.6,2008,8,"auto(l4)","4",13,17,"r","pickup"\n"89","ford","f150 pickup 4wd",5.4,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"90","ford","f150 pickup 4wd",5.4,2008,8,"auto(l4)","4",13,17,"r","pickup"\n"91","ford","mustang",3.8,1999,6,"manual(m5)","r",18,26,"r","subcompact"\n"92","ford","mustang",3.8,1999,6,"auto(l4)","r",18,25,"r","subcompact"\n"93","ford","mustang",4,2008,6,"manual(m5)","r",17,26,"r","subcompact"\n"94","ford","mustang",4,2008,6,"auto(l5)","r",16,24,"r","subcompact"\n"95","ford","mustang",4.6,1999,8,"auto(l4)","r",15,21,"r","subcompact"\n"96","ford","mustang",4.6,1999,8,"manual(m5)","r",15,22,"r","subcompact"\n"97","ford","mustang",4.6,2008,8,"manual(m5)","r",15,23,"r","subcompact"\n"98","ford","mustang",4.6,2008,8,"auto(l5)","r",15,22,"r","subcompact"\n"99","ford","mustang",5.4,2008,8,"manual(m6)","r",14,20,"p","subcompact"\n"100","honda","civic",1.6,1999,4,"manual(m5)","f",28,33,"r","subcompact"\n"101","honda","civic",1.6,1999,4,"auto(l4)","f",24,32,"r","subcompact"\n"102","honda","civic",1.6,1999,4,"manual(m5)","f",25,32,"r","subcompact"\n"103","honda","civic",1.6,1999,4,"manual(m5)","f",23,29,"p","subcompact"\n"104","honda","civic",1.6,1999,4,"auto(l4)","f",24,32,"r","subcompact"\n"105","honda","civic",1.8,2008,4,"manual(m5)","f",26,34,"r","subcompact"\n"106","honda","civic",1.8,2008,4,"auto(l5)","f",25,36,"r","subcompact"\n"107","honda","civic",1.8,2008,4,"auto(l5)","f",24,36,"c","subcompact"\n"108","honda","civic",2,2008,4,"manual(m6)","f",21,29,"p","subcompact"\n"109","hyundai","sonata",2.4,1999,4,"auto(l4)","f",18,26,"r","midsize"\n"110","hyundai","sonata",2.4,1999,4,"manual(m5)","f",18,27,"r","midsize"\n"111","hyundai","sonata",2.4,2008,4,"auto(l4)","f",21,30,"r","midsize"\n"112","hyundai","sonata",2.4,2008,4,"manual(m5)","f",21,31,"r","midsize"\n"113","hyundai","sonata",2.5,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"114","hyundai","sonata",2.5,1999,6,"manual(m5)","f",18,26,"r","midsize"\n"115","hyundai","sonata",3.3,2008,6,"auto(l5)","f",19,28,"r","midsize"\n"116","hyundai","tiburon",2,1999,4,"auto(l4)","f",19,26,"r","subcompact"\n"117","hyundai","tiburon",2,1999,4,"manual(m5)","f",19,29,"r","subcompact"\n"118","hyundai","tiburon",2,2008,4,"manual(m5)","f",20,28,"r","subcompact"\n"119","hyundai","tiburon",2,2008,4,"auto(l4)","f",20,27,"r","subcompact"\n"120","hyundai","tiburon",2.7,2008,6,"auto(l4)","f",17,24,"r","subcompact"\n"121","hyundai","tiburon",2.7,2008,6,"manual(m6)","f",16,24,"r","subcompact"\n"122","hyundai","tiburon",2.7,2008,6,"manual(m5)","f",17,24,"r","subcompact"\n"123","jeep","grand cherokee 4wd",3,2008,6,"auto(l5)","4",17,22,"d","suv"\n"124","jeep","grand cherokee 4wd",3.7,2008,6,"auto(l5)","4",15,19,"r","suv"\n"125","jeep","grand cherokee 4wd",4,1999,6,"auto(l4)","4",15,20,"r","suv"\n"126","jeep","grand cherokee 4wd",4.7,1999,8,"auto(l4)","4",14,17,"r","suv"\n"127","jeep","grand cherokee 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","suv"\n"128","jeep","grand cherokee 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","suv"\n"129","jeep","grand cherokee 4wd",5.7,2008,8,"auto(l5)","4",13,18,"r","suv"\n"130","jeep","grand cherokee 4wd",6.1,2008,8,"auto(l5)","4",11,14,"p","suv"\n"131","land rover","range rover",4,1999,8,"auto(l4)","4",11,15,"p","suv"\n"132","land rover","range rover",4.2,2008,8,"auto(s6)","4",12,18,"r","suv"\n"133","land rover","range rover",4.4,2008,8,"auto(s6)","4",12,18,"r","suv"\n"134","land rover","range rover",4.6,1999,8,"auto(l4)","4",11,15,"p","suv"\n"135","lincoln","navigator 2wd",5.4,1999,8,"auto(l4)","r",11,17,"r","suv"\n"136","lincoln","navigator 2wd",5.4,1999,8,"auto(l4)","r",11,16,"p","suv"\n"137","lincoln","navigator 2wd",5.4,2008,8,"auto(l6)","r",12,18,"r","suv"\n"138","mercury","mountaineer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"139","mercury","mountaineer 4wd",4,2008,6,"auto(l5)","4",13,19,"r","suv"\n"140","mercury","mountaineer 4wd",4.6,2008,8,"auto(l6)","4",13,19,"r","suv"\n"141","mercury","mountaineer 4wd",5,1999,8,"auto(l4)","4",13,17,"r","suv"\n"142","nissan","altima",2.4,1999,4,"manual(m5)","f",21,29,"r","compact"\n"143","nissan","altima",2.4,1999,4,"auto(l4)","f",19,27,"r","compact"\n"144","nissan","altima",2.5,2008,4,"auto(av)","f",23,31,"r","midsize"\n"145","nissan","altima",2.5,2008,4,"manual(m6)","f",23,32,"r","midsize"\n"146","nissan","altima",3.5,2008,6,"manual(m6)","f",19,27,"p","midsize"\n"147","nissan","altima",3.5,2008,6,"auto(av)","f",19,26,"p","midsize"\n"148","nissan","maxima",3,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"149","nissan","maxima",3,1999,6,"manual(m5)","f",19,25,"r","midsize"\n"150","nissan","maxima",3.5,2008,6,"auto(av)","f",19,25,"p","midsize"\n"151","nissan","pathfinder 4wd",3.3,1999,6,"auto(l4)","4",14,17,"r","suv"\n"152","nissan","pathfinder 4wd",3.3,1999,6,"manual(m5)","4",15,17,"r","suv"\n"153","nissan","pathfinder 4wd",4,2008,6,"auto(l5)","4",14,20,"p","suv"\n"154","nissan","pathfinder 4wd",5.6,2008,8,"auto(s5)","4",12,18,"p","suv"\n"155","pontiac","grand prix",3.1,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"156","pontiac","grand prix",3.8,1999,6,"auto(l4)","f",16,26,"p","midsize"\n"157","pontiac","grand prix",3.8,1999,6,"auto(l4)","f",17,27,"r","midsize"\n"158","pontiac","grand prix",3.8,2008,6,"auto(l4)","f",18,28,"r","midsize"\n"159","pontiac","grand prix",5.3,2008,8,"auto(s4)","f",16,25,"p","midsize"\n"160","subaru","forester awd",2.5,1999,4,"manual(m5)","4",18,25,"r","suv"\n"161","subaru","forester awd",2.5,1999,4,"auto(l4)","4",18,24,"r","suv"\n"162","subaru","forester awd",2.5,2008,4,"manual(m5)","4",20,27,"r","suv"\n"163","subaru","forester awd",2.5,2008,4,"manual(m5)","4",19,25,"p","suv"\n"164","subaru","forester awd",2.5,2008,4,"auto(l4)","4",20,26,"r","suv"\n"165","subaru","forester awd",2.5,2008,4,"auto(l4)","4",18,23,"p","suv"\n"166","subaru","impreza awd",2.2,1999,4,"auto(l4)","4",21,26,"r","subcompact"\n"167","subaru","impreza awd",2.2,1999,4,"manual(m5)","4",19,26,"r","subcompact"\n"168","subaru","impreza awd",2.5,1999,4,"manual(m5)","4",19,26,"r","subcompact"\n"169","subaru","impreza awd",2.5,1999,4,"auto(l4)","4",19,26,"r","subcompact"\n"170","subaru","impreza awd",2.5,2008,4,"auto(s4)","4",20,25,"p","compact"\n"171","subaru","impreza awd",2.5,2008,4,"auto(s4)","4",20,27,"r","compact"\n"172","subaru","impreza awd",2.5,2008,4,"manual(m5)","4",19,25,"p","compact"\n"173","subaru","impreza awd",2.5,2008,4,"manual(m5)","4",20,27,"r","compact"\n"174","toyota","4runner 4wd",2.7,1999,4,"manual(m5)","4",15,20,"r","suv"\n"175","toyota","4runner 4wd",2.7,1999,4,"auto(l4)","4",16,20,"r","suv"\n"176","toyota","4runner 4wd",3.4,1999,6,"auto(l4)","4",15,19,"r","suv"\n"177","toyota","4runner 4wd",3.4,1999,6,"manual(m5)","4",15,17,"r","suv"\n"178","toyota","4runner 4wd",4,2008,6,"auto(l5)","4",16,20,"r","suv"\n"179","toyota","4runner 4wd",4.7,2008,8,"auto(l5)","4",14,17,"r","suv"\n"180","toyota","camry",2.2,1999,4,"manual(m5)","f",21,29,"r","midsize"\n"181","toyota","camry",2.2,1999,4,"auto(l4)","f",21,27,"r","midsize"\n"182","toyota","camry",2.4,2008,4,"manual(m5)","f",21,31,"r","midsize"\n"183","toyota","camry",2.4,2008,4,"auto(l5)","f",21,31,"r","midsize"\n"184","toyota","camry",3,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"185","toyota","camry",3,1999,6,"manual(m5)","f",18,26,"r","midsize"\n"186","toyota","camry",3.5,2008,6,"auto(s6)","f",19,28,"r","midsize"\n"187","toyota","camry solara",2.2,1999,4,"auto(l4)","f",21,27,"r","compact"\n"188","toyota","camry solara",2.2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"189","toyota","camry solara",2.4,2008,4,"manual(m5)","f",21,31,"r","compact"\n"190","toyota","camry solara",2.4,2008,4,"auto(s5)","f",22,31,"r","compact"\n"191","toyota","camry solara",3,1999,6,"auto(l4)","f",18,26,"r","compact"\n"192","toyota","camry solara",3,1999,6,"manual(m5)","f",18,26,"r","compact"\n"193","toyota","camry solara",3.3,2008,6,"auto(s5)","f",18,27,"r","compact"\n"194","toyota","corolla",1.8,1999,4,"auto(l3)","f",24,30,"r","compact"\n"195","toyota","corolla",1.8,1999,4,"auto(l4)","f",24,33,"r","compact"\n"196","toyota","corolla",1.8,1999,4,"manual(m5)","f",26,35,"r","compact"\n"197","toyota","corolla",1.8,2008,4,"manual(m5)","f",28,37,"r","compact"\n"198","toyota","corolla",1.8,2008,4,"auto(l4)","f",26,35,"r","compact"\n"199","toyota","land cruiser wagon 4wd",4.7,1999,8,"auto(l4)","4",11,15,"r","suv"\n"200","toyota","land cruiser wagon 4wd",5.7,2008,8,"auto(s6)","4",13,18,"r","suv"\n"201","toyota","toyota tacoma 4wd",2.7,1999,4,"manual(m5)","4",15,20,"r","pickup"\n"202","toyota","toyota tacoma 4wd",2.7,1999,4,"auto(l4)","4",16,20,"r","pickup"\n"203","toyota","toyota tacoma 4wd",2.7,2008,4,"manual(m5)","4",17,22,"r","pickup"\n"204","toyota","toyota tacoma 4wd",3.4,1999,6,"manual(m5)","4",15,17,"r","pickup"\n"205","toyota","toyota tacoma 4wd",3.4,1999,6,"auto(l4)","4",15,19,"r","pickup"\n"206","toyota","toyota tacoma 4wd",4,2008,6,"manual(m6)","4",15,18,"r","pickup"\n"207","toyota","toyota tacoma 4wd",4,2008,6,"auto(l5)","4",16,20,"r","pickup"\n"208","volkswagen","gti",2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"209","volkswagen","gti",2,1999,4,"auto(l4)","f",19,26,"r","compact"\n"210","volkswagen","gti",2,2008,4,"manual(m6)","f",21,29,"p","compact"\n"211","volkswagen","gti",2,2008,4,"auto(s6)","f",22,29,"p","compact"\n"212","volkswagen","gti",2.8,1999,6,"manual(m5)","f",17,24,"r","compact"\n"213","volkswagen","jetta",1.9,1999,4,"manual(m5)","f",33,44,"d","compact"\n"214","volkswagen","jetta",2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"215","volkswagen","jetta",2,1999,4,"auto(l4)","f",19,26,"r","compact"\n"216","volkswagen","jetta",2,2008,4,"auto(s6)","f",22,29,"p","compact"\n"217","volkswagen","jetta",2,2008,4,"manual(m6)","f",21,29,"p","compact"\n"218","volkswagen","jetta",2.5,2008,5,"auto(s6)","f",21,29,"r","compact"\n"219","volkswagen","jetta",2.5,2008,5,"manual(m5)","f",21,29,"r","compact"\n"220","volkswagen","jetta",2.8,1999,6,"auto(l4)","f",16,23,"r","compact"\n"221","volkswagen","jetta",2.8,1999,6,"manual(m5)","f",17,24,"r","compact"\n"222","volkswagen","new beetle",1.9,1999,4,"manual(m5)","f",35,44,"d","subcompact"\n"223","volkswagen","new beetle",1.9,1999,4,"auto(l4)","f",29,41,"d","subcompact"\n"224","volkswagen","new beetle",2,1999,4,"manual(m5)","f",21,29,"r","subcompact"\n"225","volkswagen","new beetle",2,1999,4,"auto(l4)","f",19,26,"r","subcompact"\n"226","volkswagen","new beetle",2.5,2008,5,"manual(m5)","f",20,28,"r","subcompact"\n"227","volkswagen","new beetle",2.5,2008,5,"auto(s6)","f",20,29,"r","subcompact"\n"228","volkswagen","passat",1.8,1999,4,"manual(m5)","f",21,29,"p","midsize"\n"229","volkswagen","passat",1.8,1999,4,"auto(l5)","f",18,29,"p","midsize"\n"230","volkswagen","passat",2,2008,4,"auto(s6)","f",19,28,"p","midsize"\n"231","volkswagen","passat",2,2008,4,"manual(m6)","f",21,29,"p","midsize"\n"232","volkswagen","passat",2.8,1999,6,"auto(l5)","f",16,26,"p","midsize"\n"233","volkswagen","passat",2.8,1999,6,"manual(m5)","f",18,26,"p","midsize"\n"234","volkswagen","passat",3.6,2008,6,"auto(s6)","f",17,26,"p","midsize"\n'


This looks much better. At least, it's reabable. However, it's still in the form of a string. Let's convert it into our required format.

In [14]:
from io import StringIO
# Decoding & formatting
data=csv.reader(StringIO(content.decode('utf-8')))
#Printing the first 5 rows
for row in list(data)[:5]:
    print(row)
['', 'manufacturer', 'model', 'displ', 'year', 'cyl', 'trans', 'drv', 'cty', 'hwy', 'fl', 'class']
['1', 'audi', 'a4', '1.8', '1999', '4', 'auto(l5)', 'f', '18', '29', 'p', 'compact']
['2', 'audi', 'a4', '1.8', '1999', '4', 'manual(m5)', 'f', '21', '29', 'p', 'compact']
['3', 'audi', 'a4', '2', '2008', '4', 'manual(m6)', 'f', '20', '31', 'p', 'compact']
['4', 'audi', 'a4', '2', '2008', '4', 'auto(av)', 'f', '21', '30', 'p', 'compact']


Looks great! Now we already know how to convert the data into a Python dictionary.

In [15]:
# Converting aata to a dictionary format
data=list(csv.DictReader(StringIO(content.decode('utf-8'))))
# Printing the first 2 rows
data[:2]
Out[15]:
[{'': '1',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'auto(l5)',
  'drv': 'f',
  'cty': '18',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'},
 {'': '2',
  'manufacturer': 'audi',
  'model': 'a4',
  'displ': '1.8',
  'year': '1999',
  'cyl': '4',
  'trans': 'manual(m5)',
  'drv': 'f',
  'cty': '21',
  'hwy': '29',
  'fl': 'p',
  'class': 'compact'}]

Project files

ref

Get a file:

In [16]:
f=project.files.get(file_path='mpg.csv', ref='master')
# get the base64 encoded content
print(f.content)
IiIsIm1hbnVmYWN0dXJlciIsIm1vZGVsIiwiZGlzcGwiLCJ5ZWFyIiwiY3lsIiwidHJhbnMiLCJkcnYiLCJjdHkiLCJod3kiLCJmbCIsImNsYXNzIgoiMSIsImF1ZGkiLCJhNCIsMS44LDE5OTksNCwiYXV0byhsNSkiLCJmIiwxOCwyOSwicCIsImNvbXBhY3QiCiIyIiwiYXVkaSIsImE0IiwxLjgsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMjEsMjksInAiLCJjb21wYWN0IgoiMyIsImF1ZGkiLCJhNCIsMiwyMDA4LDQsIm1hbnVhbChtNikiLCJmIiwyMCwzMSwicCIsImNvbXBhY3QiCiI0IiwiYXVkaSIsImE0IiwyLDIwMDgsNCwiYXV0byhhdikiLCJmIiwyMSwzMCwicCIsImNvbXBhY3QiCiI1IiwiYXVkaSIsImE0IiwyLjgsMTk5OSw2LCJhdXRvKGw1KSIsImYiLDE2LDI2LCJwIiwiY29tcGFjdCIKIjYiLCJhdWRpIiwiYTQiLDIuOCwxOTk5LDYsIm1hbnVhbChtNSkiLCJmIiwxOCwyNiwicCIsImNvbXBhY3QiCiI3IiwiYXVkaSIsImE0IiwzLjEsMjAwOCw2LCJhdXRvKGF2KSIsImYiLDE4LDI3LCJwIiwiY29tcGFjdCIKIjgiLCJhdWRpIiwiYTQgcXVhdHRybyIsMS44LDE5OTksNCwibWFudWFsKG01KSIsIjQiLDE4LDI2LCJwIiwiY29tcGFjdCIKIjkiLCJhdWRpIiwiYTQgcXVhdHRybyIsMS44LDE5OTksNCwiYXV0byhsNSkiLCI0IiwxNiwyNSwicCIsImNvbXBhY3QiCiIxMCIsImF1ZGkiLCJhNCBxdWF0dHJvIiwyLDIwMDgsNCwibWFudWFsKG02KSIsIjQiLDIwLDI4LCJwIiwiY29tcGFjdCIKIjExIiwiYXVkaSIsImE0IHF1YXR0cm8iLDIsMjAwOCw0LCJhdXRvKHM2KSIsIjQiLDE5LDI3LCJwIiwiY29tcGFjdCIKIjEyIiwiYXVkaSIsImE0IHF1YXR0cm8iLDIuOCwxOTk5LDYsImF1dG8obDUpIiwiNCIsMTUsMjUsInAiLCJjb21wYWN0IgoiMTMiLCJhdWRpIiwiYTQgcXVhdHRybyIsMi44LDE5OTksNiwibWFudWFsKG01KSIsIjQiLDE3LDI1LCJwIiwiY29tcGFjdCIKIjE0IiwiYXVkaSIsImE0IHF1YXR0cm8iLDMuMSwyMDA4LDYsImF1dG8oczYpIiwiNCIsMTcsMjUsInAiLCJjb21wYWN0IgoiMTUiLCJhdWRpIiwiYTQgcXVhdHRybyIsMy4xLDIwMDgsNiwibWFudWFsKG02KSIsIjQiLDE1LDI1LCJwIiwiY29tcGFjdCIKIjE2IiwiYXVkaSIsImE2IHF1YXR0cm8iLDIuOCwxOTk5LDYsImF1dG8obDUpIiwiNCIsMTUsMjQsInAiLCJtaWRzaXplIgoiMTciLCJhdWRpIiwiYTYgcXVhdHRybyIsMy4xLDIwMDgsNiwiYXV0byhzNikiLCI0IiwxNywyNSwicCIsIm1pZHNpemUiCiIxOCIsImF1ZGkiLCJhNiBxdWF0dHJvIiw0LjIsMjAwOCw4LCJhdXRvKHM2KSIsIjQiLDE2LDIzLCJwIiwibWlkc2l6ZSIKIjE5IiwiY2hldnJvbGV0IiwiYzE1MDAgc3VidXJiYW4gMndkIiw1LjMsMjAwOCw4LCJhdXRvKGw0KSIsInIiLDE0LDIwLCJyIiwic3V2IgoiMjAiLCJjaGV2cm9sZXQiLCJjMTUwMCBzdWJ1cmJhbiAyd2QiLDUuMywyMDA4LDgsImF1dG8obDQpIiwiciIsMTEsMTUsImUiLCJzdXYiCiIyMSIsImNoZXZyb2xldCIsImMxNTAwIHN1YnVyYmFuIDJ3ZCIsNS4zLDIwMDgsOCwiYXV0byhsNCkiLCJyIiwxNCwyMCwiciIsInN1diIKIjIyIiwiY2hldnJvbGV0IiwiYzE1MDAgc3VidXJiYW4gMndkIiw1LjcsMTk5OSw4LCJhdXRvKGw0KSIsInIiLDEzLDE3LCJyIiwic3V2IgoiMjMiLCJjaGV2cm9sZXQiLCJjMTUwMCBzdWJ1cmJhbiAyd2QiLDYsMjAwOCw4LCJhdXRvKGw0KSIsInIiLDEyLDE3LCJyIiwic3V2IgoiMjQiLCJjaGV2cm9sZXQiLCJjb3J2ZXR0ZSIsNS43LDE5OTksOCwibWFudWFsKG02KSIsInIiLDE2LDI2LCJwIiwiMnNlYXRlciIKIjI1IiwiY2hldnJvbGV0IiwiY29ydmV0dGUiLDUuNywxOTk5LDgsImF1dG8obDQpIiwiciIsMTUsMjMsInAiLCIyc2VhdGVyIgoiMjYiLCJjaGV2cm9sZXQiLCJjb3J2ZXR0ZSIsNi4yLDIwMDgsOCwibWFudWFsKG02KSIsInIiLDE2LDI2LCJwIiwiMnNlYXRlciIKIjI3IiwiY2hldnJvbGV0IiwiY29ydmV0dGUiLDYuMiwyMDA4LDgsImF1dG8oczYpIiwiciIsMTUsMjUsInAiLCIyc2VhdGVyIgoiMjgiLCJjaGV2cm9sZXQiLCJjb3J2ZXR0ZSIsNywyMDA4LDgsIm1hbnVhbChtNikiLCJyIiwxNSwyNCwicCIsIjJzZWF0ZXIiCiIyOSIsImNoZXZyb2xldCIsImsxNTAwIHRhaG9lIDR3ZCIsNS4zLDIwMDgsOCwiYXV0byhsNCkiLCI0IiwxNCwxOSwiciIsInN1diIKIjMwIiwiY2hldnJvbGV0IiwiazE1MDAgdGFob2UgNHdkIiw1LjMsMjAwOCw4LCJhdXRvKGw0KSIsIjQiLDExLDE0LCJlIiwic3V2IgoiMzEiLCJjaGV2cm9sZXQiLCJrMTUwMCB0YWhvZSA0d2QiLDUuNywxOTk5LDgsImF1dG8obDQpIiwiNCIsMTEsMTUsInIiLCJzdXYiCiIzMiIsImNoZXZyb2xldCIsImsxNTAwIHRhaG9lIDR3ZCIsNi41LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxNCwxNywiZCIsInN1diIKIjMzIiwiY2hldnJvbGV0IiwibWFsaWJ1IiwyLjQsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDE5LDI3LCJyIiwibWlkc2l6ZSIKIjM0IiwiY2hldnJvbGV0IiwibWFsaWJ1IiwyLjQsMjAwOCw0LCJhdXRvKGw0KSIsImYiLDIyLDMwLCJyIiwibWlkc2l6ZSIKIjM1IiwiY2hldnJvbGV0IiwibWFsaWJ1IiwzLjEsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE4LDI2LCJyIiwibWlkc2l6ZSIKIjM2IiwiY2hldnJvbGV0IiwibWFsaWJ1IiwzLjUsMjAwOCw2LCJhdXRvKGw0KSIsImYiLDE4LDI5LCJyIiwibWlkc2l6ZSIKIjM3IiwiY2hldnJvbGV0IiwibWFsaWJ1IiwzLjYsMjAwOCw2LCJhdXRvKHM2KSIsImYiLDE3LDI2LCJyIiwibWlkc2l6ZSIKIjM4IiwiZG9kZ2UiLCJjYXJhdmFuIDJ3ZCIsMi40LDE5OTksNCwiYXV0byhsMykiLCJmIiwxOCwyNCwiciIsIm1pbml2YW4iCiIzOSIsImRvZGdlIiwiY2FyYXZhbiAyd2QiLDMsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE3LDI0LCJyIiwibWluaXZhbiIKIjQwIiwiZG9kZ2UiLCJjYXJhdmFuIDJ3ZCIsMy4zLDE5OTksNiwiYXV0byhsNCkiLCJmIiwxNiwyMiwiciIsIm1pbml2YW4iCiI0MSIsImRvZGdlIiwiY2FyYXZhbiAyd2QiLDMuMywxOTk5LDYsImF1dG8obDQpIiwiZiIsMTYsMjIsInIiLCJtaW5pdmFuIgoiNDIiLCJkb2RnZSIsImNhcmF2YW4gMndkIiwzLjMsMjAwOCw2LCJhdXRvKGw0KSIsImYiLDE3LDI0LCJyIiwibWluaXZhbiIKIjQzIiwiZG9kZ2UiLCJjYXJhdmFuIDJ3ZCIsMy4zLDIwMDgsNiwiYXV0byhsNCkiLCJmIiwxNywyNCwiciIsIm1pbml2YW4iCiI0NCIsImRvZGdlIiwiY2FyYXZhbiAyd2QiLDMuMywyMDA4LDYsImF1dG8obDQpIiwiZiIsMTEsMTcsImUiLCJtaW5pdmFuIgoiNDUiLCJkb2RnZSIsImNhcmF2YW4gMndkIiwzLjgsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE1LDIyLCJyIiwibWluaXZhbiIKIjQ2IiwiZG9kZ2UiLCJjYXJhdmFuIDJ3ZCIsMy44LDE5OTksNiwiYXV0byhsNCkiLCJmIiwxNSwyMSwiciIsIm1pbml2YW4iCiI0NyIsImRvZGdlIiwiY2FyYXZhbiAyd2QiLDMuOCwyMDA4LDYsImF1dG8obDYpIiwiZiIsMTYsMjMsInIiLCJtaW5pdmFuIgoiNDgiLCJkb2RnZSIsImNhcmF2YW4gMndkIiw0LDIwMDgsNiwiYXV0byhsNikiLCJmIiwxNiwyMywiciIsIm1pbml2YW4iCiI0OSIsImRvZGdlIiwiZGFrb3RhIHBpY2t1cCA0d2QiLDMuNywyMDA4LDYsIm1hbnVhbChtNikiLCI0IiwxNSwxOSwiciIsInBpY2t1cCIKIjUwIiwiZG9kZ2UiLCJkYWtvdGEgcGlja3VwIDR3ZCIsMy43LDIwMDgsNiwiYXV0byhsNCkiLCI0IiwxNCwxOCwiciIsInBpY2t1cCIKIjUxIiwiZG9kZ2UiLCJkYWtvdGEgcGlja3VwIDR3ZCIsMy45LDE5OTksNiwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInBpY2t1cCIKIjUyIiwiZG9kZ2UiLCJkYWtvdGEgcGlja3VwIDR3ZCIsMy45LDE5OTksNiwibWFudWFsKG01KSIsIjQiLDE0LDE3LCJyIiwicGlja3VwIgoiNTMiLCJkb2RnZSIsImRha290YSBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDE0LDE5LCJyIiwicGlja3VwIgoiNTQiLCJkb2RnZSIsImRha290YSBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDE0LDE5LCJyIiwicGlja3VwIgoiNTUiLCJkb2RnZSIsImRha290YSBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDksMTIsImUiLCJwaWNrdXAiCiI1NiIsImRvZGdlIiwiZGFrb3RhIHBpY2t1cCA0d2QiLDUuMiwxOTk5LDgsIm1hbnVhbChtNSkiLCI0IiwxMSwxNywiciIsInBpY2t1cCIKIjU3IiwiZG9kZ2UiLCJkYWtvdGEgcGlja3VwIDR3ZCIsNS4yLDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMSwxNSwiciIsInBpY2t1cCIKIjU4IiwiZG9kZ2UiLCJkdXJhbmdvIDR3ZCIsMy45LDE5OTksNiwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInN1diIKIjU5IiwiZG9kZ2UiLCJkdXJhbmdvIDR3ZCIsNC43LDIwMDgsOCwiYXV0byhsNSkiLCI0IiwxMywxNywiciIsInN1diIKIjYwIiwiZG9kZ2UiLCJkdXJhbmdvIDR3ZCIsNC43LDIwMDgsOCwiYXV0byhsNSkiLCI0Iiw5LDEyLCJlIiwic3V2IgoiNjEiLCJkb2RnZSIsImR1cmFuZ28gNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDEzLDE3LCJyIiwic3V2IgoiNjIiLCJkb2RnZSIsImR1cmFuZ28gNHdkIiw1LjIsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE2LCJyIiwic3V2IgoiNjMiLCJkb2RnZSIsImR1cmFuZ28gNHdkIiw1LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDEzLDE4LCJyIiwic3V2IgoiNjQiLCJkb2RnZSIsImR1cmFuZ28gNHdkIiw1LjksMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE1LCJyIiwic3V2IgoiNjUiLCJkb2RnZSIsInJhbSAxNTAwIHBpY2t1cCA0d2QiLDQuNywyMDA4LDgsIm1hbnVhbChtNikiLCI0IiwxMiwxNiwiciIsInBpY2t1cCIKIjY2IiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDksMTIsImUiLCJwaWNrdXAiCiI2NyIsImRvZGdlIiwicmFtIDE1MDAgcGlja3VwIDR3ZCIsNC43LDIwMDgsOCwiYXV0byhsNSkiLCI0IiwxMywxNywiciIsInBpY2t1cCIKIjY4IiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDEzLDE3LCJyIiwicGlja3VwIgoiNjkiLCJkb2RnZSIsInJhbSAxNTAwIHBpY2t1cCA0d2QiLDQuNywyMDA4LDgsIm1hbnVhbChtNikiLCI0IiwxMiwxNiwiciIsInBpY2t1cCIKIjcwIiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw0LjcsMjAwOCw4LCJtYW51YWwobTYpIiwiNCIsOSwxMiwiZSIsInBpY2t1cCIKIjcxIiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw1LjIsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE1LCJyIiwicGlja3VwIgoiNzIiLCJkb2RnZSIsInJhbSAxNTAwIHBpY2t1cCA0d2QiLDUuMiwxOTk5LDgsIm1hbnVhbChtNSkiLCI0IiwxMSwxNiwiciIsInBpY2t1cCIKIjczIiwiZG9kZ2UiLCJyYW0gMTUwMCBwaWNrdXAgNHdkIiw1LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDEzLDE3LCJyIiwicGlja3VwIgoiNzQiLCJkb2RnZSIsInJhbSAxNTAwIHBpY2t1cCA0d2QiLDUuOSwxOTk5LDgsImF1dG8obDQpIiwiNCIsMTEsMTUsInIiLCJwaWNrdXAiCiI3NSIsImZvcmQiLCJleHBlZGl0aW9uIDJ3ZCIsNC42LDE5OTksOCwiYXV0byhsNCkiLCJyIiwxMSwxNywiciIsInN1diIKIjc2IiwiZm9yZCIsImV4cGVkaXRpb24gMndkIiw1LjQsMTk5OSw4LCJhdXRvKGw0KSIsInIiLDExLDE3LCJyIiwic3V2IgoiNzciLCJmb3JkIiwiZXhwZWRpdGlvbiAyd2QiLDUuNCwyMDA4LDgsImF1dG8obDYpIiwiciIsMTIsMTgsInIiLCJzdXYiCiI3OCIsImZvcmQiLCJleHBsb3JlciA0d2QiLDQsMTk5OSw2LCJhdXRvKGw1KSIsIjQiLDE0LDE3LCJyIiwic3V2IgoiNzkiLCJmb3JkIiwiZXhwbG9yZXIgNHdkIiw0LDE5OTksNiwibWFudWFsKG01KSIsIjQiLDE1LDE5LCJyIiwic3V2IgoiODAiLCJmb3JkIiwiZXhwbG9yZXIgNHdkIiw0LDE5OTksNiwiYXV0byhsNSkiLCI0IiwxNCwxNywiciIsInN1diIKIjgxIiwiZm9yZCIsImV4cGxvcmVyIDR3ZCIsNCwyMDA4LDYsImF1dG8obDUpIiwiNCIsMTMsMTksInIiLCJzdXYiCiI4MiIsImZvcmQiLCJleHBsb3JlciA0d2QiLDQuNiwyMDA4LDgsImF1dG8obDYpIiwiNCIsMTMsMTksInIiLCJzdXYiCiI4MyIsImZvcmQiLCJleHBsb3JlciA0d2QiLDUsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDEzLDE3LCJyIiwic3V2IgoiODQiLCJmb3JkIiwiZjE1MCBwaWNrdXAgNHdkIiw0LjIsMTk5OSw2LCJhdXRvKGw0KSIsIjQiLDE0LDE3LCJyIiwicGlja3VwIgoiODUiLCJmb3JkIiwiZjE1MCBwaWNrdXAgNHdkIiw0LjIsMTk5OSw2LCJtYW51YWwobTUpIiwiNCIsMTQsMTcsInIiLCJwaWNrdXAiCiI4NiIsImZvcmQiLCJmMTUwIHBpY2t1cCA0d2QiLDQuNiwxOTk5LDgsIm1hbnVhbChtNSkiLCI0IiwxMywxNiwiciIsInBpY2t1cCIKIjg3IiwiZm9yZCIsImYxNTAgcGlja3VwIDR3ZCIsNC42LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMywxNiwiciIsInBpY2t1cCIKIjg4IiwiZm9yZCIsImYxNTAgcGlja3VwIDR3ZCIsNC42LDIwMDgsOCwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInBpY2t1cCIKIjg5IiwiZm9yZCIsImYxNTAgcGlja3VwIDR3ZCIsNS40LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMSwxNSwiciIsInBpY2t1cCIKIjkwIiwiZm9yZCIsImYxNTAgcGlja3VwIDR3ZCIsNS40LDIwMDgsOCwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInBpY2t1cCIKIjkxIiwiZm9yZCIsIm11c3RhbmciLDMuOCwxOTk5LDYsIm1hbnVhbChtNSkiLCJyIiwxOCwyNiwiciIsInN1YmNvbXBhY3QiCiI5MiIsImZvcmQiLCJtdXN0YW5nIiwzLjgsMTk5OSw2LCJhdXRvKGw0KSIsInIiLDE4LDI1LCJyIiwic3ViY29tcGFjdCIKIjkzIiwiZm9yZCIsIm11c3RhbmciLDQsMjAwOCw2LCJtYW51YWwobTUpIiwiciIsMTcsMjYsInIiLCJzdWJjb21wYWN0IgoiOTQiLCJmb3JkIiwibXVzdGFuZyIsNCwyMDA4LDYsImF1dG8obDUpIiwiciIsMTYsMjQsInIiLCJzdWJjb21wYWN0IgoiOTUiLCJmb3JkIiwibXVzdGFuZyIsNC42LDE5OTksOCwiYXV0byhsNCkiLCJyIiwxNSwyMSwiciIsInN1YmNvbXBhY3QiCiI5NiIsImZvcmQiLCJtdXN0YW5nIiw0LjYsMTk5OSw4LCJtYW51YWwobTUpIiwiciIsMTUsMjIsInIiLCJzdWJjb21wYWN0IgoiOTciLCJmb3JkIiwibXVzdGFuZyIsNC42LDIwMDgsOCwibWFudWFsKG01KSIsInIiLDE1LDIzLCJyIiwic3ViY29tcGFjdCIKIjk4IiwiZm9yZCIsIm11c3RhbmciLDQuNiwyMDA4LDgsImF1dG8obDUpIiwiciIsMTUsMjIsInIiLCJzdWJjb21wYWN0IgoiOTkiLCJmb3JkIiwibXVzdGFuZyIsNS40LDIwMDgsOCwibWFudWFsKG02KSIsInIiLDE0LDIwLCJwIiwic3ViY29tcGFjdCIKIjEwMCIsImhvbmRhIiwiY2l2aWMiLDEuNiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyOCwzMywiciIsInN1YmNvbXBhY3QiCiIxMDEiLCJob25kYSIsImNpdmljIiwxLjYsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDI0LDMyLCJyIiwic3ViY29tcGFjdCIKIjEwMiIsImhvbmRhIiwiY2l2aWMiLDEuNiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyNSwzMiwiciIsInN1YmNvbXBhY3QiCiIxMDMiLCJob25kYSIsImNpdmljIiwxLjYsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMjMsMjksInAiLCJzdWJjb21wYWN0IgoiMTA0IiwiaG9uZGEiLCJjaXZpYyIsMS42LDE5OTksNCwiYXV0byhsNCkiLCJmIiwyNCwzMiwiciIsInN1YmNvbXBhY3QiCiIxMDUiLCJob25kYSIsImNpdmljIiwxLjgsMjAwOCw0LCJtYW51YWwobTUpIiwiZiIsMjYsMzQsInIiLCJzdWJjb21wYWN0IgoiMTA2IiwiaG9uZGEiLCJjaXZpYyIsMS44LDIwMDgsNCwiYXV0byhsNSkiLCJmIiwyNSwzNiwiciIsInN1YmNvbXBhY3QiCiIxMDciLCJob25kYSIsImNpdmljIiwxLjgsMjAwOCw0LCJhdXRvKGw1KSIsImYiLDI0LDM2LCJjIiwic3ViY29tcGFjdCIKIjEwOCIsImhvbmRhIiwiY2l2aWMiLDIsMjAwOCw0LCJtYW51YWwobTYpIiwiZiIsMjEsMjksInAiLCJzdWJjb21wYWN0IgoiMTA5IiwiaHl1bmRhaSIsInNvbmF0YSIsMi40LDE5OTksNCwiYXV0byhsNCkiLCJmIiwxOCwyNiwiciIsIm1pZHNpemUiCiIxMTAiLCJoeXVuZGFpIiwic29uYXRhIiwyLjQsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMTgsMjcsInIiLCJtaWRzaXplIgoiMTExIiwiaHl1bmRhaSIsInNvbmF0YSIsMi40LDIwMDgsNCwiYXV0byhsNCkiLCJmIiwyMSwzMCwiciIsIm1pZHNpemUiCiIxMTIiLCJoeXVuZGFpIiwic29uYXRhIiwyLjQsMjAwOCw0LCJtYW51YWwobTUpIiwiZiIsMjEsMzEsInIiLCJtaWRzaXplIgoiMTEzIiwiaHl1bmRhaSIsInNvbmF0YSIsMi41LDE5OTksNiwiYXV0byhsNCkiLCJmIiwxOCwyNiwiciIsIm1pZHNpemUiCiIxMTQiLCJoeXVuZGFpIiwic29uYXRhIiwyLjUsMTk5OSw2LCJtYW51YWwobTUpIiwiZiIsMTgsMjYsInIiLCJtaWRzaXplIgoiMTE1IiwiaHl1bmRhaSIsInNvbmF0YSIsMy4zLDIwMDgsNiwiYXV0byhsNSkiLCJmIiwxOSwyOCwiciIsIm1pZHNpemUiCiIxMTYiLCJoeXVuZGFpIiwidGlidXJvbiIsMiwxOTk5LDQsImF1dG8obDQpIiwiZiIsMTksMjYsInIiLCJzdWJjb21wYWN0IgoiMTE3IiwiaHl1bmRhaSIsInRpYnVyb24iLDIsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMTksMjksInIiLCJzdWJjb21wYWN0IgoiMTE4IiwiaHl1bmRhaSIsInRpYnVyb24iLDIsMjAwOCw0LCJtYW51YWwobTUpIiwiZiIsMjAsMjgsInIiLCJzdWJjb21wYWN0IgoiMTE5IiwiaHl1bmRhaSIsInRpYnVyb24iLDIsMjAwOCw0LCJhdXRvKGw0KSIsImYiLDIwLDI3LCJyIiwic3ViY29tcGFjdCIKIjEyMCIsImh5dW5kYWkiLCJ0aWJ1cm9uIiwyLjcsMjAwOCw2LCJhdXRvKGw0KSIsImYiLDE3LDI0LCJyIiwic3ViY29tcGFjdCIKIjEyMSIsImh5dW5kYWkiLCJ0aWJ1cm9uIiwyLjcsMjAwOCw2LCJtYW51YWwobTYpIiwiZiIsMTYsMjQsInIiLCJzdWJjb21wYWN0IgoiMTIyIiwiaHl1bmRhaSIsInRpYnVyb24iLDIuNywyMDA4LDYsIm1hbnVhbChtNSkiLCJmIiwxNywyNCwiciIsInN1YmNvbXBhY3QiCiIxMjMiLCJqZWVwIiwiZ3JhbmQgY2hlcm9rZWUgNHdkIiwzLDIwMDgsNiwiYXV0byhsNSkiLCI0IiwxNywyMiwiZCIsInN1diIKIjEyNCIsImplZXAiLCJncmFuZCBjaGVyb2tlZSA0d2QiLDMuNywyMDA4LDYsImF1dG8obDUpIiwiNCIsMTUsMTksInIiLCJzdXYiCiIxMjUiLCJqZWVwIiwiZ3JhbmQgY2hlcm9rZWUgNHdkIiw0LDE5OTksNiwiYXV0byhsNCkiLCI0IiwxNSwyMCwiciIsInN1diIKIjEyNiIsImplZXAiLCJncmFuZCBjaGVyb2tlZSA0d2QiLDQuNywxOTk5LDgsImF1dG8obDQpIiwiNCIsMTQsMTcsInIiLCJzdXYiCiIxMjciLCJqZWVwIiwiZ3JhbmQgY2hlcm9rZWUgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDksMTIsImUiLCJzdXYiCiIxMjgiLCJqZWVwIiwiZ3JhbmQgY2hlcm9rZWUgNHdkIiw0LjcsMjAwOCw4LCJhdXRvKGw1KSIsIjQiLDE0LDE5LCJyIiwic3V2IgoiMTI5IiwiamVlcCIsImdyYW5kIGNoZXJva2VlIDR3ZCIsNS43LDIwMDgsOCwiYXV0byhsNSkiLCI0IiwxMywxOCwiciIsInN1diIKIjEzMCIsImplZXAiLCJncmFuZCBjaGVyb2tlZSA0d2QiLDYuMSwyMDA4LDgsImF1dG8obDUpIiwiNCIsMTEsMTQsInAiLCJzdXYiCiIxMzEiLCJsYW5kIHJvdmVyIiwicmFuZ2Ugcm92ZXIiLDQsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE1LCJwIiwic3V2IgoiMTMyIiwibGFuZCByb3ZlciIsInJhbmdlIHJvdmVyIiw0LjIsMjAwOCw4LCJhdXRvKHM2KSIsIjQiLDEyLDE4LCJyIiwic3V2IgoiMTMzIiwibGFuZCByb3ZlciIsInJhbmdlIHJvdmVyIiw0LjQsMjAwOCw4LCJhdXRvKHM2KSIsIjQiLDEyLDE4LCJyIiwic3V2IgoiMTM0IiwibGFuZCByb3ZlciIsInJhbmdlIHJvdmVyIiw0LjYsMTk5OSw4LCJhdXRvKGw0KSIsIjQiLDExLDE1LCJwIiwic3V2IgoiMTM1IiwibGluY29sbiIsIm5hdmlnYXRvciAyd2QiLDUuNCwxOTk5LDgsImF1dG8obDQpIiwiciIsMTEsMTcsInIiLCJzdXYiCiIxMzYiLCJsaW5jb2xuIiwibmF2aWdhdG9yIDJ3ZCIsNS40LDE5OTksOCwiYXV0byhsNCkiLCJyIiwxMSwxNiwicCIsInN1diIKIjEzNyIsImxpbmNvbG4iLCJuYXZpZ2F0b3IgMndkIiw1LjQsMjAwOCw4LCJhdXRvKGw2KSIsInIiLDEyLDE4LCJyIiwic3V2IgoiMTM4IiwibWVyY3VyeSIsIm1vdW50YWluZWVyIDR3ZCIsNCwxOTk5LDYsImF1dG8obDUpIiwiNCIsMTQsMTcsInIiLCJzdXYiCiIxMzkiLCJtZXJjdXJ5IiwibW91bnRhaW5lZXIgNHdkIiw0LDIwMDgsNiwiYXV0byhsNSkiLCI0IiwxMywxOSwiciIsInN1diIKIjE0MCIsIm1lcmN1cnkiLCJtb3VudGFpbmVlciA0d2QiLDQuNiwyMDA4LDgsImF1dG8obDYpIiwiNCIsMTMsMTksInIiLCJzdXYiCiIxNDEiLCJtZXJjdXJ5IiwibW91bnRhaW5lZXIgNHdkIiw1LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMywxNywiciIsInN1diIKIjE0MiIsIm5pc3NhbiIsImFsdGltYSIsMi40LDE5OTksNCwibWFudWFsKG01KSIsImYiLDIxLDI5LCJyIiwiY29tcGFjdCIKIjE0MyIsIm5pc3NhbiIsImFsdGltYSIsMi40LDE5OTksNCwiYXV0byhsNCkiLCJmIiwxOSwyNywiciIsImNvbXBhY3QiCiIxNDQiLCJuaXNzYW4iLCJhbHRpbWEiLDIuNSwyMDA4LDQsImF1dG8oYXYpIiwiZiIsMjMsMzEsInIiLCJtaWRzaXplIgoiMTQ1Iiwibmlzc2FuIiwiYWx0aW1hIiwyLjUsMjAwOCw0LCJtYW51YWwobTYpIiwiZiIsMjMsMzIsInIiLCJtaWRzaXplIgoiMTQ2Iiwibmlzc2FuIiwiYWx0aW1hIiwzLjUsMjAwOCw2LCJtYW51YWwobTYpIiwiZiIsMTksMjcsInAiLCJtaWRzaXplIgoiMTQ3Iiwibmlzc2FuIiwiYWx0aW1hIiwzLjUsMjAwOCw2LCJhdXRvKGF2KSIsImYiLDE5LDI2LCJwIiwibWlkc2l6ZSIKIjE0OCIsIm5pc3NhbiIsIm1heGltYSIsMywxOTk5LDYsImF1dG8obDQpIiwiZiIsMTgsMjYsInIiLCJtaWRzaXplIgoiMTQ5Iiwibmlzc2FuIiwibWF4aW1hIiwzLDE5OTksNiwibWFudWFsKG01KSIsImYiLDE5LDI1LCJyIiwibWlkc2l6ZSIKIjE1MCIsIm5pc3NhbiIsIm1heGltYSIsMy41LDIwMDgsNiwiYXV0byhhdikiLCJmIiwxOSwyNSwicCIsIm1pZHNpemUiCiIxNTEiLCJuaXNzYW4iLCJwYXRoZmluZGVyIDR3ZCIsMy4zLDE5OTksNiwiYXV0byhsNCkiLCI0IiwxNCwxNywiciIsInN1diIKIjE1MiIsIm5pc3NhbiIsInBhdGhmaW5kZXIgNHdkIiwzLjMsMTk5OSw2LCJtYW51YWwobTUpIiwiNCIsMTUsMTcsInIiLCJzdXYiCiIxNTMiLCJuaXNzYW4iLCJwYXRoZmluZGVyIDR3ZCIsNCwyMDA4LDYsImF1dG8obDUpIiwiNCIsMTQsMjAsInAiLCJzdXYiCiIxNTQiLCJuaXNzYW4iLCJwYXRoZmluZGVyIDR3ZCIsNS42LDIwMDgsOCwiYXV0byhzNSkiLCI0IiwxMiwxOCwicCIsInN1diIKIjE1NSIsInBvbnRpYWMiLCJncmFuZCBwcml4IiwzLjEsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE4LDI2LCJyIiwibWlkc2l6ZSIKIjE1NiIsInBvbnRpYWMiLCJncmFuZCBwcml4IiwzLjgsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE2LDI2LCJwIiwibWlkc2l6ZSIKIjE1NyIsInBvbnRpYWMiLCJncmFuZCBwcml4IiwzLjgsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE3LDI3LCJyIiwibWlkc2l6ZSIKIjE1OCIsInBvbnRpYWMiLCJncmFuZCBwcml4IiwzLjgsMjAwOCw2LCJhdXRvKGw0KSIsImYiLDE4LDI4LCJyIiwibWlkc2l6ZSIKIjE1OSIsInBvbnRpYWMiLCJncmFuZCBwcml4Iiw1LjMsMjAwOCw4LCJhdXRvKHM0KSIsImYiLDE2LDI1LCJwIiwibWlkc2l6ZSIKIjE2MCIsInN1YmFydSIsImZvcmVzdGVyIGF3ZCIsMi41LDE5OTksNCwibWFudWFsKG01KSIsIjQiLDE4LDI1LCJyIiwic3V2IgoiMTYxIiwic3ViYXJ1IiwiZm9yZXN0ZXIgYXdkIiwyLjUsMTk5OSw0LCJhdXRvKGw0KSIsIjQiLDE4LDI0LCJyIiwic3V2IgoiMTYyIiwic3ViYXJ1IiwiZm9yZXN0ZXIgYXdkIiwyLjUsMjAwOCw0LCJtYW51YWwobTUpIiwiNCIsMjAsMjcsInIiLCJzdXYiCiIxNjMiLCJzdWJhcnUiLCJmb3Jlc3RlciBhd2QiLDIuNSwyMDA4LDQsIm1hbnVhbChtNSkiLCI0IiwxOSwyNSwicCIsInN1diIKIjE2NCIsInN1YmFydSIsImZvcmVzdGVyIGF3ZCIsMi41LDIwMDgsNCwiYXV0byhsNCkiLCI0IiwyMCwyNiwiciIsInN1diIKIjE2NSIsInN1YmFydSIsImZvcmVzdGVyIGF3ZCIsMi41LDIwMDgsNCwiYXV0byhsNCkiLCI0IiwxOCwyMywicCIsInN1diIKIjE2NiIsInN1YmFydSIsImltcHJlemEgYXdkIiwyLjIsMTk5OSw0LCJhdXRvKGw0KSIsIjQiLDIxLDI2LCJyIiwic3ViY29tcGFjdCIKIjE2NyIsInN1YmFydSIsImltcHJlemEgYXdkIiwyLjIsMTk5OSw0LCJtYW51YWwobTUpIiwiNCIsMTksMjYsInIiLCJzdWJjb21wYWN0IgoiMTY4Iiwic3ViYXJ1IiwiaW1wcmV6YSBhd2QiLDIuNSwxOTk5LDQsIm1hbnVhbChtNSkiLCI0IiwxOSwyNiwiciIsInN1YmNvbXBhY3QiCiIxNjkiLCJzdWJhcnUiLCJpbXByZXphIGF3ZCIsMi41LDE5OTksNCwiYXV0byhsNCkiLCI0IiwxOSwyNiwiciIsInN1YmNvbXBhY3QiCiIxNzAiLCJzdWJhcnUiLCJpbXByZXphIGF3ZCIsMi41LDIwMDgsNCwiYXV0byhzNCkiLCI0IiwyMCwyNSwicCIsImNvbXBhY3QiCiIxNzEiLCJzdWJhcnUiLCJpbXByZXphIGF3ZCIsMi41LDIwMDgsNCwiYXV0byhzNCkiLCI0IiwyMCwyNywiciIsImNvbXBhY3QiCiIxNzIiLCJzdWJhcnUiLCJpbXByZXphIGF3ZCIsMi41LDIwMDgsNCwibWFudWFsKG01KSIsIjQiLDE5LDI1LCJwIiwiY29tcGFjdCIKIjE3MyIsInN1YmFydSIsImltcHJlemEgYXdkIiwyLjUsMjAwOCw0LCJtYW51YWwobTUpIiwiNCIsMjAsMjcsInIiLCJjb21wYWN0IgoiMTc0IiwidG95b3RhIiwiNHJ1bm5lciA0d2QiLDIuNywxOTk5LDQsIm1hbnVhbChtNSkiLCI0IiwxNSwyMCwiciIsInN1diIKIjE3NSIsInRveW90YSIsIjRydW5uZXIgNHdkIiwyLjcsMTk5OSw0LCJhdXRvKGw0KSIsIjQiLDE2LDIwLCJyIiwic3V2IgoiMTc2IiwidG95b3RhIiwiNHJ1bm5lciA0d2QiLDMuNCwxOTk5LDYsImF1dG8obDQpIiwiNCIsMTUsMTksInIiLCJzdXYiCiIxNzciLCJ0b3lvdGEiLCI0cnVubmVyIDR3ZCIsMy40LDE5OTksNiwibWFudWFsKG01KSIsIjQiLDE1LDE3LCJyIiwic3V2IgoiMTc4IiwidG95b3RhIiwiNHJ1bm5lciA0d2QiLDQsMjAwOCw2LCJhdXRvKGw1KSIsIjQiLDE2LDIwLCJyIiwic3V2IgoiMTc5IiwidG95b3RhIiwiNHJ1bm5lciA0d2QiLDQuNywyMDA4LDgsImF1dG8obDUpIiwiNCIsMTQsMTcsInIiLCJzdXYiCiIxODAiLCJ0b3lvdGEiLCJjYW1yeSIsMi4yLDE5OTksNCwibWFudWFsKG01KSIsImYiLDIxLDI5LCJyIiwibWlkc2l6ZSIKIjE4MSIsInRveW90YSIsImNhbXJ5IiwyLjIsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDIxLDI3LCJyIiwibWlkc2l6ZSIKIjE4MiIsInRveW90YSIsImNhbXJ5IiwyLjQsMjAwOCw0LCJtYW51YWwobTUpIiwiZiIsMjEsMzEsInIiLCJtaWRzaXplIgoiMTgzIiwidG95b3RhIiwiY2FtcnkiLDIuNCwyMDA4LDQsImF1dG8obDUpIiwiZiIsMjEsMzEsInIiLCJtaWRzaXplIgoiMTg0IiwidG95b3RhIiwiY2FtcnkiLDMsMTk5OSw2LCJhdXRvKGw0KSIsImYiLDE4LDI2LCJyIiwibWlkc2l6ZSIKIjE4NSIsInRveW90YSIsImNhbXJ5IiwzLDE5OTksNiwibWFudWFsKG01KSIsImYiLDE4LDI2LCJyIiwibWlkc2l6ZSIKIjE4NiIsInRveW90YSIsImNhbXJ5IiwzLjUsMjAwOCw2LCJhdXRvKHM2KSIsImYiLDE5LDI4LCJyIiwibWlkc2l6ZSIKIjE4NyIsInRveW90YSIsImNhbXJ5IHNvbGFyYSIsMi4yLDE5OTksNCwiYXV0byhsNCkiLCJmIiwyMSwyNywiciIsImNvbXBhY3QiCiIxODgiLCJ0b3lvdGEiLCJjYW1yeSBzb2xhcmEiLDIuMiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyMSwyOSwiciIsImNvbXBhY3QiCiIxODkiLCJ0b3lvdGEiLCJjYW1yeSBzb2xhcmEiLDIuNCwyMDA4LDQsIm1hbnVhbChtNSkiLCJmIiwyMSwzMSwiciIsImNvbXBhY3QiCiIxOTAiLCJ0b3lvdGEiLCJjYW1yeSBzb2xhcmEiLDIuNCwyMDA4LDQsImF1dG8oczUpIiwiZiIsMjIsMzEsInIiLCJjb21wYWN0IgoiMTkxIiwidG95b3RhIiwiY2Ftcnkgc29sYXJhIiwzLDE5OTksNiwiYXV0byhsNCkiLCJmIiwxOCwyNiwiciIsImNvbXBhY3QiCiIxOTIiLCJ0b3lvdGEiLCJjYW1yeSBzb2xhcmEiLDMsMTk5OSw2LCJtYW51YWwobTUpIiwiZiIsMTgsMjYsInIiLCJjb21wYWN0IgoiMTkzIiwidG95b3RhIiwiY2Ftcnkgc29sYXJhIiwzLjMsMjAwOCw2LCJhdXRvKHM1KSIsImYiLDE4LDI3LCJyIiwiY29tcGFjdCIKIjE5NCIsInRveW90YSIsImNvcm9sbGEiLDEuOCwxOTk5LDQsImF1dG8obDMpIiwiZiIsMjQsMzAsInIiLCJjb21wYWN0IgoiMTk1IiwidG95b3RhIiwiY29yb2xsYSIsMS44LDE5OTksNCwiYXV0byhsNCkiLCJmIiwyNCwzMywiciIsImNvbXBhY3QiCiIxOTYiLCJ0b3lvdGEiLCJjb3JvbGxhIiwxLjgsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMjYsMzUsInIiLCJjb21wYWN0IgoiMTk3IiwidG95b3RhIiwiY29yb2xsYSIsMS44LDIwMDgsNCwibWFudWFsKG01KSIsImYiLDI4LDM3LCJyIiwiY29tcGFjdCIKIjE5OCIsInRveW90YSIsImNvcm9sbGEiLDEuOCwyMDA4LDQsImF1dG8obDQpIiwiZiIsMjYsMzUsInIiLCJjb21wYWN0IgoiMTk5IiwidG95b3RhIiwibGFuZCBjcnVpc2VyIHdhZ29uIDR3ZCIsNC43LDE5OTksOCwiYXV0byhsNCkiLCI0IiwxMSwxNSwiciIsInN1diIKIjIwMCIsInRveW90YSIsImxhbmQgY3J1aXNlciB3YWdvbiA0d2QiLDUuNywyMDA4LDgsImF1dG8oczYpIiwiNCIsMTMsMTgsInIiLCJzdXYiCiIyMDEiLCJ0b3lvdGEiLCJ0b3lvdGEgdGFjb21hIDR3ZCIsMi43LDE5OTksNCwibWFudWFsKG01KSIsIjQiLDE1LDIwLCJyIiwicGlja3VwIgoiMjAyIiwidG95b3RhIiwidG95b3RhIHRhY29tYSA0d2QiLDIuNywxOTk5LDQsImF1dG8obDQpIiwiNCIsMTYsMjAsInIiLCJwaWNrdXAiCiIyMDMiLCJ0b3lvdGEiLCJ0b3lvdGEgdGFjb21hIDR3ZCIsMi43LDIwMDgsNCwibWFudWFsKG01KSIsIjQiLDE3LDIyLCJyIiwicGlja3VwIgoiMjA0IiwidG95b3RhIiwidG95b3RhIHRhY29tYSA0d2QiLDMuNCwxOTk5LDYsIm1hbnVhbChtNSkiLCI0IiwxNSwxNywiciIsInBpY2t1cCIKIjIwNSIsInRveW90YSIsInRveW90YSB0YWNvbWEgNHdkIiwzLjQsMTk5OSw2LCJhdXRvKGw0KSIsIjQiLDE1LDE5LCJyIiwicGlja3VwIgoiMjA2IiwidG95b3RhIiwidG95b3RhIHRhY29tYSA0d2QiLDQsMjAwOCw2LCJtYW51YWwobTYpIiwiNCIsMTUsMTgsInIiLCJwaWNrdXAiCiIyMDciLCJ0b3lvdGEiLCJ0b3lvdGEgdGFjb21hIDR3ZCIsNCwyMDA4LDYsImF1dG8obDUpIiwiNCIsMTYsMjAsInIiLCJwaWNrdXAiCiIyMDgiLCJ2b2xrc3dhZ2VuIiwiZ3RpIiwyLDE5OTksNCwibWFudWFsKG01KSIsImYiLDIxLDI5LCJyIiwiY29tcGFjdCIKIjIwOSIsInZvbGtzd2FnZW4iLCJndGkiLDIsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDE5LDI2LCJyIiwiY29tcGFjdCIKIjIxMCIsInZvbGtzd2FnZW4iLCJndGkiLDIsMjAwOCw0LCJtYW51YWwobTYpIiwiZiIsMjEsMjksInAiLCJjb21wYWN0IgoiMjExIiwidm9sa3N3YWdlbiIsImd0aSIsMiwyMDA4LDQsImF1dG8oczYpIiwiZiIsMjIsMjksInAiLCJjb21wYWN0IgoiMjEyIiwidm9sa3N3YWdlbiIsImd0aSIsMi44LDE5OTksNiwibWFudWFsKG01KSIsImYiLDE3LDI0LCJyIiwiY29tcGFjdCIKIjIxMyIsInZvbGtzd2FnZW4iLCJqZXR0YSIsMS45LDE5OTksNCwibWFudWFsKG01KSIsImYiLDMzLDQ0LCJkIiwiY29tcGFjdCIKIjIxNCIsInZvbGtzd2FnZW4iLCJqZXR0YSIsMiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyMSwyOSwiciIsImNvbXBhY3QiCiIyMTUiLCJ2b2xrc3dhZ2VuIiwiamV0dGEiLDIsMTk5OSw0LCJhdXRvKGw0KSIsImYiLDE5LDI2LCJyIiwiY29tcGFjdCIKIjIxNiIsInZvbGtzd2FnZW4iLCJqZXR0YSIsMiwyMDA4LDQsImF1dG8oczYpIiwiZiIsMjIsMjksInAiLCJjb21wYWN0IgoiMjE3Iiwidm9sa3N3YWdlbiIsImpldHRhIiwyLDIwMDgsNCwibWFudWFsKG02KSIsImYiLDIxLDI5LCJwIiwiY29tcGFjdCIKIjIxOCIsInZvbGtzd2FnZW4iLCJqZXR0YSIsMi41LDIwMDgsNSwiYXV0byhzNikiLCJmIiwyMSwyOSwiciIsImNvbXBhY3QiCiIyMTkiLCJ2b2xrc3dhZ2VuIiwiamV0dGEiLDIuNSwyMDA4LDUsIm1hbnVhbChtNSkiLCJmIiwyMSwyOSwiciIsImNvbXBhY3QiCiIyMjAiLCJ2b2xrc3dhZ2VuIiwiamV0dGEiLDIuOCwxOTk5LDYsImF1dG8obDQpIiwiZiIsMTYsMjMsInIiLCJjb21wYWN0IgoiMjIxIiwidm9sa3N3YWdlbiIsImpldHRhIiwyLjgsMTk5OSw2LCJtYW51YWwobTUpIiwiZiIsMTcsMjQsInIiLCJjb21wYWN0IgoiMjIyIiwidm9sa3N3YWdlbiIsIm5ldyBiZWV0bGUiLDEuOSwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwzNSw0NCwiZCIsInN1YmNvbXBhY3QiCiIyMjMiLCJ2b2xrc3dhZ2VuIiwibmV3IGJlZXRsZSIsMS45LDE5OTksNCwiYXV0byhsNCkiLCJmIiwyOSw0MSwiZCIsInN1YmNvbXBhY3QiCiIyMjQiLCJ2b2xrc3dhZ2VuIiwibmV3IGJlZXRsZSIsMiwxOTk5LDQsIm1hbnVhbChtNSkiLCJmIiwyMSwyOSwiciIsInN1YmNvbXBhY3QiCiIyMjUiLCJ2b2xrc3dhZ2VuIiwibmV3IGJlZXRsZSIsMiwxOTk5LDQsImF1dG8obDQpIiwiZiIsMTksMjYsInIiLCJzdWJjb21wYWN0IgoiMjI2Iiwidm9sa3N3YWdlbiIsIm5ldyBiZWV0bGUiLDIuNSwyMDA4LDUsIm1hbnVhbChtNSkiLCJmIiwyMCwyOCwiciIsInN1YmNvbXBhY3QiCiIyMjciLCJ2b2xrc3dhZ2VuIiwibmV3IGJlZXRsZSIsMi41LDIwMDgsNSwiYXV0byhzNikiLCJmIiwyMCwyOSwiciIsInN1YmNvbXBhY3QiCiIyMjgiLCJ2b2xrc3dhZ2VuIiwicGFzc2F0IiwxLjgsMTk5OSw0LCJtYW51YWwobTUpIiwiZiIsMjEsMjksInAiLCJtaWRzaXplIgoiMjI5Iiwidm9sa3N3YWdlbiIsInBhc3NhdCIsMS44LDE5OTksNCwiYXV0byhsNSkiLCJmIiwxOCwyOSwicCIsIm1pZHNpemUiCiIyMzAiLCJ2b2xrc3dhZ2VuIiwicGFzc2F0IiwyLDIwMDgsNCwiYXV0byhzNikiLCJmIiwxOSwyOCwicCIsIm1pZHNpemUiCiIyMzEiLCJ2b2xrc3dhZ2VuIiwicGFzc2F0IiwyLDIwMDgsNCwibWFudWFsKG02KSIsImYiLDIxLDI5LCJwIiwibWlkc2l6ZSIKIjIzMiIsInZvbGtzd2FnZW4iLCJwYXNzYXQiLDIuOCwxOTk5LDYsImF1dG8obDUpIiwiZiIsMTYsMjYsInAiLCJtaWRzaXplIgoiMjMzIiwidm9sa3N3YWdlbiIsInBhc3NhdCIsMi44LDE5OTksNiwibWFudWFsKG01KSIsImYiLDE4LDI2LCJwIiwibWlkc2l6ZSIKIjIzNCIsInZvbGtzd2FnZW4iLCJwYXNzYXQiLDMuNiwyMDA4LDYsImF1dG8oczYpIiwiZiIsMTcsMjYsInAiLCJtaWRzaXplIgo=
In [17]:
# get the decoded content
print(f.decode())
b'"","manufacturer","model","displ","year","cyl","trans","drv","cty","hwy","fl","class"\n"1","audi","a4",1.8,1999,4,"auto(l5)","f",18,29,"p","compact"\n"2","audi","a4",1.8,1999,4,"manual(m5)","f",21,29,"p","compact"\n"3","audi","a4",2,2008,4,"manual(m6)","f",20,31,"p","compact"\n"4","audi","a4",2,2008,4,"auto(av)","f",21,30,"p","compact"\n"5","audi","a4",2.8,1999,6,"auto(l5)","f",16,26,"p","compact"\n"6","audi","a4",2.8,1999,6,"manual(m5)","f",18,26,"p","compact"\n"7","audi","a4",3.1,2008,6,"auto(av)","f",18,27,"p","compact"\n"8","audi","a4 quattro",1.8,1999,4,"manual(m5)","4",18,26,"p","compact"\n"9","audi","a4 quattro",1.8,1999,4,"auto(l5)","4",16,25,"p","compact"\n"10","audi","a4 quattro",2,2008,4,"manual(m6)","4",20,28,"p","compact"\n"11","audi","a4 quattro",2,2008,4,"auto(s6)","4",19,27,"p","compact"\n"12","audi","a4 quattro",2.8,1999,6,"auto(l5)","4",15,25,"p","compact"\n"13","audi","a4 quattro",2.8,1999,6,"manual(m5)","4",17,25,"p","compact"\n"14","audi","a4 quattro",3.1,2008,6,"auto(s6)","4",17,25,"p","compact"\n"15","audi","a4 quattro",3.1,2008,6,"manual(m6)","4",15,25,"p","compact"\n"16","audi","a6 quattro",2.8,1999,6,"auto(l5)","4",15,24,"p","midsize"\n"17","audi","a6 quattro",3.1,2008,6,"auto(s6)","4",17,25,"p","midsize"\n"18","audi","a6 quattro",4.2,2008,8,"auto(s6)","4",16,23,"p","midsize"\n"19","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",14,20,"r","suv"\n"20","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",11,15,"e","suv"\n"21","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",14,20,"r","suv"\n"22","chevrolet","c1500 suburban 2wd",5.7,1999,8,"auto(l4)","r",13,17,"r","suv"\n"23","chevrolet","c1500 suburban 2wd",6,2008,8,"auto(l4)","r",12,17,"r","suv"\n"24","chevrolet","corvette",5.7,1999,8,"manual(m6)","r",16,26,"p","2seater"\n"25","chevrolet","corvette",5.7,1999,8,"auto(l4)","r",15,23,"p","2seater"\n"26","chevrolet","corvette",6.2,2008,8,"manual(m6)","r",16,26,"p","2seater"\n"27","chevrolet","corvette",6.2,2008,8,"auto(s6)","r",15,25,"p","2seater"\n"28","chevrolet","corvette",7,2008,8,"manual(m6)","r",15,24,"p","2seater"\n"29","chevrolet","k1500 tahoe 4wd",5.3,2008,8,"auto(l4)","4",14,19,"r","suv"\n"30","chevrolet","k1500 tahoe 4wd",5.3,2008,8,"auto(l4)","4",11,14,"e","suv"\n"31","chevrolet","k1500 tahoe 4wd",5.7,1999,8,"auto(l4)","4",11,15,"r","suv"\n"32","chevrolet","k1500 tahoe 4wd",6.5,1999,8,"auto(l4)","4",14,17,"d","suv"\n"33","chevrolet","malibu",2.4,1999,4,"auto(l4)","f",19,27,"r","midsize"\n"34","chevrolet","malibu",2.4,2008,4,"auto(l4)","f",22,30,"r","midsize"\n"35","chevrolet","malibu",3.1,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"36","chevrolet","malibu",3.5,2008,6,"auto(l4)","f",18,29,"r","midsize"\n"37","chevrolet","malibu",3.6,2008,6,"auto(s6)","f",17,26,"r","midsize"\n"38","dodge","caravan 2wd",2.4,1999,4,"auto(l3)","f",18,24,"r","minivan"\n"39","dodge","caravan 2wd",3,1999,6,"auto(l4)","f",17,24,"r","minivan"\n"40","dodge","caravan 2wd",3.3,1999,6,"auto(l4)","f",16,22,"r","minivan"\n"41","dodge","caravan 2wd",3.3,1999,6,"auto(l4)","f",16,22,"r","minivan"\n"42","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",17,24,"r","minivan"\n"43","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",17,24,"r","minivan"\n"44","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",11,17,"e","minivan"\n"45","dodge","caravan 2wd",3.8,1999,6,"auto(l4)","f",15,22,"r","minivan"\n"46","dodge","caravan 2wd",3.8,1999,6,"auto(l4)","f",15,21,"r","minivan"\n"47","dodge","caravan 2wd",3.8,2008,6,"auto(l6)","f",16,23,"r","minivan"\n"48","dodge","caravan 2wd",4,2008,6,"auto(l6)","f",16,23,"r","minivan"\n"49","dodge","dakota pickup 4wd",3.7,2008,6,"manual(m6)","4",15,19,"r","pickup"\n"50","dodge","dakota pickup 4wd",3.7,2008,6,"auto(l4)","4",14,18,"r","pickup"\n"51","dodge","dakota pickup 4wd",3.9,1999,6,"auto(l4)","4",13,17,"r","pickup"\n"52","dodge","dakota pickup 4wd",3.9,1999,6,"manual(m5)","4",14,17,"r","pickup"\n"53","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","pickup"\n"54","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","pickup"\n"55","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","pickup"\n"56","dodge","dakota pickup 4wd",5.2,1999,8,"manual(m5)","4",11,17,"r","pickup"\n"57","dodge","dakota pickup 4wd",5.2,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"58","dodge","durango 4wd",3.9,1999,6,"auto(l4)","4",13,17,"r","suv"\n"59","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","suv"\n"60","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","suv"\n"61","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","suv"\n"62","dodge","durango 4wd",5.2,1999,8,"auto(l4)","4",11,16,"r","suv"\n"63","dodge","durango 4wd",5.7,2008,8,"auto(l5)","4",13,18,"r","suv"\n"64","dodge","durango 4wd",5.9,1999,8,"auto(l4)","4",11,15,"r","suv"\n"65","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",12,16,"r","pickup"\n"66","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","pickup"\n"67","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"68","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"69","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",12,16,"r","pickup"\n"70","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",9,12,"e","pickup"\n"71","dodge","ram 1500 pickup 4wd",5.2,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"72","dodge","ram 1500 pickup 4wd",5.2,1999,8,"manual(m5)","4",11,16,"r","pickup"\n"73","dodge","ram 1500 pickup 4wd",5.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"74","dodge","ram 1500 pickup 4wd",5.9,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"75","ford","expedition 2wd",4.6,1999,8,"auto(l4)","r",11,17,"r","suv"\n"76","ford","expedition 2wd",5.4,1999,8,"auto(l4)","r",11,17,"r","suv"\n"77","ford","expedition 2wd",5.4,2008,8,"auto(l6)","r",12,18,"r","suv"\n"78","ford","explorer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"79","ford","explorer 4wd",4,1999,6,"manual(m5)","4",15,19,"r","suv"\n"80","ford","explorer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"81","ford","explorer 4wd",4,2008,6,"auto(l5)","4",13,19,"r","suv"\n"82","ford","explorer 4wd",4.6,2008,8,"auto(l6)","4",13,19,"r","suv"\n"83","ford","explorer 4wd",5,1999,8,"auto(l4)","4",13,17,"r","suv"\n"84","ford","f150 pickup 4wd",4.2,1999,6,"auto(l4)","4",14,17,"r","pickup"\n"85","ford","f150 pickup 4wd",4.2,1999,6,"manual(m5)","4",14,17,"r","pickup"\n"86","ford","f150 pickup 4wd",4.6,1999,8,"manual(m5)","4",13,16,"r","pickup"\n"87","ford","f150 pickup 4wd",4.6,1999,8,"auto(l4)","4",13,16,"r","pickup"\n"88","ford","f150 pickup 4wd",4.6,2008,8,"auto(l4)","4",13,17,"r","pickup"\n"89","ford","f150 pickup 4wd",5.4,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"90","ford","f150 pickup 4wd",5.4,2008,8,"auto(l4)","4",13,17,"r","pickup"\n"91","ford","mustang",3.8,1999,6,"manual(m5)","r",18,26,"r","subcompact"\n"92","ford","mustang",3.8,1999,6,"auto(l4)","r",18,25,"r","subcompact"\n"93","ford","mustang",4,2008,6,"manual(m5)","r",17,26,"r","subcompact"\n"94","ford","mustang",4,2008,6,"auto(l5)","r",16,24,"r","subcompact"\n"95","ford","mustang",4.6,1999,8,"auto(l4)","r",15,21,"r","subcompact"\n"96","ford","mustang",4.6,1999,8,"manual(m5)","r",15,22,"r","subcompact"\n"97","ford","mustang",4.6,2008,8,"manual(m5)","r",15,23,"r","subcompact"\n"98","ford","mustang",4.6,2008,8,"auto(l5)","r",15,22,"r","subcompact"\n"99","ford","mustang",5.4,2008,8,"manual(m6)","r",14,20,"p","subcompact"\n"100","honda","civic",1.6,1999,4,"manual(m5)","f",28,33,"r","subcompact"\n"101","honda","civic",1.6,1999,4,"auto(l4)","f",24,32,"r","subcompact"\n"102","honda","civic",1.6,1999,4,"manual(m5)","f",25,32,"r","subcompact"\n"103","honda","civic",1.6,1999,4,"manual(m5)","f",23,29,"p","subcompact"\n"104","honda","civic",1.6,1999,4,"auto(l4)","f",24,32,"r","subcompact"\n"105","honda","civic",1.8,2008,4,"manual(m5)","f",26,34,"r","subcompact"\n"106","honda","civic",1.8,2008,4,"auto(l5)","f",25,36,"r","subcompact"\n"107","honda","civic",1.8,2008,4,"auto(l5)","f",24,36,"c","subcompact"\n"108","honda","civic",2,2008,4,"manual(m6)","f",21,29,"p","subcompact"\n"109","hyundai","sonata",2.4,1999,4,"auto(l4)","f",18,26,"r","midsize"\n"110","hyundai","sonata",2.4,1999,4,"manual(m5)","f",18,27,"r","midsize"\n"111","hyundai","sonata",2.4,2008,4,"auto(l4)","f",21,30,"r","midsize"\n"112","hyundai","sonata",2.4,2008,4,"manual(m5)","f",21,31,"r","midsize"\n"113","hyundai","sonata",2.5,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"114","hyundai","sonata",2.5,1999,6,"manual(m5)","f",18,26,"r","midsize"\n"115","hyundai","sonata",3.3,2008,6,"auto(l5)","f",19,28,"r","midsize"\n"116","hyundai","tiburon",2,1999,4,"auto(l4)","f",19,26,"r","subcompact"\n"117","hyundai","tiburon",2,1999,4,"manual(m5)","f",19,29,"r","subcompact"\n"118","hyundai","tiburon",2,2008,4,"manual(m5)","f",20,28,"r","subcompact"\n"119","hyundai","tiburon",2,2008,4,"auto(l4)","f",20,27,"r","subcompact"\n"120","hyundai","tiburon",2.7,2008,6,"auto(l4)","f",17,24,"r","subcompact"\n"121","hyundai","tiburon",2.7,2008,6,"manual(m6)","f",16,24,"r","subcompact"\n"122","hyundai","tiburon",2.7,2008,6,"manual(m5)","f",17,24,"r","subcompact"\n"123","jeep","grand cherokee 4wd",3,2008,6,"auto(l5)","4",17,22,"d","suv"\n"124","jeep","grand cherokee 4wd",3.7,2008,6,"auto(l5)","4",15,19,"r","suv"\n"125","jeep","grand cherokee 4wd",4,1999,6,"auto(l4)","4",15,20,"r","suv"\n"126","jeep","grand cherokee 4wd",4.7,1999,8,"auto(l4)","4",14,17,"r","suv"\n"127","jeep","grand cherokee 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","suv"\n"128","jeep","grand cherokee 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","suv"\n"129","jeep","grand cherokee 4wd",5.7,2008,8,"auto(l5)","4",13,18,"r","suv"\n"130","jeep","grand cherokee 4wd",6.1,2008,8,"auto(l5)","4",11,14,"p","suv"\n"131","land rover","range rover",4,1999,8,"auto(l4)","4",11,15,"p","suv"\n"132","land rover","range rover",4.2,2008,8,"auto(s6)","4",12,18,"r","suv"\n"133","land rover","range rover",4.4,2008,8,"auto(s6)","4",12,18,"r","suv"\n"134","land rover","range rover",4.6,1999,8,"auto(l4)","4",11,15,"p","suv"\n"135","lincoln","navigator 2wd",5.4,1999,8,"auto(l4)","r",11,17,"r","suv"\n"136","lincoln","navigator 2wd",5.4,1999,8,"auto(l4)","r",11,16,"p","suv"\n"137","lincoln","navigator 2wd",5.4,2008,8,"auto(l6)","r",12,18,"r","suv"\n"138","mercury","mountaineer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"139","mercury","mountaineer 4wd",4,2008,6,"auto(l5)","4",13,19,"r","suv"\n"140","mercury","mountaineer 4wd",4.6,2008,8,"auto(l6)","4",13,19,"r","suv"\n"141","mercury","mountaineer 4wd",5,1999,8,"auto(l4)","4",13,17,"r","suv"\n"142","nissan","altima",2.4,1999,4,"manual(m5)","f",21,29,"r","compact"\n"143","nissan","altima",2.4,1999,4,"auto(l4)","f",19,27,"r","compact"\n"144","nissan","altima",2.5,2008,4,"auto(av)","f",23,31,"r","midsize"\n"145","nissan","altima",2.5,2008,4,"manual(m6)","f",23,32,"r","midsize"\n"146","nissan","altima",3.5,2008,6,"manual(m6)","f",19,27,"p","midsize"\n"147","nissan","altima",3.5,2008,6,"auto(av)","f",19,26,"p","midsize"\n"148","nissan","maxima",3,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"149","nissan","maxima",3,1999,6,"manual(m5)","f",19,25,"r","midsize"\n"150","nissan","maxima",3.5,2008,6,"auto(av)","f",19,25,"p","midsize"\n"151","nissan","pathfinder 4wd",3.3,1999,6,"auto(l4)","4",14,17,"r","suv"\n"152","nissan","pathfinder 4wd",3.3,1999,6,"manual(m5)","4",15,17,"r","suv"\n"153","nissan","pathfinder 4wd",4,2008,6,"auto(l5)","4",14,20,"p","suv"\n"154","nissan","pathfinder 4wd",5.6,2008,8,"auto(s5)","4",12,18,"p","suv"\n"155","pontiac","grand prix",3.1,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"156","pontiac","grand prix",3.8,1999,6,"auto(l4)","f",16,26,"p","midsize"\n"157","pontiac","grand prix",3.8,1999,6,"auto(l4)","f",17,27,"r","midsize"\n"158","pontiac","grand prix",3.8,2008,6,"auto(l4)","f",18,28,"r","midsize"\n"159","pontiac","grand prix",5.3,2008,8,"auto(s4)","f",16,25,"p","midsize"\n"160","subaru","forester awd",2.5,1999,4,"manual(m5)","4",18,25,"r","suv"\n"161","subaru","forester awd",2.5,1999,4,"auto(l4)","4",18,24,"r","suv"\n"162","subaru","forester awd",2.5,2008,4,"manual(m5)","4",20,27,"r","suv"\n"163","subaru","forester awd",2.5,2008,4,"manual(m5)","4",19,25,"p","suv"\n"164","subaru","forester awd",2.5,2008,4,"auto(l4)","4",20,26,"r","suv"\n"165","subaru","forester awd",2.5,2008,4,"auto(l4)","4",18,23,"p","suv"\n"166","subaru","impreza awd",2.2,1999,4,"auto(l4)","4",21,26,"r","subcompact"\n"167","subaru","impreza awd",2.2,1999,4,"manual(m5)","4",19,26,"r","subcompact"\n"168","subaru","impreza awd",2.5,1999,4,"manual(m5)","4",19,26,"r","subcompact"\n"169","subaru","impreza awd",2.5,1999,4,"auto(l4)","4",19,26,"r","subcompact"\n"170","subaru","impreza awd",2.5,2008,4,"auto(s4)","4",20,25,"p","compact"\n"171","subaru","impreza awd",2.5,2008,4,"auto(s4)","4",20,27,"r","compact"\n"172","subaru","impreza awd",2.5,2008,4,"manual(m5)","4",19,25,"p","compact"\n"173","subaru","impreza awd",2.5,2008,4,"manual(m5)","4",20,27,"r","compact"\n"174","toyota","4runner 4wd",2.7,1999,4,"manual(m5)","4",15,20,"r","suv"\n"175","toyota","4runner 4wd",2.7,1999,4,"auto(l4)","4",16,20,"r","suv"\n"176","toyota","4runner 4wd",3.4,1999,6,"auto(l4)","4",15,19,"r","suv"\n"177","toyota","4runner 4wd",3.4,1999,6,"manual(m5)","4",15,17,"r","suv"\n"178","toyota","4runner 4wd",4,2008,6,"auto(l5)","4",16,20,"r","suv"\n"179","toyota","4runner 4wd",4.7,2008,8,"auto(l5)","4",14,17,"r","suv"\n"180","toyota","camry",2.2,1999,4,"manual(m5)","f",21,29,"r","midsize"\n"181","toyota","camry",2.2,1999,4,"auto(l4)","f",21,27,"r","midsize"\n"182","toyota","camry",2.4,2008,4,"manual(m5)","f",21,31,"r","midsize"\n"183","toyota","camry",2.4,2008,4,"auto(l5)","f",21,31,"r","midsize"\n"184","toyota","camry",3,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"185","toyota","camry",3,1999,6,"manual(m5)","f",18,26,"r","midsize"\n"186","toyota","camry",3.5,2008,6,"auto(s6)","f",19,28,"r","midsize"\n"187","toyota","camry solara",2.2,1999,4,"auto(l4)","f",21,27,"r","compact"\n"188","toyota","camry solara",2.2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"189","toyota","camry solara",2.4,2008,4,"manual(m5)","f",21,31,"r","compact"\n"190","toyota","camry solara",2.4,2008,4,"auto(s5)","f",22,31,"r","compact"\n"191","toyota","camry solara",3,1999,6,"auto(l4)","f",18,26,"r","compact"\n"192","toyota","camry solara",3,1999,6,"manual(m5)","f",18,26,"r","compact"\n"193","toyota","camry solara",3.3,2008,6,"auto(s5)","f",18,27,"r","compact"\n"194","toyota","corolla",1.8,1999,4,"auto(l3)","f",24,30,"r","compact"\n"195","toyota","corolla",1.8,1999,4,"auto(l4)","f",24,33,"r","compact"\n"196","toyota","corolla",1.8,1999,4,"manual(m5)","f",26,35,"r","compact"\n"197","toyota","corolla",1.8,2008,4,"manual(m5)","f",28,37,"r","compact"\n"198","toyota","corolla",1.8,2008,4,"auto(l4)","f",26,35,"r","compact"\n"199","toyota","land cruiser wagon 4wd",4.7,1999,8,"auto(l4)","4",11,15,"r","suv"\n"200","toyota","land cruiser wagon 4wd",5.7,2008,8,"auto(s6)","4",13,18,"r","suv"\n"201","toyota","toyota tacoma 4wd",2.7,1999,4,"manual(m5)","4",15,20,"r","pickup"\n"202","toyota","toyota tacoma 4wd",2.7,1999,4,"auto(l4)","4",16,20,"r","pickup"\n"203","toyota","toyota tacoma 4wd",2.7,2008,4,"manual(m5)","4",17,22,"r","pickup"\n"204","toyota","toyota tacoma 4wd",3.4,1999,6,"manual(m5)","4",15,17,"r","pickup"\n"205","toyota","toyota tacoma 4wd",3.4,1999,6,"auto(l4)","4",15,19,"r","pickup"\n"206","toyota","toyota tacoma 4wd",4,2008,6,"manual(m6)","4",15,18,"r","pickup"\n"207","toyota","toyota tacoma 4wd",4,2008,6,"auto(l5)","4",16,20,"r","pickup"\n"208","volkswagen","gti",2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"209","volkswagen","gti",2,1999,4,"auto(l4)","f",19,26,"r","compact"\n"210","volkswagen","gti",2,2008,4,"manual(m6)","f",21,29,"p","compact"\n"211","volkswagen","gti",2,2008,4,"auto(s6)","f",22,29,"p","compact"\n"212","volkswagen","gti",2.8,1999,6,"manual(m5)","f",17,24,"r","compact"\n"213","volkswagen","jetta",1.9,1999,4,"manual(m5)","f",33,44,"d","compact"\n"214","volkswagen","jetta",2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"215","volkswagen","jetta",2,1999,4,"auto(l4)","f",19,26,"r","compact"\n"216","volkswagen","jetta",2,2008,4,"auto(s6)","f",22,29,"p","compact"\n"217","volkswagen","jetta",2,2008,4,"manual(m6)","f",21,29,"p","compact"\n"218","volkswagen","jetta",2.5,2008,5,"auto(s6)","f",21,29,"r","compact"\n"219","volkswagen","jetta",2.5,2008,5,"manual(m5)","f",21,29,"r","compact"\n"220","volkswagen","jetta",2.8,1999,6,"auto(l4)","f",16,23,"r","compact"\n"221","volkswagen","jetta",2.8,1999,6,"manual(m5)","f",17,24,"r","compact"\n"222","volkswagen","new beetle",1.9,1999,4,"manual(m5)","f",35,44,"d","subcompact"\n"223","volkswagen","new beetle",1.9,1999,4,"auto(l4)","f",29,41,"d","subcompact"\n"224","volkswagen","new beetle",2,1999,4,"manual(m5)","f",21,29,"r","subcompact"\n"225","volkswagen","new beetle",2,1999,4,"auto(l4)","f",19,26,"r","subcompact"\n"226","volkswagen","new beetle",2.5,2008,5,"manual(m5)","f",20,28,"r","subcompact"\n"227","volkswagen","new beetle",2.5,2008,5,"auto(s6)","f",20,29,"r","subcompact"\n"228","volkswagen","passat",1.8,1999,4,"manual(m5)","f",21,29,"p","midsize"\n"229","volkswagen","passat",1.8,1999,4,"auto(l5)","f",18,29,"p","midsize"\n"230","volkswagen","passat",2,2008,4,"auto(s6)","f",19,28,"p","midsize"\n"231","volkswagen","passat",2,2008,4,"manual(m6)","f",21,29,"p","midsize"\n"232","volkswagen","passat",2.8,1999,6,"auto(l5)","f",16,26,"p","midsize"\n"233","volkswagen","passat",2.8,1999,6,"manual(m5)","f",18,26,"p","midsize"\n"234","volkswagen","passat",3.6,2008,6,"auto(s6)","f",17,26,"p","midsize"\n'


Get a raw file:

In [18]:
raw_content = project.files.raw(file_path='mpg.csv', ref='master')
print(raw_content)
b'"","manufacturer","model","displ","year","cyl","trans","drv","cty","hwy","fl","class"\n"1","audi","a4",1.8,1999,4,"auto(l5)","f",18,29,"p","compact"\n"2","audi","a4",1.8,1999,4,"manual(m5)","f",21,29,"p","compact"\n"3","audi","a4",2,2008,4,"manual(m6)","f",20,31,"p","compact"\n"4","audi","a4",2,2008,4,"auto(av)","f",21,30,"p","compact"\n"5","audi","a4",2.8,1999,6,"auto(l5)","f",16,26,"p","compact"\n"6","audi","a4",2.8,1999,6,"manual(m5)","f",18,26,"p","compact"\n"7","audi","a4",3.1,2008,6,"auto(av)","f",18,27,"p","compact"\n"8","audi","a4 quattro",1.8,1999,4,"manual(m5)","4",18,26,"p","compact"\n"9","audi","a4 quattro",1.8,1999,4,"auto(l5)","4",16,25,"p","compact"\n"10","audi","a4 quattro",2,2008,4,"manual(m6)","4",20,28,"p","compact"\n"11","audi","a4 quattro",2,2008,4,"auto(s6)","4",19,27,"p","compact"\n"12","audi","a4 quattro",2.8,1999,6,"auto(l5)","4",15,25,"p","compact"\n"13","audi","a4 quattro",2.8,1999,6,"manual(m5)","4",17,25,"p","compact"\n"14","audi","a4 quattro",3.1,2008,6,"auto(s6)","4",17,25,"p","compact"\n"15","audi","a4 quattro",3.1,2008,6,"manual(m6)","4",15,25,"p","compact"\n"16","audi","a6 quattro",2.8,1999,6,"auto(l5)","4",15,24,"p","midsize"\n"17","audi","a6 quattro",3.1,2008,6,"auto(s6)","4",17,25,"p","midsize"\n"18","audi","a6 quattro",4.2,2008,8,"auto(s6)","4",16,23,"p","midsize"\n"19","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",14,20,"r","suv"\n"20","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",11,15,"e","suv"\n"21","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",14,20,"r","suv"\n"22","chevrolet","c1500 suburban 2wd",5.7,1999,8,"auto(l4)","r",13,17,"r","suv"\n"23","chevrolet","c1500 suburban 2wd",6,2008,8,"auto(l4)","r",12,17,"r","suv"\n"24","chevrolet","corvette",5.7,1999,8,"manual(m6)","r",16,26,"p","2seater"\n"25","chevrolet","corvette",5.7,1999,8,"auto(l4)","r",15,23,"p","2seater"\n"26","chevrolet","corvette",6.2,2008,8,"manual(m6)","r",16,26,"p","2seater"\n"27","chevrolet","corvette",6.2,2008,8,"auto(s6)","r",15,25,"p","2seater"\n"28","chevrolet","corvette",7,2008,8,"manual(m6)","r",15,24,"p","2seater"\n"29","chevrolet","k1500 tahoe 4wd",5.3,2008,8,"auto(l4)","4",14,19,"r","suv"\n"30","chevrolet","k1500 tahoe 4wd",5.3,2008,8,"auto(l4)","4",11,14,"e","suv"\n"31","chevrolet","k1500 tahoe 4wd",5.7,1999,8,"auto(l4)","4",11,15,"r","suv"\n"32","chevrolet","k1500 tahoe 4wd",6.5,1999,8,"auto(l4)","4",14,17,"d","suv"\n"33","chevrolet","malibu",2.4,1999,4,"auto(l4)","f",19,27,"r","midsize"\n"34","chevrolet","malibu",2.4,2008,4,"auto(l4)","f",22,30,"r","midsize"\n"35","chevrolet","malibu",3.1,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"36","chevrolet","malibu",3.5,2008,6,"auto(l4)","f",18,29,"r","midsize"\n"37","chevrolet","malibu",3.6,2008,6,"auto(s6)","f",17,26,"r","midsize"\n"38","dodge","caravan 2wd",2.4,1999,4,"auto(l3)","f",18,24,"r","minivan"\n"39","dodge","caravan 2wd",3,1999,6,"auto(l4)","f",17,24,"r","minivan"\n"40","dodge","caravan 2wd",3.3,1999,6,"auto(l4)","f",16,22,"r","minivan"\n"41","dodge","caravan 2wd",3.3,1999,6,"auto(l4)","f",16,22,"r","minivan"\n"42","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",17,24,"r","minivan"\n"43","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",17,24,"r","minivan"\n"44","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",11,17,"e","minivan"\n"45","dodge","caravan 2wd",3.8,1999,6,"auto(l4)","f",15,22,"r","minivan"\n"46","dodge","caravan 2wd",3.8,1999,6,"auto(l4)","f",15,21,"r","minivan"\n"47","dodge","caravan 2wd",3.8,2008,6,"auto(l6)","f",16,23,"r","minivan"\n"48","dodge","caravan 2wd",4,2008,6,"auto(l6)","f",16,23,"r","minivan"\n"49","dodge","dakota pickup 4wd",3.7,2008,6,"manual(m6)","4",15,19,"r","pickup"\n"50","dodge","dakota pickup 4wd",3.7,2008,6,"auto(l4)","4",14,18,"r","pickup"\n"51","dodge","dakota pickup 4wd",3.9,1999,6,"auto(l4)","4",13,17,"r","pickup"\n"52","dodge","dakota pickup 4wd",3.9,1999,6,"manual(m5)","4",14,17,"r","pickup"\n"53","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","pickup"\n"54","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","pickup"\n"55","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","pickup"\n"56","dodge","dakota pickup 4wd",5.2,1999,8,"manual(m5)","4",11,17,"r","pickup"\n"57","dodge","dakota pickup 4wd",5.2,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"58","dodge","durango 4wd",3.9,1999,6,"auto(l4)","4",13,17,"r","suv"\n"59","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","suv"\n"60","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","suv"\n"61","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","suv"\n"62","dodge","durango 4wd",5.2,1999,8,"auto(l4)","4",11,16,"r","suv"\n"63","dodge","durango 4wd",5.7,2008,8,"auto(l5)","4",13,18,"r","suv"\n"64","dodge","durango 4wd",5.9,1999,8,"auto(l4)","4",11,15,"r","suv"\n"65","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",12,16,"r","pickup"\n"66","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","pickup"\n"67","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"68","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"69","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",12,16,"r","pickup"\n"70","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",9,12,"e","pickup"\n"71","dodge","ram 1500 pickup 4wd",5.2,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"72","dodge","ram 1500 pickup 4wd",5.2,1999,8,"manual(m5)","4",11,16,"r","pickup"\n"73","dodge","ram 1500 pickup 4wd",5.7,2008,8,"auto(l5)","4",13,17,"r","pickup"\n"74","dodge","ram 1500 pickup 4wd",5.9,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"75","ford","expedition 2wd",4.6,1999,8,"auto(l4)","r",11,17,"r","suv"\n"76","ford","expedition 2wd",5.4,1999,8,"auto(l4)","r",11,17,"r","suv"\n"77","ford","expedition 2wd",5.4,2008,8,"auto(l6)","r",12,18,"r","suv"\n"78","ford","explorer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"79","ford","explorer 4wd",4,1999,6,"manual(m5)","4",15,19,"r","suv"\n"80","ford","explorer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"81","ford","explorer 4wd",4,2008,6,"auto(l5)","4",13,19,"r","suv"\n"82","ford","explorer 4wd",4.6,2008,8,"auto(l6)","4",13,19,"r","suv"\n"83","ford","explorer 4wd",5,1999,8,"auto(l4)","4",13,17,"r","suv"\n"84","ford","f150 pickup 4wd",4.2,1999,6,"auto(l4)","4",14,17,"r","pickup"\n"85","ford","f150 pickup 4wd",4.2,1999,6,"manual(m5)","4",14,17,"r","pickup"\n"86","ford","f150 pickup 4wd",4.6,1999,8,"manual(m5)","4",13,16,"r","pickup"\n"87","ford","f150 pickup 4wd",4.6,1999,8,"auto(l4)","4",13,16,"r","pickup"\n"88","ford","f150 pickup 4wd",4.6,2008,8,"auto(l4)","4",13,17,"r","pickup"\n"89","ford","f150 pickup 4wd",5.4,1999,8,"auto(l4)","4",11,15,"r","pickup"\n"90","ford","f150 pickup 4wd",5.4,2008,8,"auto(l4)","4",13,17,"r","pickup"\n"91","ford","mustang",3.8,1999,6,"manual(m5)","r",18,26,"r","subcompact"\n"92","ford","mustang",3.8,1999,6,"auto(l4)","r",18,25,"r","subcompact"\n"93","ford","mustang",4,2008,6,"manual(m5)","r",17,26,"r","subcompact"\n"94","ford","mustang",4,2008,6,"auto(l5)","r",16,24,"r","subcompact"\n"95","ford","mustang",4.6,1999,8,"auto(l4)","r",15,21,"r","subcompact"\n"96","ford","mustang",4.6,1999,8,"manual(m5)","r",15,22,"r","subcompact"\n"97","ford","mustang",4.6,2008,8,"manual(m5)","r",15,23,"r","subcompact"\n"98","ford","mustang",4.6,2008,8,"auto(l5)","r",15,22,"r","subcompact"\n"99","ford","mustang",5.4,2008,8,"manual(m6)","r",14,20,"p","subcompact"\n"100","honda","civic",1.6,1999,4,"manual(m5)","f",28,33,"r","subcompact"\n"101","honda","civic",1.6,1999,4,"auto(l4)","f",24,32,"r","subcompact"\n"102","honda","civic",1.6,1999,4,"manual(m5)","f",25,32,"r","subcompact"\n"103","honda","civic",1.6,1999,4,"manual(m5)","f",23,29,"p","subcompact"\n"104","honda","civic",1.6,1999,4,"auto(l4)","f",24,32,"r","subcompact"\n"105","honda","civic",1.8,2008,4,"manual(m5)","f",26,34,"r","subcompact"\n"106","honda","civic",1.8,2008,4,"auto(l5)","f",25,36,"r","subcompact"\n"107","honda","civic",1.8,2008,4,"auto(l5)","f",24,36,"c","subcompact"\n"108","honda","civic",2,2008,4,"manual(m6)","f",21,29,"p","subcompact"\n"109","hyundai","sonata",2.4,1999,4,"auto(l4)","f",18,26,"r","midsize"\n"110","hyundai","sonata",2.4,1999,4,"manual(m5)","f",18,27,"r","midsize"\n"111","hyundai","sonata",2.4,2008,4,"auto(l4)","f",21,30,"r","midsize"\n"112","hyundai","sonata",2.4,2008,4,"manual(m5)","f",21,31,"r","midsize"\n"113","hyundai","sonata",2.5,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"114","hyundai","sonata",2.5,1999,6,"manual(m5)","f",18,26,"r","midsize"\n"115","hyundai","sonata",3.3,2008,6,"auto(l5)","f",19,28,"r","midsize"\n"116","hyundai","tiburon",2,1999,4,"auto(l4)","f",19,26,"r","subcompact"\n"117","hyundai","tiburon",2,1999,4,"manual(m5)","f",19,29,"r","subcompact"\n"118","hyundai","tiburon",2,2008,4,"manual(m5)","f",20,28,"r","subcompact"\n"119","hyundai","tiburon",2,2008,4,"auto(l4)","f",20,27,"r","subcompact"\n"120","hyundai","tiburon",2.7,2008,6,"auto(l4)","f",17,24,"r","subcompact"\n"121","hyundai","tiburon",2.7,2008,6,"manual(m6)","f",16,24,"r","subcompact"\n"122","hyundai","tiburon",2.7,2008,6,"manual(m5)","f",17,24,"r","subcompact"\n"123","jeep","grand cherokee 4wd",3,2008,6,"auto(l5)","4",17,22,"d","suv"\n"124","jeep","grand cherokee 4wd",3.7,2008,6,"auto(l5)","4",15,19,"r","suv"\n"125","jeep","grand cherokee 4wd",4,1999,6,"auto(l4)","4",15,20,"r","suv"\n"126","jeep","grand cherokee 4wd",4.7,1999,8,"auto(l4)","4",14,17,"r","suv"\n"127","jeep","grand cherokee 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","suv"\n"128","jeep","grand cherokee 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","suv"\n"129","jeep","grand cherokee 4wd",5.7,2008,8,"auto(l5)","4",13,18,"r","suv"\n"130","jeep","grand cherokee 4wd",6.1,2008,8,"auto(l5)","4",11,14,"p","suv"\n"131","land rover","range rover",4,1999,8,"auto(l4)","4",11,15,"p","suv"\n"132","land rover","range rover",4.2,2008,8,"auto(s6)","4",12,18,"r","suv"\n"133","land rover","range rover",4.4,2008,8,"auto(s6)","4",12,18,"r","suv"\n"134","land rover","range rover",4.6,1999,8,"auto(l4)","4",11,15,"p","suv"\n"135","lincoln","navigator 2wd",5.4,1999,8,"auto(l4)","r",11,17,"r","suv"\n"136","lincoln","navigator 2wd",5.4,1999,8,"auto(l4)","r",11,16,"p","suv"\n"137","lincoln","navigator 2wd",5.4,2008,8,"auto(l6)","r",12,18,"r","suv"\n"138","mercury","mountaineer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"\n"139","mercury","mountaineer 4wd",4,2008,6,"auto(l5)","4",13,19,"r","suv"\n"140","mercury","mountaineer 4wd",4.6,2008,8,"auto(l6)","4",13,19,"r","suv"\n"141","mercury","mountaineer 4wd",5,1999,8,"auto(l4)","4",13,17,"r","suv"\n"142","nissan","altima",2.4,1999,4,"manual(m5)","f",21,29,"r","compact"\n"143","nissan","altima",2.4,1999,4,"auto(l4)","f",19,27,"r","compact"\n"144","nissan","altima",2.5,2008,4,"auto(av)","f",23,31,"r","midsize"\n"145","nissan","altima",2.5,2008,4,"manual(m6)","f",23,32,"r","midsize"\n"146","nissan","altima",3.5,2008,6,"manual(m6)","f",19,27,"p","midsize"\n"147","nissan","altima",3.5,2008,6,"auto(av)","f",19,26,"p","midsize"\n"148","nissan","maxima",3,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"149","nissan","maxima",3,1999,6,"manual(m5)","f",19,25,"r","midsize"\n"150","nissan","maxima",3.5,2008,6,"auto(av)","f",19,25,"p","midsize"\n"151","nissan","pathfinder 4wd",3.3,1999,6,"auto(l4)","4",14,17,"r","suv"\n"152","nissan","pathfinder 4wd",3.3,1999,6,"manual(m5)","4",15,17,"r","suv"\n"153","nissan","pathfinder 4wd",4,2008,6,"auto(l5)","4",14,20,"p","suv"\n"154","nissan","pathfinder 4wd",5.6,2008,8,"auto(s5)","4",12,18,"p","suv"\n"155","pontiac","grand prix",3.1,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"156","pontiac","grand prix",3.8,1999,6,"auto(l4)","f",16,26,"p","midsize"\n"157","pontiac","grand prix",3.8,1999,6,"auto(l4)","f",17,27,"r","midsize"\n"158","pontiac","grand prix",3.8,2008,6,"auto(l4)","f",18,28,"r","midsize"\n"159","pontiac","grand prix",5.3,2008,8,"auto(s4)","f",16,25,"p","midsize"\n"160","subaru","forester awd",2.5,1999,4,"manual(m5)","4",18,25,"r","suv"\n"161","subaru","forester awd",2.5,1999,4,"auto(l4)","4",18,24,"r","suv"\n"162","subaru","forester awd",2.5,2008,4,"manual(m5)","4",20,27,"r","suv"\n"163","subaru","forester awd",2.5,2008,4,"manual(m5)","4",19,25,"p","suv"\n"164","subaru","forester awd",2.5,2008,4,"auto(l4)","4",20,26,"r","suv"\n"165","subaru","forester awd",2.5,2008,4,"auto(l4)","4",18,23,"p","suv"\n"166","subaru","impreza awd",2.2,1999,4,"auto(l4)","4",21,26,"r","subcompact"\n"167","subaru","impreza awd",2.2,1999,4,"manual(m5)","4",19,26,"r","subcompact"\n"168","subaru","impreza awd",2.5,1999,4,"manual(m5)","4",19,26,"r","subcompact"\n"169","subaru","impreza awd",2.5,1999,4,"auto(l4)","4",19,26,"r","subcompact"\n"170","subaru","impreza awd",2.5,2008,4,"auto(s4)","4",20,25,"p","compact"\n"171","subaru","impreza awd",2.5,2008,4,"auto(s4)","4",20,27,"r","compact"\n"172","subaru","impreza awd",2.5,2008,4,"manual(m5)","4",19,25,"p","compact"\n"173","subaru","impreza awd",2.5,2008,4,"manual(m5)","4",20,27,"r","compact"\n"174","toyota","4runner 4wd",2.7,1999,4,"manual(m5)","4",15,20,"r","suv"\n"175","toyota","4runner 4wd",2.7,1999,4,"auto(l4)","4",16,20,"r","suv"\n"176","toyota","4runner 4wd",3.4,1999,6,"auto(l4)","4",15,19,"r","suv"\n"177","toyota","4runner 4wd",3.4,1999,6,"manual(m5)","4",15,17,"r","suv"\n"178","toyota","4runner 4wd",4,2008,6,"auto(l5)","4",16,20,"r","suv"\n"179","toyota","4runner 4wd",4.7,2008,8,"auto(l5)","4",14,17,"r","suv"\n"180","toyota","camry",2.2,1999,4,"manual(m5)","f",21,29,"r","midsize"\n"181","toyota","camry",2.2,1999,4,"auto(l4)","f",21,27,"r","midsize"\n"182","toyota","camry",2.4,2008,4,"manual(m5)","f",21,31,"r","midsize"\n"183","toyota","camry",2.4,2008,4,"auto(l5)","f",21,31,"r","midsize"\n"184","toyota","camry",3,1999,6,"auto(l4)","f",18,26,"r","midsize"\n"185","toyota","camry",3,1999,6,"manual(m5)","f",18,26,"r","midsize"\n"186","toyota","camry",3.5,2008,6,"auto(s6)","f",19,28,"r","midsize"\n"187","toyota","camry solara",2.2,1999,4,"auto(l4)","f",21,27,"r","compact"\n"188","toyota","camry solara",2.2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"189","toyota","camry solara",2.4,2008,4,"manual(m5)","f",21,31,"r","compact"\n"190","toyota","camry solara",2.4,2008,4,"auto(s5)","f",22,31,"r","compact"\n"191","toyota","camry solara",3,1999,6,"auto(l4)","f",18,26,"r","compact"\n"192","toyota","camry solara",3,1999,6,"manual(m5)","f",18,26,"r","compact"\n"193","toyota","camry solara",3.3,2008,6,"auto(s5)","f",18,27,"r","compact"\n"194","toyota","corolla",1.8,1999,4,"auto(l3)","f",24,30,"r","compact"\n"195","toyota","corolla",1.8,1999,4,"auto(l4)","f",24,33,"r","compact"\n"196","toyota","corolla",1.8,1999,4,"manual(m5)","f",26,35,"r","compact"\n"197","toyota","corolla",1.8,2008,4,"manual(m5)","f",28,37,"r","compact"\n"198","toyota","corolla",1.8,2008,4,"auto(l4)","f",26,35,"r","compact"\n"199","toyota","land cruiser wagon 4wd",4.7,1999,8,"auto(l4)","4",11,15,"r","suv"\n"200","toyota","land cruiser wagon 4wd",5.7,2008,8,"auto(s6)","4",13,18,"r","suv"\n"201","toyota","toyota tacoma 4wd",2.7,1999,4,"manual(m5)","4",15,20,"r","pickup"\n"202","toyota","toyota tacoma 4wd",2.7,1999,4,"auto(l4)","4",16,20,"r","pickup"\n"203","toyota","toyota tacoma 4wd",2.7,2008,4,"manual(m5)","4",17,22,"r","pickup"\n"204","toyota","toyota tacoma 4wd",3.4,1999,6,"manual(m5)","4",15,17,"r","pickup"\n"205","toyota","toyota tacoma 4wd",3.4,1999,6,"auto(l4)","4",15,19,"r","pickup"\n"206","toyota","toyota tacoma 4wd",4,2008,6,"manual(m6)","4",15,18,"r","pickup"\n"207","toyota","toyota tacoma 4wd",4,2008,6,"auto(l5)","4",16,20,"r","pickup"\n"208","volkswagen","gti",2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"209","volkswagen","gti",2,1999,4,"auto(l4)","f",19,26,"r","compact"\n"210","volkswagen","gti",2,2008,4,"manual(m6)","f",21,29,"p","compact"\n"211","volkswagen","gti",2,2008,4,"auto(s6)","f",22,29,"p","compact"\n"212","volkswagen","gti",2.8,1999,6,"manual(m5)","f",17,24,"r","compact"\n"213","volkswagen","jetta",1.9,1999,4,"manual(m5)","f",33,44,"d","compact"\n"214","volkswagen","jetta",2,1999,4,"manual(m5)","f",21,29,"r","compact"\n"215","volkswagen","jetta",2,1999,4,"auto(l4)","f",19,26,"r","compact"\n"216","volkswagen","jetta",2,2008,4,"auto(s6)","f",22,29,"p","compact"\n"217","volkswagen","jetta",2,2008,4,"manual(m6)","f",21,29,"p","compact"\n"218","volkswagen","jetta",2.5,2008,5,"auto(s6)","f",21,29,"r","compact"\n"219","volkswagen","jetta",2.5,2008,5,"manual(m5)","f",21,29,"r","compact"\n"220","volkswagen","jetta",2.8,1999,6,"auto(l4)","f",16,23,"r","compact"\n"221","volkswagen","jetta",2.8,1999,6,"manual(m5)","f",17,24,"r","compact"\n"222","volkswagen","new beetle",1.9,1999,4,"manual(m5)","f",35,44,"d","subcompact"\n"223","volkswagen","new beetle",1.9,1999,4,"auto(l4)","f",29,41,"d","subcompact"\n"224","volkswagen","new beetle",2,1999,4,"manual(m5)","f",21,29,"r","subcompact"\n"225","volkswagen","new beetle",2,1999,4,"auto(l4)","f",19,26,"r","subcompact"\n"226","volkswagen","new beetle",2.5,2008,5,"manual(m5)","f",20,28,"r","subcompact"\n"227","volkswagen","new beetle",2.5,2008,5,"auto(s6)","f",20,29,"r","subcompact"\n"228","volkswagen","passat",1.8,1999,4,"manual(m5)","f",21,29,"p","midsize"\n"229","volkswagen","passat",1.8,1999,4,"auto(l5)","f",18,29,"p","midsize"\n"230","volkswagen","passat",2,2008,4,"auto(s6)","f",19,28,"p","midsize"\n"231","volkswagen","passat",2,2008,4,"manual(m6)","f",21,29,"p","midsize"\n"232","volkswagen","passat",2.8,1999,6,"auto(l5)","f",16,26,"p","midsize"\n"233","volkswagen","passat",2.8,1999,6,"manual(m5)","f",18,26,"p","midsize"\n"234","volkswagen","passat",3.6,2008,6,"auto(s6)","f",17,26,"p","midsize"\n'


Extract decoded file.

In [19]:
print(raw_content.decode())
"","manufacturer","model","displ","year","cyl","trans","drv","cty","hwy","fl","class"
"1","audi","a4",1.8,1999,4,"auto(l5)","f",18,29,"p","compact"
"2","audi","a4",1.8,1999,4,"manual(m5)","f",21,29,"p","compact"
"3","audi","a4",2,2008,4,"manual(m6)","f",20,31,"p","compact"
"4","audi","a4",2,2008,4,"auto(av)","f",21,30,"p","compact"
"5","audi","a4",2.8,1999,6,"auto(l5)","f",16,26,"p","compact"
"6","audi","a4",2.8,1999,6,"manual(m5)","f",18,26,"p","compact"
"7","audi","a4",3.1,2008,6,"auto(av)","f",18,27,"p","compact"
"8","audi","a4 quattro",1.8,1999,4,"manual(m5)","4",18,26,"p","compact"
"9","audi","a4 quattro",1.8,1999,4,"auto(l5)","4",16,25,"p","compact"
"10","audi","a4 quattro",2,2008,4,"manual(m6)","4",20,28,"p","compact"
"11","audi","a4 quattro",2,2008,4,"auto(s6)","4",19,27,"p","compact"
"12","audi","a4 quattro",2.8,1999,6,"auto(l5)","4",15,25,"p","compact"
"13","audi","a4 quattro",2.8,1999,6,"manual(m5)","4",17,25,"p","compact"
"14","audi","a4 quattro",3.1,2008,6,"auto(s6)","4",17,25,"p","compact"
"15","audi","a4 quattro",3.1,2008,6,"manual(m6)","4",15,25,"p","compact"
"16","audi","a6 quattro",2.8,1999,6,"auto(l5)","4",15,24,"p","midsize"
"17","audi","a6 quattro",3.1,2008,6,"auto(s6)","4",17,25,"p","midsize"
"18","audi","a6 quattro",4.2,2008,8,"auto(s6)","4",16,23,"p","midsize"
"19","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",14,20,"r","suv"
"20","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",11,15,"e","suv"
"21","chevrolet","c1500 suburban 2wd",5.3,2008,8,"auto(l4)","r",14,20,"r","suv"
"22","chevrolet","c1500 suburban 2wd",5.7,1999,8,"auto(l4)","r",13,17,"r","suv"
"23","chevrolet","c1500 suburban 2wd",6,2008,8,"auto(l4)","r",12,17,"r","suv"
"24","chevrolet","corvette",5.7,1999,8,"manual(m6)","r",16,26,"p","2seater"
"25","chevrolet","corvette",5.7,1999,8,"auto(l4)","r",15,23,"p","2seater"
"26","chevrolet","corvette",6.2,2008,8,"manual(m6)","r",16,26,"p","2seater"
"27","chevrolet","corvette",6.2,2008,8,"auto(s6)","r",15,25,"p","2seater"
"28","chevrolet","corvette",7,2008,8,"manual(m6)","r",15,24,"p","2seater"
"29","chevrolet","k1500 tahoe 4wd",5.3,2008,8,"auto(l4)","4",14,19,"r","suv"
"30","chevrolet","k1500 tahoe 4wd",5.3,2008,8,"auto(l4)","4",11,14,"e","suv"
"31","chevrolet","k1500 tahoe 4wd",5.7,1999,8,"auto(l4)","4",11,15,"r","suv"
"32","chevrolet","k1500 tahoe 4wd",6.5,1999,8,"auto(l4)","4",14,17,"d","suv"
"33","chevrolet","malibu",2.4,1999,4,"auto(l4)","f",19,27,"r","midsize"
"34","chevrolet","malibu",2.4,2008,4,"auto(l4)","f",22,30,"r","midsize"
"35","chevrolet","malibu",3.1,1999,6,"auto(l4)","f",18,26,"r","midsize"
"36","chevrolet","malibu",3.5,2008,6,"auto(l4)","f",18,29,"r","midsize"
"37","chevrolet","malibu",3.6,2008,6,"auto(s6)","f",17,26,"r","midsize"
"38","dodge","caravan 2wd",2.4,1999,4,"auto(l3)","f",18,24,"r","minivan"
"39","dodge","caravan 2wd",3,1999,6,"auto(l4)","f",17,24,"r","minivan"
"40","dodge","caravan 2wd",3.3,1999,6,"auto(l4)","f",16,22,"r","minivan"
"41","dodge","caravan 2wd",3.3,1999,6,"auto(l4)","f",16,22,"r","minivan"
"42","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",17,24,"r","minivan"
"43","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",17,24,"r","minivan"
"44","dodge","caravan 2wd",3.3,2008,6,"auto(l4)","f",11,17,"e","minivan"
"45","dodge","caravan 2wd",3.8,1999,6,"auto(l4)","f",15,22,"r","minivan"
"46","dodge","caravan 2wd",3.8,1999,6,"auto(l4)","f",15,21,"r","minivan"
"47","dodge","caravan 2wd",3.8,2008,6,"auto(l6)","f",16,23,"r","minivan"
"48","dodge","caravan 2wd",4,2008,6,"auto(l6)","f",16,23,"r","minivan"
"49","dodge","dakota pickup 4wd",3.7,2008,6,"manual(m6)","4",15,19,"r","pickup"
"50","dodge","dakota pickup 4wd",3.7,2008,6,"auto(l4)","4",14,18,"r","pickup"
"51","dodge","dakota pickup 4wd",3.9,1999,6,"auto(l4)","4",13,17,"r","pickup"
"52","dodge","dakota pickup 4wd",3.9,1999,6,"manual(m5)","4",14,17,"r","pickup"
"53","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","pickup"
"54","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","pickup"
"55","dodge","dakota pickup 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","pickup"
"56","dodge","dakota pickup 4wd",5.2,1999,8,"manual(m5)","4",11,17,"r","pickup"
"57","dodge","dakota pickup 4wd",5.2,1999,8,"auto(l4)","4",11,15,"r","pickup"
"58","dodge","durango 4wd",3.9,1999,6,"auto(l4)","4",13,17,"r","suv"
"59","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","suv"
"60","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","suv"
"61","dodge","durango 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","suv"
"62","dodge","durango 4wd",5.2,1999,8,"auto(l4)","4",11,16,"r","suv"
"63","dodge","durango 4wd",5.7,2008,8,"auto(l5)","4",13,18,"r","suv"
"64","dodge","durango 4wd",5.9,1999,8,"auto(l4)","4",11,15,"r","suv"
"65","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",12,16,"r","pickup"
"66","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","pickup"
"67","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","pickup"
"68","dodge","ram 1500 pickup 4wd",4.7,2008,8,"auto(l5)","4",13,17,"r","pickup"
"69","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",12,16,"r","pickup"
"70","dodge","ram 1500 pickup 4wd",4.7,2008,8,"manual(m6)","4",9,12,"e","pickup"
"71","dodge","ram 1500 pickup 4wd",5.2,1999,8,"auto(l4)","4",11,15,"r","pickup"
"72","dodge","ram 1500 pickup 4wd",5.2,1999,8,"manual(m5)","4",11,16,"r","pickup"
"73","dodge","ram 1500 pickup 4wd",5.7,2008,8,"auto(l5)","4",13,17,"r","pickup"
"74","dodge","ram 1500 pickup 4wd",5.9,1999,8,"auto(l4)","4",11,15,"r","pickup"
"75","ford","expedition 2wd",4.6,1999,8,"auto(l4)","r",11,17,"r","suv"
"76","ford","expedition 2wd",5.4,1999,8,"auto(l4)","r",11,17,"r","suv"
"77","ford","expedition 2wd",5.4,2008,8,"auto(l6)","r",12,18,"r","suv"
"78","ford","explorer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"
"79","ford","explorer 4wd",4,1999,6,"manual(m5)","4",15,19,"r","suv"
"80","ford","explorer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"
"81","ford","explorer 4wd",4,2008,6,"auto(l5)","4",13,19,"r","suv"
"82","ford","explorer 4wd",4.6,2008,8,"auto(l6)","4",13,19,"r","suv"
"83","ford","explorer 4wd",5,1999,8,"auto(l4)","4",13,17,"r","suv"
"84","ford","f150 pickup 4wd",4.2,1999,6,"auto(l4)","4",14,17,"r","pickup"
"85","ford","f150 pickup 4wd",4.2,1999,6,"manual(m5)","4",14,17,"r","pickup"
"86","ford","f150 pickup 4wd",4.6,1999,8,"manual(m5)","4",13,16,"r","pickup"
"87","ford","f150 pickup 4wd",4.6,1999,8,"auto(l4)","4",13,16,"r","pickup"
"88","ford","f150 pickup 4wd",4.6,2008,8,"auto(l4)","4",13,17,"r","pickup"
"89","ford","f150 pickup 4wd",5.4,1999,8,"auto(l4)","4",11,15,"r","pickup"
"90","ford","f150 pickup 4wd",5.4,2008,8,"auto(l4)","4",13,17,"r","pickup"
"91","ford","mustang",3.8,1999,6,"manual(m5)","r",18,26,"r","subcompact"
"92","ford","mustang",3.8,1999,6,"auto(l4)","r",18,25,"r","subcompact"
"93","ford","mustang",4,2008,6,"manual(m5)","r",17,26,"r","subcompact"
"94","ford","mustang",4,2008,6,"auto(l5)","r",16,24,"r","subcompact"
"95","ford","mustang",4.6,1999,8,"auto(l4)","r",15,21,"r","subcompact"
"96","ford","mustang",4.6,1999,8,"manual(m5)","r",15,22,"r","subcompact"
"97","ford","mustang",4.6,2008,8,"manual(m5)","r",15,23,"r","subcompact"
"98","ford","mustang",4.6,2008,8,"auto(l5)","r",15,22,"r","subcompact"
"99","ford","mustang",5.4,2008,8,"manual(m6)","r",14,20,"p","subcompact"
"100","honda","civic",1.6,1999,4,"manual(m5)","f",28,33,"r","subcompact"
"101","honda","civic",1.6,1999,4,"auto(l4)","f",24,32,"r","subcompact"
"102","honda","civic",1.6,1999,4,"manual(m5)","f",25,32,"r","subcompact"
"103","honda","civic",1.6,1999,4,"manual(m5)","f",23,29,"p","subcompact"
"104","honda","civic",1.6,1999,4,"auto(l4)","f",24,32,"r","subcompact"
"105","honda","civic",1.8,2008,4,"manual(m5)","f",26,34,"r","subcompact"
"106","honda","civic",1.8,2008,4,"auto(l5)","f",25,36,"r","subcompact"
"107","honda","civic",1.8,2008,4,"auto(l5)","f",24,36,"c","subcompact"
"108","honda","civic",2,2008,4,"manual(m6)","f",21,29,"p","subcompact"
"109","hyundai","sonata",2.4,1999,4,"auto(l4)","f",18,26,"r","midsize"
"110","hyundai","sonata",2.4,1999,4,"manual(m5)","f",18,27,"r","midsize"
"111","hyundai","sonata",2.4,2008,4,"auto(l4)","f",21,30,"r","midsize"
"112","hyundai","sonata",2.4,2008,4,"manual(m5)","f",21,31,"r","midsize"
"113","hyundai","sonata",2.5,1999,6,"auto(l4)","f",18,26,"r","midsize"
"114","hyundai","sonata",2.5,1999,6,"manual(m5)","f",18,26,"r","midsize"
"115","hyundai","sonata",3.3,2008,6,"auto(l5)","f",19,28,"r","midsize"
"116","hyundai","tiburon",2,1999,4,"auto(l4)","f",19,26,"r","subcompact"
"117","hyundai","tiburon",2,1999,4,"manual(m5)","f",19,29,"r","subcompact"
"118","hyundai","tiburon",2,2008,4,"manual(m5)","f",20,28,"r","subcompact"
"119","hyundai","tiburon",2,2008,4,"auto(l4)","f",20,27,"r","subcompact"
"120","hyundai","tiburon",2.7,2008,6,"auto(l4)","f",17,24,"r","subcompact"
"121","hyundai","tiburon",2.7,2008,6,"manual(m6)","f",16,24,"r","subcompact"
"122","hyundai","tiburon",2.7,2008,6,"manual(m5)","f",17,24,"r","subcompact"
"123","jeep","grand cherokee 4wd",3,2008,6,"auto(l5)","4",17,22,"d","suv"
"124","jeep","grand cherokee 4wd",3.7,2008,6,"auto(l5)","4",15,19,"r","suv"
"125","jeep","grand cherokee 4wd",4,1999,6,"auto(l4)","4",15,20,"r","suv"
"126","jeep","grand cherokee 4wd",4.7,1999,8,"auto(l4)","4",14,17,"r","suv"
"127","jeep","grand cherokee 4wd",4.7,2008,8,"auto(l5)","4",9,12,"e","suv"
"128","jeep","grand cherokee 4wd",4.7,2008,8,"auto(l5)","4",14,19,"r","suv"
"129","jeep","grand cherokee 4wd",5.7,2008,8,"auto(l5)","4",13,18,"r","suv"
"130","jeep","grand cherokee 4wd",6.1,2008,8,"auto(l5)","4",11,14,"p","suv"
"131","land rover","range rover",4,1999,8,"auto(l4)","4",11,15,"p","suv"
"132","land rover","range rover",4.2,2008,8,"auto(s6)","4",12,18,"r","suv"
"133","land rover","range rover",4.4,2008,8,"auto(s6)","4",12,18,"r","suv"
"134","land rover","range rover",4.6,1999,8,"auto(l4)","4",11,15,"p","suv"
"135","lincoln","navigator 2wd",5.4,1999,8,"auto(l4)","r",11,17,"r","suv"
"136","lincoln","navigator 2wd",5.4,1999,8,"auto(l4)","r",11,16,"p","suv"
"137","lincoln","navigator 2wd",5.4,2008,8,"auto(l6)","r",12,18,"r","suv"
"138","mercury","mountaineer 4wd",4,1999,6,"auto(l5)","4",14,17,"r","suv"
"139","mercury","mountaineer 4wd",4,2008,6,"auto(l5)","4",13,19,"r","suv"
"140","mercury","mountaineer 4wd",4.6,2008,8,"auto(l6)","4",13,19,"r","suv"
"141","mercury","mountaineer 4wd",5,1999,8,"auto(l4)","4",13,17,"r","suv"
"142","nissan","altima",2.4,1999,4,"manual(m5)","f",21,29,"r","compact"
"143","nissan","altima",2.4,1999,4,"auto(l4)","f",19,27,"r","compact"
"144","nissan","altima",2.5,2008,4,"auto(av)","f",23,31,"r","midsize"
"145","nissan","altima",2.5,2008,4,"manual(m6)","f",23,32,"r","midsize"
"146","nissan","altima",3.5,2008,6,"manual(m6)","f",19,27,"p","midsize"
"147","nissan","altima",3.5,2008,6,"auto(av)","f",19,26,"p","midsize"
"148","nissan","maxima",3,1999,6,"auto(l4)","f",18,26,"r","midsize"
"149","nissan","maxima",3,1999,6,"manual(m5)","f",19,25,"r","midsize"
"150","nissan","maxima",3.5,2008,6,"auto(av)","f",19,25,"p","midsize"
"151","nissan","pathfinder 4wd",3.3,1999,6,"auto(l4)","4",14,17,"r","suv"
"152","nissan","pathfinder 4wd",3.3,1999,6,"manual(m5)","4",15,17,"r","suv"
"153","nissan","pathfinder 4wd",4,2008,6,"auto(l5)","4",14,20,"p","suv"
"154","nissan","pathfinder 4wd",5.6,2008,8,"auto(s5)","4",12,18,"p","suv"
"155","pontiac","grand prix",3.1,1999,6,"auto(l4)","f",18,26,"r","midsize"
"156","pontiac","grand prix",3.8,1999,6,"auto(l4)","f",16,26,"p","midsize"
"157","pontiac","grand prix",3.8,1999,6,"auto(l4)","f",17,27,"r","midsize"
"158","pontiac","grand prix",3.8,2008,6,"auto(l4)","f",18,28,"r","midsize"
"159","pontiac","grand prix",5.3,2008,8,"auto(s4)","f",16,25,"p","midsize"
"160","subaru","forester awd",2.5,1999,4,"manual(m5)","4",18,25,"r","suv"
"161","subaru","forester awd",2.5,1999,4,"auto(l4)","4",18,24,"r","suv"
"162","subaru","forester awd",2.5,2008,4,"manual(m5)","4",20,27,"r","suv"
"163","subaru","forester awd",2.5,2008,4,"manual(m5)","4",19,25,"p","suv"
"164","subaru","forester awd",2.5,2008,4,"auto(l4)","4",20,26,"r","suv"
"165","subaru","forester awd",2.5,2008,4,"auto(l4)","4",18,23,"p","suv"
"166","subaru","impreza awd",2.2,1999,4,"auto(l4)","4",21,26,"r","subcompact"
"167","subaru","impreza awd",2.2,1999,4,"manual(m5)","4",19,26,"r","subcompact"
"168","subaru","impreza awd",2.5,1999,4,"manual(m5)","4",19,26,"r","subcompact"
"169","subaru","impreza awd",2.5,1999,4,"auto(l4)","4",19,26,"r","subcompact"
"170","subaru","impreza awd",2.5,2008,4,"auto(s4)","4",20,25,"p","compact"
"171","subaru","impreza awd",2.5,2008,4,"auto(s4)","4",20,27,"r","compact"
"172","subaru","impreza awd",2.5,2008,4,"manual(m5)","4",19,25,"p","compact"
"173","subaru","impreza awd",2.5,2008,4,"manual(m5)","4",20,27,"r","compact"
"174","toyota","4runner 4wd",2.7,1999,4,"manual(m5)","4",15,20,"r","suv"
"175","toyota","4runner 4wd",2.7,1999,4,"auto(l4)","4",16,20,"r","suv"
"176","toyota","4runner 4wd",3.4,1999,6,"auto(l4)","4",15,19,"r","suv"
"177","toyota","4runner 4wd",3.4,1999,6,"manual(m5)","4",15,17,"r","suv"
"178","toyota","4runner 4wd",4,2008,6,"auto(l5)","4",16,20,"r","suv"
"179","toyota","4runner 4wd",4.7,2008,8,"auto(l5)","4",14,17,"r","suv"
"180","toyota","camry",2.2,1999,4,"manual(m5)","f",21,29,"r","midsize"
"181","toyota","camry",2.2,1999,4,"auto(l4)","f",21,27,"r","midsize"
"182","toyota","camry",2.4,2008,4,"manual(m5)","f",21,31,"r","midsize"
"183","toyota","camry",2.4,2008,4,"auto(l5)","f",21,31,"r","midsize"
"184","toyota","camry",3,1999,6,"auto(l4)","f",18,26,"r","midsize"
"185","toyota","camry",3,1999,6,"manual(m5)","f",18,26,"r","midsize"
"186","toyota","camry",3.5,2008,6,"auto(s6)","f",19,28,"r","midsize"
"187","toyota","camry solara",2.2,1999,4,"auto(l4)","f",21,27,"r","compact"
"188","toyota","camry solara",2.2,1999,4,"manual(m5)","f",21,29,"r","compact"
"189","toyota","camry solara",2.4,2008,4,"manual(m5)","f",21,31,"r","compact"
"190","toyota","camry solara",2.4,2008,4,"auto(s5)","f",22,31,"r","compact"
"191","toyota","camry solara",3,1999,6,"auto(l4)","f",18,26,"r","compact"
"192","toyota","camry solara",3,1999,6,"manual(m5)","f",18,26,"r","compact"
"193","toyota","camry solara",3.3,2008,6,"auto(s5)","f",18,27,"r","compact"
"194","toyota","corolla",1.8,1999,4,"auto(l3)","f",24,30,"r","compact"
"195","toyota","corolla",1.8,1999,4,"auto(l4)","f",24,33,"r","compact"
"196","toyota","corolla",1.8,1999,4,"manual(m5)","f",26,35,"r","compact"
"197","toyota","corolla",1.8,2008,4,"manual(m5)","f",28,37,"r","compact"
"198","toyota","corolla",1.8,2008,4,"auto(l4)","f",26,35,"r","compact"
"199","toyota","land cruiser wagon 4wd",4.7,1999,8,"auto(l4)","4",11,15,"r","suv"
"200","toyota","land cruiser wagon 4wd",5.7,2008,8,"auto(s6)","4",13,18,"r","suv"
"201","toyota","toyota tacoma 4wd",2.7,1999,4,"manual(m5)","4",15,20,"r","pickup"
"202","toyota","toyota tacoma 4wd",2.7,1999,4,"auto(l4)","4",16,20,"r","pickup"
"203","toyota","toyota tacoma 4wd",2.7,2008,4,"manual(m5)","4",17,22,"r","pickup"
"204","toyota","toyota tacoma 4wd",3.4,1999,6,"manual(m5)","4",15,17,"r","pickup"
"205","toyota","toyota tacoma 4wd",3.4,1999,6,"auto(l4)","4",15,19,"r","pickup"
"206","toyota","toyota tacoma 4wd",4,2008,6,"manual(m6)","4",15,18,"r","pickup"
"207","toyota","toyota tacoma 4wd",4,2008,6,"auto(l5)","4",16,20,"r","pickup"
"208","volkswagen","gti",2,1999,4,"manual(m5)","f",21,29,"r","compact"
"209","volkswagen","gti",2,1999,4,"auto(l4)","f",19,26,"r","compact"
"210","volkswagen","gti",2,2008,4,"manual(m6)","f",21,29,"p","compact"
"211","volkswagen","gti",2,2008,4,"auto(s6)","f",22,29,"p","compact"
"212","volkswagen","gti",2.8,1999,6,"manual(m5)","f",17,24,"r","compact"
"213","volkswagen","jetta",1.9,1999,4,"manual(m5)","f",33,44,"d","compact"
"214","volkswagen","jetta",2,1999,4,"manual(m5)","f",21,29,"r","compact"
"215","volkswagen","jetta",2,1999,4,"auto(l4)","f",19,26,"r","compact"
"216","volkswagen","jetta",2,2008,4,"auto(s6)","f",22,29,"p","compact"
"217","volkswagen","jetta",2,2008,4,"manual(m6)","f",21,29,"p","compact"
"218","volkswagen","jetta",2.5,2008,5,"auto(s6)","f",21,29,"r","compact"
"219","volkswagen","jetta",2.5,2008,5,"manual(m5)","f",21,29,"r","compact"
"220","volkswagen","jetta",2.8,1999,6,"auto(l4)","f",16,23,"r","compact"
"221","volkswagen","jetta",2.8,1999,6,"manual(m5)","f",17,24,"r","compact"
"222","volkswagen","new beetle",1.9,1999,4,"manual(m5)","f",35,44,"d","subcompact"
"223","volkswagen","new beetle",1.9,1999,4,"auto(l4)","f",29,41,"d","subcompact"
"224","volkswagen","new beetle",2,1999,4,"manual(m5)","f",21,29,"r","subcompact"
"225","volkswagen","new beetle",2,1999,4,"auto(l4)","f",19,26,"r","subcompact"
"226","volkswagen","new beetle",2.5,2008,5,"manual(m5)","f",20,28,"r","subcompact"
"227","volkswagen","new beetle",2.5,2008,5,"auto(s6)","f",20,29,"r","subcompact"
"228","volkswagen","passat",1.8,1999,4,"manual(m5)","f",21,29,"p","midsize"
"229","volkswagen","passat",1.8,1999,4,"auto(l5)","f",18,29,"p","midsize"
"230","volkswagen","passat",2,2008,4,"auto(s6)","f",19,28,"p","midsize"
"231","volkswagen","passat",2,2008,4,"manual(m6)","f",21,29,"p","midsize"
"232","volkswagen","passat",2.8,1999,6,"auto(l5)","f",16,26,"p","midsize"
"233","volkswagen","passat",2.8,1999,6,"manual(m5)","f",18,26,"p","midsize"
"234","volkswagen","passat",3.6,2008,6,"auto(s6)","f",17,26,"p","midsize"


Since I access data from GitLab often, I created the following function and saved it pyGitLab.py in my utils directory and added the path to the directory to PYTHONPATH environment variable for the user.

In [20]:
# Reading single files from GitLab

import gitlab
from io import StringIO, BytesIO

def gl2Str(filepath, projectID,branch='master'):
    # Reading a text-like file
    return gitlab.Gitlab('https://gitlab.com/').projects.get(projectID).files.raw(file_path=filepath, ref=branch).decode()

def gl2StrObj(filepath, projectID,branch='master'):
    # Reading a text-like file as a StringIO object
    return StringIO(gitlab.Gitlab('https://gitlab.com/').projects.get(projectID).files.raw(file_path=filepath, ref=branch).decode())
    
def gl2ByteObj(filepath, projectID,branch='master'):
    # Reading a non-text file as a ByteIO object. Examples: Images, Zip files, etc
    return BytesIO(gitlab.Gitlab('https://gitlab.com/').projects.get(projectID).files.raw(file_path=filepath, ref=branch).decode())

[^top]

Last updated 2020-12-16 15:04:41.099138 IST

Python Basics (notes)

wordcloud

Types and Sequences


Use `type` to return the object's type.
In [1]:
type('This is a string')
Out[1]:
str
In [2]:
type(None)
Out[2]:
NoneType
In [3]:
type(1)
Out[3]:
int
In [4]:
type(1.0)
Out[4]:
float

Tuples are an immutable data structure (cannot be altered).
In [6]:
x = (1, 'a', 2, 'b')
type(x)
Out[6]:
tuple

Lists are a mutable data structure.
In [7]:
x = [1, 'a', 2, 'b']
type(x)
Out[7]:
list

Use `append` to append an object to a list.
In [8]:
x.append(3.3)
print(x)
[1, 'a', 2, 'b', 3.3]

This is an example of how to loop through each item in the list.
In [9]:
for item in x:
    print(item)
1
a
2
b
3.3

Or using the indexing operator:
In [10]:
i=0
while( i != len(x) ):
    print(x[i])
    i = i + 1
1
a
2
b
3.3

Use `+` to concatenate lists.
In [11]:
[1,2] + [3,4]
Out[11]:
[1, 2, 3, 4]

Use `*` to repeat lists.
In [12]:
[1]*3
Out[12]:
[1, 1, 1]

Use the `in` operator to check if something is inside a list.
In [13]:
1 in [1, 2, 3]
Out[13]:
True

Now let's look at strings. Use bracket notation to slice a string.
In [14]:
x = 'This is a string'
print(x[0]) #first character
print(x[0:1]) #first character, but we have explicitly set the end character
print(x[0:2]) #first two characters
T
T
Th

This will return the last element of the string.
In [15]:
x[-1]
Out[15]:
'g'

This will return the slice starting from the 4th element from the end and stopping before the 2nd element from the end.
In [16]:
x[-4:-2]
Out[16]:
'ri'

This is a slice from the beginning of the string and stopping before the 3rd element.
In [17]:
x[:3]
Out[17]:
'Thi'

And this is a slice starting from the 4th element of the string and going all the way to the end.
In [18]:
x[3:]
Out[18]:
's is a string'
In [19]:
firstname = 'Krishnakanth'
lastname = 'Allika'

print(firstname + ' ' + lastname)
print(firstname*3)
print('Krish' in firstname)
Krishnakanth Allika
KrishnakanthKrishnakanthKrishnakanth
True

`split` returns a list of all the words in a string, or a list split on a specific character.
In [20]:
firstname = 'Christopher Eric Hitchens'.split(' ')[0] # [0] selects the first element of the list
lastname = 'Christopher Eric Hitchens'.split(' ')[-1] # [-1] selects the last element of the list
print(firstname)
print(lastname)
Christopher
Hitchens

Make sure you convert objects to strings before concatenating.
In [21]:
'Chris' + 2
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-21-9d01956b24db> in <module>
----> 1 'Chris' + 2

TypeError: can only concatenate str (not "int") to str
In [22]:
'Chris' + str(2)
Out[22]:
'Chris2'

Dictionaries associate keys with values.
In [23]:
x = {'Christopher Hitchens': 'The Missionary Position: Mother Teresa in Theory and Practice',
     'Richard Dawkins': 'The Selfish Gene',
     'Yuval Noah Harari':'Sapiens: A Brief History of Humankind',
     'Douglas Adams':"The Hitchhiker's Guide to the Galaxy"
    }

x['Christopher Hitchens'] # Retrieve a value by using the indexing operator
Out[23]:
'The Missionary Position: Mother Teresa in Theory and Practice'
In [24]:
x['Carl Sagan'] = None
x['Carl Sagan']

Iterate over all of the keys:
In [25]:
for name in x:
    print(x[name])
The Missionary Position: Mother Teresa in Theory and Practice
The Selfish Gene
Sapiens: A Brief History of Humankind
The Hitchhiker's Guide to the Galaxy
None

Iterate over all of the values:
In [26]:
for book in x.values():
    print(book)
The Missionary Position: Mother Teresa in Theory and Practice
The Selfish Gene
Sapiens: A Brief History of Humankind
The Hitchhiker's Guide to the Galaxy
None

Iterate over all of the items in the list:
In [27]:
for name, book in x.items():
    print(name)
    print(book)
Christopher Hitchens
The Missionary Position: Mother Teresa in Theory and Practice
Richard Dawkins
The Selfish Gene
Yuval Noah Harari
Sapiens: A Brief History of Humankind
Douglas Adams
The Hitchhiker's Guide to the Galaxy
Carl Sagan
None

You can unpack a sequence into different variables:
In [28]:
x = ('Richard','Dawkins','Evolutionary Biologist')
fname, lname, profession = x
In [29]:
fname
Out[29]:
'Richard'
In [30]:
lname
Out[30]:
'Dawkins'

Make sure the number of values you are unpacking matches the number of variables being assigned.
In [31]:
x = ('Richard','Dawkins','Evolutionary Biologist','Author')
fname, lname, profession = x
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-31-4d9d585aa37c> in <module>
      1 x = ('Richard','Dawkins','Evolutionary Biologist','Author')
----> 2 fname, lname, profession = x

ValueError: too many values to unpack (expected 3)

Python has a built in method for convenient string formatting.
In [34]:
sales_record = {
'price': 22.50,
'num_items': 3,
'person': 'John'}

sales_statement = '{} bought {} item(s) at a price of {} each for a total of {}'

print(sales_statement.format(sales_record['person'],
                             sales_record['num_items'],
                             sales_record['price'],
                             sales_record['num_items']*sales_record['price']))
John bought 3 item(s) at a price of 22.5 each for a total of 67.5

Dates and Times

In [35]:
import datetime as dt
import time as tm

`time` returns the current time in seconds since the Epoch. (January 1st, 1970)
In [36]:
tm.time()
Out[36]:
1606902428.0856857

Convert the timestamp to datetime.
In [37]:
dtnow = dt.datetime.fromtimestamp(tm.time())
dtnow
Out[37]:
datetime.datetime(2020, 12, 2, 15, 17, 10, 873519)

Handy datetime attributes:
In [38]:
# get year, month, day, etc.from a datetime
dtnow.year, dtnow.month, dtnow.day, dtnow.hour, dtnow.minute, dtnow.second 
Out[38]:
(2020, 12, 2, 15, 17, 10)

`timedelta` is a duration expressing the difference between two dates.
In [39]:
delta = dt.timedelta(days = 100) # create a timedelta of 100 days
delta
Out[39]:
datetime.timedelta(days=100)

`date.today` returns the current local date.
In [40]:
today = dt.date.today()
In [41]:
today - delta # the date 100 days ago
Out[41]:
datetime.date(2020, 8, 24)
In [42]:
today > today-delta # compare dates
Out[42]:
True

Functions

In [43]:
x = 1
y = 2
x + y
Out[43]:
3
In [44]:
y
Out[44]:
2

`add_numbers` is a function that takes two numbers and adds them together.
In [45]:
def add_numbers(x, y):
    return x + y

add_numbers(1, 2)
Out[45]:
3

'add_numbers' updated to take an optional 3rd parameter. Using `print` allows printing of multiple expressions within a single cell.
In [46]:
def add_numbers(x,y,z=None):
    if (z==None):
        return x+y
    else:
        return x+y+z

print(add_numbers(1, 2))
print(add_numbers(1, 2, 3))
3
6

`add_numbers` updated to take an optional flag parameter.
In [47]:
def add_numbers(x, y, z=None, flag=False):
    if (flag):
        print('Flag is true!')
    if (z==None):
        return x + y
    else:
        return x + y + z
    
print(add_numbers(1, 2, flag=True))
Flag is true!
3

Assign function `add_numbers` to variable `a`.
In [48]:
def add_numbers(x,y):
    return x+y

a = add_numbers
a(1,2)
Out[48]:
3

Objects and map()


An example of a class in python:
In [61]:
class Person:
    course = 'Python programming' #a class variable

    def set_name(self, new_name): #a method
        self.name = new_name
    def set_location(self, new_location):
        self.location = new_location
In [63]:
person = Person()
person.set_name('Krishnakanth Allika')
person.set_location('Hyderabad, India')
print('{} lives in {} and is learning {}.'.format(person.name, person.location, person.course))
Krishnakanth Allika lives in Hyderabad, India and is learning Python programming.

Here's an example of mapping the `min` function between two lists.
In [67]:
store1 = [10.00, 11.00, 12.34, 2.34]
store2 = [9.00, 11.10, 12.34, 2.01]
cheapest = map(min, store1, store2)
cheapest
Out[67]:
<map at 0x1ee30f809d0>

Now let's iterate through the map object to see the values.
In [68]:
for item in cheapest:
    print(item)
9.0
11.0
12.34
2.01

Lambda and List Comprehensions


Here's an example of lambda that takes in three parameters and adds the first two.
In [69]:
my_function = lambda a, b, c : a + b
In [70]:
my_function(1, 2, 3)
Out[70]:
3

Let's iterate from 0 to 999 and return the even numbers.
In [72]:
my_list = []
for number in range(0, 1000):
    if number % 2 == 0:
        my_list.append(number)
print(my_list)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 570, 572, 574, 576, 578, 580, 582, 584, 586, 588, 590, 592, 594, 596, 598, 600, 602, 604, 606, 608, 610, 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, 640, 642, 644, 646, 648, 650, 652, 654, 656, 658, 660, 662, 664, 666, 668, 670, 672, 674, 676, 678, 680, 682, 684, 686, 688, 690, 692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724, 726, 728, 730, 732, 734, 736, 738, 740, 742, 744, 746, 748, 750, 752, 754, 756, 758, 760, 762, 764, 766, 768, 770, 772, 774, 776, 778, 780, 782, 784, 786, 788, 790, 792, 794, 796, 798, 800, 802, 804, 806, 808, 810, 812, 814, 816, 818, 820, 822, 824, 826, 828, 830, 832, 834, 836, 838, 840, 842, 844, 846, 848, 850, 852, 854, 856, 858, 860, 862, 864, 866, 868, 870, 872, 874, 876, 878, 880, 882, 884, 886, 888, 890, 892, 894, 896, 898, 900, 902, 904, 906, 908, 910, 912, 914, 916, 918, 920, 922, 924, 926, 928, 930, 932, 934, 936, 938, 940, 942, 944, 946, 948, 950, 952, 954, 956, 958, 960, 962, 964, 966, 968, 970, 972, 974, 976, 978, 980, 982, 984, 986, 988, 990, 992, 994, 996, 998]

Now the same thing but with list comprehension.
In [73]:
my_list = [number for number in range(0,1000) if number % 2 == 0]
print(my_list)
[0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52, 54, 56, 58, 60, 62, 64, 66, 68, 70, 72, 74, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 98, 100, 102, 104, 106, 108, 110, 112, 114, 116, 118, 120, 122, 124, 126, 128, 130, 132, 134, 136, 138, 140, 142, 144, 146, 148, 150, 152, 154, 156, 158, 160, 162, 164, 166, 168, 170, 172, 174, 176, 178, 180, 182, 184, 186, 188, 190, 192, 194, 196, 198, 200, 202, 204, 206, 208, 210, 212, 214, 216, 218, 220, 222, 224, 226, 228, 230, 232, 234, 236, 238, 240, 242, 244, 246, 248, 250, 252, 254, 256, 258, 260, 262, 264, 266, 268, 270, 272, 274, 276, 278, 280, 282, 284, 286, 288, 290, 292, 294, 296, 298, 300, 302, 304, 306, 308, 310, 312, 314, 316, 318, 320, 322, 324, 326, 328, 330, 332, 334, 336, 338, 340, 342, 344, 346, 348, 350, 352, 354, 356, 358, 360, 362, 364, 366, 368, 370, 372, 374, 376, 378, 380, 382, 384, 386, 388, 390, 392, 394, 396, 398, 400, 402, 404, 406, 408, 410, 412, 414, 416, 418, 420, 422, 424, 426, 428, 430, 432, 434, 436, 438, 440, 442, 444, 446, 448, 450, 452, 454, 456, 458, 460, 462, 464, 466, 468, 470, 472, 474, 476, 478, 480, 482, 484, 486, 488, 490, 492, 494, 496, 498, 500, 502, 504, 506, 508, 510, 512, 514, 516, 518, 520, 522, 524, 526, 528, 530, 532, 534, 536, 538, 540, 542, 544, 546, 548, 550, 552, 554, 556, 558, 560, 562, 564, 566, 568, 570, 572, 574, 576, 578, 580, 582, 584, 586, 588, 590, 592, 594, 596, 598, 600, 602, 604, 606, 608, 610, 612, 614, 616, 618, 620, 622, 624, 626, 628, 630, 632, 634, 636, 638, 640, 642, 644, 646, 648, 650, 652, 654, 656, 658, 660, 662, 664, 666, 668, 670, 672, 674, 676, 678, 680, 682, 684, 686, 688, 690, 692, 694, 696, 698, 700, 702, 704, 706, 708, 710, 712, 714, 716, 718, 720, 722, 724, 726, 728, 730, 732, 734, 736, 738, 740, 742, 744, 746, 748, 750, 752, 754, 756, 758, 760, 762, 764, 766, 768, 770, 772, 774, 776, 778, 780, 782, 784, 786, 788, 790, 792, 794, 796, 798, 800, 802, 804, 806, 808, 810, 812, 814, 816, 818, 820, 822, 824, 826, 828, 830, 832, 834, 836, 838, 840, 842, 844, 846, 848, 850, 852, 854, 856, 858, 860, 862, 864, 866, 868, 870, 872, 874, 876, 878, 880, 882, 884, 886, 888, 890, 892, 894, 896, 898, 900, 902, 904, 906, 908, 910, 912, 914, 916, 918, 920, 922, 924, 926, 928, 930, 932, 934, 936, 938, 940, 942, 944, 946, 948, 950, 952, 954, 956, 958, 960, 962, 964, 966, 968, 970, 972, 974, 976, 978, 980, 982, 984, 986, 988, 990, 992, 994, 996, 998]

Last updated 2020-12-02 15:48:33.869841 IST

Python Class Inheritance - Food & Drinks ordering system

wordcloud

We have already created a simple food ordering system using Python classes here. Let's attempt to improve it by adding an option to order drinks along with food.

Here is the code to the MenuItem class:

In [1]:
class MenuItem:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def info(self):
        return self.name + ': $' + str(self.price)

    def get_total_price(self, count):
        total_price = self.price * count

        if count >= 3:
            total_price *= 0.9

        return round(total_price)

Let's create classes Food and Drink that inherit MenuItem

In [2]:
class Food(MenuItem):
    pass

class Drink(MenuItem):
    pass

Now we create instances of Food and Drink.

In [3]:
# Create an instance of the Food class and assign it to the food1 variable
food1=Food('Sandwich',5)

# Call the info method from food1 and output the return value
print(food1.info())

# Create an instance of the Drink class and assign it to the drink1 variable
drink1=Drink('Coffee',3)

# Call the info method from drink1 and output the return value
print(drink1.info())
Sandwich: $5
Coffee: $3

Let's add an attribute calorie_count to the food1 instance. Also, create a calorie_info method in Food class to display the calorie count.

In [5]:
class Food(MenuItem):
    # Define the calorie_info method
    def calorie_info(self):
        print('kcal: ' + str(self.calorie_count))

food1 = Food('Sandwich', 5)

# Set the calorie_count variable of food1 to 330
food1.calorie_count=330

# Call the calorie_info method from food1
food1.calorie_info()
kcal: 330

Let's add the calorie count to the info method instead to display all information at one place.

In [8]:
class Food(MenuItem):
    # Define the info method
    def info(self):
        return self.name + ': $' + str(self.price) + ' (' + str(self.calorie_count) + 'kcal)'
        
food1 = Food('Sandwich', 5)
food1.calorie_count = 330

# Call the info method from food1 and output the return value
print(food1.info())
Sandwich: $5 (330kcal)

Now add volume to the info method in the Drink class the same way.

In [10]:
class Drink(MenuItem):
    # Define the info method
    def info(self):
        return self.name + ': $' + str(self.price) + ' (' + str(self.volume) + 'mL)'
    
# Create an instance of the Drink class and assign it to the drink1 variable
drink1=Drink('Coffee',3)

# Set the volume variable of drink1 to 180
drink1.volume=180

# Call the info method from drink1 and output the return value
print(drink1.info())
Coffee: $3 (180mL)

We need to be able to assign calorie count while creating an instance. So we need to use the __init__ module like we did in the MenuItem class.

In [12]:
class Food(MenuItem):
    # Define the __init__ method
    def __init__(self,name,price,calorie_count):
        self.name=name
        self.price=price
        self.calorie_count=calorie_count
    
    
    def info(self):
        return self.name + ': $' + str(self.price) + ' (' + str(self.calorie_count) + 'kcal)'
    
    def calorie_info(self):
        print('kcal: ' + str(self.calorie_count))
        
# Add an argument to Food()
food1 = Food('Sandwich', 5, 330)
print(food1.info())
Sandwich: $5 (330kcal)

We already have name and price in the parent class Food. They need not be defined again and can be inherited from the parent class using super().

In [14]:
class Food(MenuItem):
    def __init__(self, name, price, calorie_count):
        # Using super() call __init__() from the parent class
        super().__init__(name,price)
        self.calorie_count = calorie_count
    
    def info(self):
        return self.name + ': $' + str(self.price) + ' (' + str(self.calorie_count) + 'kcal)'
    
    def calorie_info(self):
        print('kcal: ' + str(self.calorie_count))
        
food1 = Food('Sandwich', 5, 330)
print(food1.info())
Sandwich: $5 (330kcal)

Update the Drink class similarly

In [15]:
class Drink(MenuItem):
    # Define the __init__ method
    def __init__(self, name, price, volume):
        super().__init__(name, price)
        self.volume = volume
    
    def info(self):
        return self.name + ': $' + str(self.price) + ' (' + str(self.volume) + 'mL)'

# Add an argument to Drink()
drink1 = Drink('Coffee', 3,180)
print(drink1.info())
Coffee: $3 (180mL)

Now that we have required classes and methods available, let's create instances and write the code to run the program.

In [16]:
food1 = Food('Sandwich', 5, 330)
food2 = Food('Chocolate Cake', 4, 450)
food3 = Food('Cream Puff', 2, 180)

foods = [food1, food2, food3]

drink1 = Drink('Coffee', 3, 180)
drink2 = Drink('Orange Juice', 2, 350)
drink3 = Drink('Espresso', 3, 30)

drinks = [drink1, drink2, drink3]

print('Food')
index = 0
for food in foods:
    print(str(index) + '. ' + food.info())
    index += 1

print('Drinks')
index = 0
for drink in drinks:
    print(str(index) + '. ' + drink.info())
    index += 1

print('--------------------')

food_order = int(input('Enter food item number: '))
selected_food = foods[food_order]

drink_order = int(input('Enter drink item number: '))
selected_drink = drinks[drink_order]

# Take input from the console and assign it to the count variable
count=int(input('How many meals would you like to purchase? (10% off for 3 or more): '))

# Call the get_total_price method from selected_food and from selected_drink
result=selected_food.get_total_price(count)+selected_drink.get_total_price(count)

# Output 'Your total is $____'
print('Your total is $'+str(result))
Food
0. Sandwich: $5 (330kcal)
1. Chocolate Cake: $4 (450kcal)
2. Cream Puff: $2 (180kcal)
Drinks
0. Coffee: $3 (180mL)
1. Orange Juice: $2 (350mL)
2. Espresso: $3 (30mL)
--------------------
Your total is $25

Note: The code on this page is something that I wrote when I took Progate's free Python classes.

Last updated 2020-12-01 17:05:29.094509 IST

Python classes basics - Creating a food menu

wordcloud

This is an example to illustrate the basics of Python classes. We will use classes to create an elementary food ordering menu.

Python classes do not require a constructor like in C or C++. A class can be created without one. Let's create a class MenuItem with nothing in it. We use pass for empty classes.

In [1]:
class MenuItem:
    pass

Let's create an instance of the class MenuItem called menu_item1.

In [2]:
menu_item1 = MenuItem()

Let's create some attributes to this menu_item1 intance like name and price. Notice that this can be done without declaring the attributes in the class.

In [3]:
menu_item1.name = 'Sandwich'
print(menu_item1.name)
menu_item1.price=5
print(menu_item1.price)
Sandwich
5

Let's create another instance of the class MenuItem and assign some variables to it.

In [5]:
# Create an instance of the MenuItem class
menu_item2 = MenuItem()

# Set the name of menu_item2 to 'Chocolate Cake'
menu_item2.name = 'Chocolate Cake'

# Output the name of menu_item2
print(menu_item2.name)

# Set the price of menu_item2 to 4
menu_item2.price = 4

# Output the price of menu_item2
print(menu_item2.price)
Chocolate Cake
4

Methods are functions within classes. Let's create a method info to print something. All methods need to be passed the argument self.

In [6]:
class MenuItem:
    # Define the info method
    def info(self):
        print('Display menu item name and price')

menu_item1 = MenuItem()
menu_item1.name = 'Sandwich'
menu_item1.price = 5

# Call the info method from menu_item1
menu_item1.info()

menu_item2 = MenuItem()
menu_item2.name = 'Chocolate Cake'
menu_item2.price = 4

# Call the info method from menu_item2
menu_item2.info()
Display menu item name and price
Display menu item name and price

Let's modify the method to print specific information about instances like their names and prices.

In [8]:
class MenuItem:
    def info(self):
        # Output in the format '____: $____'
        print(self.name+': $'+str(self.price))


menu_item1 = MenuItem()
menu_item1.name = 'Sandwich'
menu_item1.price = 5

menu_item1.info()

menu_item2 = MenuItem()
menu_item2.name = 'Chocolate Cake'
menu_item2.price = 4

menu_item2.info()
Sandwich: $5
Chocolate Cake: $4

We can also return values from class methods just like any other function.

In [9]:
class MenuItem:
    def info(self):
        # Return the contents of print() as a return value
        return self.name + ': $' + str(self.price)


menu_item1 = MenuItem()
menu_item1.name = 'Sandwich'
menu_item1.price = 5

# Output the value of menu_item1.info()
print(menu_item1.info())

menu_item2 = MenuItem()
menu_item2.name = 'Chocolate Cake'
menu_item2.price = 4

# Output the value of menu_item2.info()
print(menu_item2.info())
Sandwich: $5
Chocolate Cake: $4

Let's pass arguments to methods and perform basic calculations like calculating the total price of the order. Note that the first argument must always be self.

In [10]:
class MenuItem:
    def info(self):
        return self.name + ': $' + str(self.price)

    # Define the get_total_price method
    def get_total_price(self,count):
        total_price=self.price*count
        return total_price


menu_item1 = MenuItem()
menu_item1.name = 'Sandwich'
menu_item1.price = 5

print(menu_item1.info())

# Call the get_total_price method
result=menu_item1.get_total_price(4)

# Output 'Your total is $____'
print('Your total is $'+str(result))
Sandwich: $5
Your total is $20

As mentioned earlier, Python does not require a constructor to be created and we have come so far without it. However, Python has a special function called __init__ that is called each time an instance is created. __init__ is optional and can be used when we need something to be done every time an instance is created.

In [11]:
class MenuItem:
    # Define the __init__ method
    def __init__(self):
        print('An instance of the MenuItem class was created!')

    def info(self):
        return self.name + ': $' + str(self.price)

    def get_total_price(self, count):
        total_price = self.price * count
        return total_price


menu_item1 = MenuItem()
menu_item1.name = 'Sandwich'
menu_item1.price = 5

print(menu_item1.info())

result = menu_item1.get_total_price(4)
print('Your total is $' + str(result))
An instance of the MenuItem class was created!
Sandwich: $5
Your total is $20

For example, let's give a default name and price to an instance when it's created.

In [12]:
class MenuItem:
    def __init__(self):
        # Set self.name to 'Sandwich'
        self.name='Sandwich'        
        # Set self.price to 5
        self.price=5

    def info(self):
        return self.name + ': $' + str(self.price)

    def get_total_price(self, count):
        total_price = self.price * count
        return total_price


menu_item1 = MenuItem()
print(menu_item1.info())

result = menu_item1.get_total_price(4)
print('Your total is $' + str(result))
Sandwich: $5
Your total is $20

However, now every instance has the same name and price. We would like to create intances of food items with different names and prices. Let's do that by passing arguments to the __init__ function.

In [14]:
class MenuItem:
    # Add the parameters name and price
    def __init__(self,name,price):
        # Set this to the name argument instead of 'Sandwich'
        self.name = name
        
        # Set this to the price argument instead of 5
        self.price = price

    def info(self):
        return self.name + ': $' + str(self.price)

    def get_total_price(self, count):
        total_price = self.price * count
        return total_price


menu_item1 = MenuItem('Sandwich', 5)
menu_item2 = MenuItem('Chocolate Cake', 4)
menu_item3 = MenuItem('Coffee', 3)
menu_item4 = MenuItem('Orange Juice', 2)

# Set the menu_items variable to a list of the MenuItem instances
menu_items=[menu_item1, menu_item2, menu_item3, menu_item4]

# Create the for loop
for menu_item in menu_items:
    print(menu_item.info())
Sandwich: $5
Chocolate Cake: $4
Coffee: $3
Orange Juice: $2

Let's print them with index numbers to make it easier for customers to order.

In [16]:
index=0

for menu_item in menu_items:
    # Print out in the format '0. Sandwich: $5' for each index
    print(str(index)+'. '+menu_item.info())
    
    # Add 1 to the index variable
    index+=1
0. Sandwich: $5
1. Chocolate Cake: $4
2. Coffee: $3
3. Orange Juice: $2

Looks almost ready. Let's use the input function to take orders from customers and confirm their order.

In [17]:
# Receive input from the console and assign the order variable to it
order=int(input('Enter menu item number: '))

# Set the selected_menu variable to the menu item that was selected
selected_menu=menu_items[order]

# Output 'Selected item: ____'
print('Selected item: '+selected_menu.name)
Selected item: Coffee

Customers might like to order more than one quantity. Let's add an option to take quantity as an input as well. Also, make it more interesting by throwing in a discount if three or more are ordered.

In [ ]:
class MenuItem:
    def __init__(self, name, price):
        self.name = name
        self.price = price

    def info(self):
        return self.name + ': $' + str(self.price)

    def get_total_price(self, count):
        total_price = self.price * count
        
        # If count is 3 or higher, multiply it by 0.9
        if count>=3:
            total_price=total_price*0.9
        
        # Round total_price to the nearest whole number and return it
        return round(total_price)
    
menu_item1 = MenuItem('Sandwich', 5)
menu_item2 = MenuItem('Chocolate Cake', 4)
menu_item3 = MenuItem('Coffee', 3)
menu_item4 = MenuItem('Orange Juice', 2)

menu_items = [menu_item1, menu_item2, menu_item3, menu_item4]

index = 0

for menu_item in menu_items:
    print(str(index) + '. ' + menu_item.info())
    index += 1

print('--------------------')

order = int(input('Enter menu item number: '))
selected_menu = menu_items[order]
print('Selected item: ' + selected_menu.name)

# Receive input from the console and set the count variable to it
count=int(input('Enter quantity (10% off for 3 or more): '))

# Call the get_total_price method
result=selected_menu.get_total_price(count)

# Output 'Your total is $____'
print('Your total is $'+str(result))

We have succesfully used Python classes to create a very basic food ordering system. The code can be split into multiple files if it's getting too long or if there are multiple people or groups working on different things. For example, the MenuItem class can be moved to a seperate file called menu_item.py and be imported into the main script when needed. Specific classes from this seperate file can be called directly too instead of importing the whole file.

In [20]:
# Importing the MenuItem class from menu_item.py
from menu_item import MenuItem

menu_item1 = MenuItem('Sandwich', 5)
menu_item2 = MenuItem('Chocolate Cake', 4)
menu_item3 = MenuItem('Coffee', 3)
menu_item4 = MenuItem('Orange Juice', 2)

menu_items = [menu_item1, menu_item2, menu_item3, menu_item4]

index = 0

for menu_item in menu_items:
    print(str(index) + '. ' + menu_item.info())
    index += 1

print('--------------------')

order = int(input('Enter menu item number: '))
selected_menu = menu_items[order]
print('Selected item: ' + selected_menu.name)

# Receive input from the console and set the count variable to it
count=int(input('Enter quantity (10% off for 3 or more): '))

# Call the get_total_price method
result=selected_menu.get_total_price(count)

# Output 'Your total is $____'
print('Your total is $'+str(result))
0. Sandwich: $5
1. Chocolate Cake: $4
2. Coffee: $3
3. Orange Juice: $2
--------------------
Selected item: Orange Juice
Your total is $9

An improvement to the above example using inheritence is demostrated here.

Note: The code on this page is something that I wrote when I took Progate's free Python classes.

Last updated 2020-12-01 12:11:36.372057 IST

Python Functions - Rock Paper Scissors game

wordcloud

This is an illustration of basics of Python functions. In this example, we will write a simple Rock-Paper-Scissors using Python functions.

Here is an example of defining a simple function that prints something and how to call the function.

In [1]:
# Define print_hand function
def print_hand():
    print('You picked: Rock')
# Call print_hand function
print_hand()
You picked: Rock

The function above takes no arguments. Let's pass an argument called hand and print it.

In [2]:
# Add a parameter to print_hand
def print_hand(hand):
    # Use the parameter to print 'You picked: ___'
    print('You picked: '+hand)

# Call print_hand with 'Rock'
print_hand('Rock')

# Call print_hand with 'Paper'
print_hand('Paper')
You picked: Rock
You picked: Paper

Now let's pass multiple arguments. While passing more than one argument, the sequence or order of arguments must match with the function definition.

In [3]:
# Add a parameter to print_hand
def print_hand(hand,name):
    # Change the output to '___ picked: ___'
    print(name+' picked: ' + hand)

# Add a second argument to print_hand
print_hand('Rock','Player')

# Add a second argument to print_hand
print_hand('Paper','Computer')
Player picked: Rock
Computer picked: Paper

We can also make some arguments optional be providing them with default values.

In [4]:
# Add a default value for name
def print_hand(hand, name='Guest'):
    print(name + ' picked: ' + hand)

# Add an argument to print_hand
print_hand('Rock')
Guest picked: Rock

Default argument values will be overwritten when their values are passed to the function. Let's input player's name.

In [5]:
# Get input, and then assign it to the player_name variable
player_name=input('Please enter your name: ')
# Add a second argument to print_hand
print_hand('Rock',player_name)
Krishnakanth picked: Rock

Let's add an option to select hand.

In [6]:
def print_hand(hand, name='Guest'):
    # Assign a list of hands to the hands variable
    hands=['Rock','Paper','Scissors']
    
    # Update using an element of the hands variable
    print(name + ' picked: ' + hands[hand])

print('Starting the Rock Paper Scissors game!')
player_name = input('Please enter your name: ')
# Print 'Pick a hand: (0: Rock, 1: Paper, 2: Scissors)'
print('Pick a hand: (0: Rock, 1: Paper, 2: Scissors)')

# Get input, convert it, and assign it to the player_hand variable
player_hand=int(input('Please enter a number (0-2): '))

# Change the first argument to player_hand
print_hand(player_hand, player_name)
Starting the Rock Paper Scissors game!
Pick a hand: (0: Rock, 1: Paper, 2: Scissors)
Krishnakanth picked: Scissors

We need to ensure that the player only selects 0, 1 or 2 and nothing else. Let's add another function to validate player input using an if...else statement.

In [10]:
# Define the validate function
def validate(hand):
    # Add control flow based on the value hand
    if hand<0 or hand>2:
        return False
    else:
        return True
    
def print_hand(hand, name='Guest'):
    hands = ['Rock', 'Paper', 'Scissors']
    print(name + ' picked: ' + hands[hand])

print('Starting the Rock Paper Scissors game!')
player_name = input('Please enter your name: ')

print('Pick a hand: (0: Rock, 1: Paper, 2: Scissors)')
player_hand = int(input('Please enter a number (0-2): '))

# Add control flow based on the return value of the validate function
if validate(player_hand):
    print_hand(player_hand, player_name)
else:
    print('Please enter a valid number')
Starting the Rock Paper Scissors game!
Pick a hand: (0: Rock, 1: Paper, 2: Scissors)
Krishnakanth picked: Rock

Is there a simpler way to write the validate function? Let's try.

In [11]:
# Define the validate function
def validate(hand):
    return 0<=hand<=2

Now that the player is able to select a hand, let's assign a hand to the computer too. Let's begin with the computer always selects 'Paper'.

In [12]:
if validate(player_hand):
    # Assign 1 to the computer_hand variable
    computer_hand=1
    
    print_hand(player_hand, player_name)
    # Call print_hand function with computer_hand and 'Computer' as arguments
    print_hand(computer_hand,'Computer')
    
else:
    print('Please enter a valid number')
Krishnakanth picked: Rock
Computer picked: Paper

Now we'll create another function Judge to determine the winner using if-else statements.

In [13]:
# Define the judge function
def judge(player,computer):
    # Add control flow based on the comparison of player and computer
    if player==computer:
        return 'Draw'
    elif player==0 and computer==1:
        return 'Lose'
    elif player==1 and computer==2:
        return 'Lose'
    elif player==2 and computer==0:
        return 'Lose'
    else:
        return 'Win'

if validate(player_hand):
    computer_hand = 1
    
    print_hand(player_hand, player_name)
    print_hand(computer_hand, 'Computer')
    
    # Assign the return value of judge to the result variable
    result=judge(player_hand,computer_hand)
    # Print the result variable
    print('Result: '+result)
else:
    print('Please enter a valid number')
Krishnakanth picked: Rock
Computer picked: Paper
Result: Lose

Is there a simpler way to write the Judge function here?

In [14]:
# Define the judge function
def judge(player,computer):
    # Add control flow based on the comparison of player and computer
    if player-computer in [1,-2]:
        return 'Win'
    elif player==computer:
        return 'Draw'
    return 'Lose'

if validate(player_hand):
    computer_hand = 1
    
    print_hand(player_hand, player_name)
    print_hand(computer_hand, 'Computer')
    
    # Assign the return value of judge to the result variable
    result=judge(player_hand,computer_hand)
    # Print the result variable
    print('Result: '+result)
else:
    print('Please enter a valid number')
Krishnakanth picked: Rock
Computer picked: Paper
Result: Lose

We would like the computer to select a hand randomly using the random function. Here is the complete code for the rock-paper-scissors game.

In [15]:
def print_hand(hand, name='Guest'):
    hands = ['Rock', 'Paper', 'Scissors']
    print(name + ' picked: ' + hands[hand])
    
def validate(hand):
    return 0<=hand<=2

def judge(player,computer):
    if player-computer in [1,-2]:
        return 'Win'
    elif player==computer:
        return 'Draw'
    return 'Lose'

# import the random module
import random

print('Starting the Rock Paper Scissors game!')
player_name = input('Please enter your name: ')

print('Pick a hand: (0: Rock, 1: Paper, 2: Scissors)')
player_hand = int(input('Please enter a number (0-2): '))

if validate(player_hand):
    # Assign a random number between 0 and 2 to computer_hand using randint
    computer_hand = random.randint(0,2)
    print_hand(player_hand, player_name)
    print_hand(computer_hand, 'Computer')
    result = judge(player_hand, computer_hand)
    print('Result: ' + result)
else:
    print('Please enter a valid number')
Starting the Rock Paper Scissors game!
Pick a hand: (0: Rock, 1: Paper, 2: Scissors)
Krishnakanth picked: Paper
Computer picked: Rock
Result: Win

Note: The code on this page is something that I wrote when I took Progate's free Python classes.

Last updated 2020-12-01 15:56:41.395022 IST

OpenCV - Face recognition using Haar Cascade Classifiers

wordcloud

1. Haar Cascade Classifiers

Haar Cascade is a machine learning object detection algorithm proposed by Paul Viola and Michael Jones in their paper “Rapid Object Detection using a Boosted Cascade of Simple Features” in 2001. More information can be found on how a cascade classifier works here. OpenCV offers pre-trained Haar cascade algorithms organized into categories such as face, eye, smile, upperbody, lowerbody, etc. Haar cascade classifiers can be downloaded from they github repository.

We are going to attempt to use Haar cascade classifiers to detect the following:

  • Cat face
  • Human face
  • Eye

Select relevant classifiers from the link above, or just download the zip file from https://go.allika.eu.org/HaarCascadeClassifiers

2. Face detection in an image

Cat face detection

Here is an image of my cat sitting on a wall. Let's attempt to detect its face from the image.

Cat on a wall
In [1]:
# Importing libraries
import cv2
from matplotlib import pyplot as plt
from PIL import Image

OpenCV provides an imshow() function to display images, however, they are displayed in a seperate window and not inline. We can use matplotlib or pillow to display images inline, but we need to convert an OpenCV image from BGR to RGB first. Let's write functions to do that to save time.

In [2]:
# A function to display an OpenCV image using matplotlib
def plot_cv_image(img):
    plt.figure(figsize=(20,10))
    plt.imshow(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
    plt.show()
    return None

# A function to display an OpenCV image using pillow
def pillow_cv_image(img):
    return Image.fromarray(cv2.cvtColor(img,cv2.COLOR_BGR2RGB))
In [3]:
# Path to Haar Cascade classifier
haar_classifier="../../files/ml/003/haarcascade_frontalcatface.xml"
# Declaring cascade classifier
haar_cascade=cv2.CascadeClassifier(haar_classifier)
# Reading the input image
cv_img=cv2.imread("../../images/ml/003/001.jpg")
# Convertng to grayscale before classifying
cv_gray=cv2.cvtColor(cv_img,cv2.COLOR_BGR2GRAY)
# Detect cat faces using the Haar classifier
faces=haar_cascade.detectMultiScale(cv_gray,scaleFactor=1.3,minNeighbors=3)
# Display the number of faces detected
print(len(faces))
1
In [4]:
# Draw a rectangle around the detected face
for (x,y,w,h) in faces:
    cv2.rectangle(cv_img,(x,y),(x+w,y+h),color=(255,0,0),thickness=2)
In [5]:
# Display the output image using matplotlib
plot_cv_image(cv_img)
No description has been provided for this image
In [6]:
# Display the output image using pillow
pillow_cv_image(cv_img)
Out[6]:
No description has been provided for this image

Multiple cat faces detection in an image

Let's try to detect cat faces from the following image of kittens

Kitten
In [7]:
# Reading the input image
cv_img=cv2.imread("../../images/ml/003/002.jpg")
# Convertng to grayscale before classifying
cv_gray=cv2.cvtColor(cv_img,cv2.COLOR_BGR2GRAY)
# Detect cat faces using the Haar classifier
faces=haar_cascade.detectMultiScale(cv_gray,scaleFactor=1.3,minNeighbors=3)
# Display the number of faces detected
print(len(faces))
3
In [8]:
# Draw rectanges around detected faces
for (x,y,w,h) in faces:
    cv2.rectangle(cv_img,(x,y),(x+w,y+h),color=(255,0,0),thickness=2)
# Display the output image using pillow
plot_cv_image(cv_img)
No description has been provided for this image

Detect Human Faces in an Image

Human faces can be detected using haarcascade_frontalface_default.xml classifier file. Let's attempt to detect human faces from the following poster.

Rational Thinking poster
In [9]:
# Path to Haar Cascade classifier
haar_classifier="../../files/ml/003/haarcascade_frontalface_default.xml"
# Declaring cascade classifier
haar_cascade=cv2.CascadeClassifier(haar_classifier)
# Reading the input image
cv_img=cv2.imread("../../images/ml/003/003.jpg")
# Convertng to grayscale before classifying
cv_gray=cv2.cvtColor(cv_img,cv2.COLOR_BGR2GRAY)
# Detect cat faces using the Haar classifier
faces=haar_cascade.detectMultiScale(cv_gray,scaleFactor=1.3,minNeighbors=3)
# Display the number of faces detected
print(len(faces))
10
In [10]:
# Draw rectanges around detected faces
for (x,y,w,h) in faces:
    cv2.rectangle(cv_img,(x,y),(x+w,y+h),color=(255,0,0),thickness=2)
# Display the output image using pillow
plot_cv_image(cv_img)
No description has been provided for this image

[^top]

3. Face detection in a video

We are going to detect faces in the video https://go.allika.eu.org/FaceDetection and save the output in a video file.

In [11]:
# Path to Haar Cascade classifier
haar_classifier="../../files/ml/003/haarcascade_frontalface_default.xml"
# Declaring cascade classifier
haar_cascade=cv2.CascadeClassifier(haar_classifier)
# Input video
input_video=cv2.VideoCapture("https://go.allika.eu.org/FaceDetection")

if input_video.isOpened():
    # Get input video properties
    width=int(input_video.get(cv2.CAP_PROP_FRAME_WIDTH))
    height=int(input_video.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps=int(input_video.get(cv2.CAP_PROP_FPS))
    print("Video size: {}x{}\nFrame rate: {}FPS".format(width,height,fps))
    # Defining output object
    output_video=cv2.VideoWriter("../../files/ml/003/face_detection.mp4", # Output file
                                cv2.VideoWriter_fourcc(*'X264'), # FOURCC codec
                                fps, # Frame rate
                                (width,height)) # video size
    while True:
        flag,frame=input_video.read() # reading input video frames
        if flag: # Process only if frame is read successfully
            gray_frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) # converting frames to grayscale
            faces=haar_cascade.detectMultiScale(gray_frame,scaleFactor=1.3,minNeighbors=3) # face detection
            # Drawing rectangles around faces
            for (x,y,w,h) in faces:
                cv2.rectangle(frame,(x,y),(x+w,y+h),color=(255,0,0),thickness=2)
            # write frame to output
            output_video.write(frame)
        else:
            break
input_video.release() # Release VideoCapture object (input file)
output_video.release() # Release VideoCapture object (output file)
cv2.destroyAllWindows() # close all display windows
Video size: 500x300
Frame rate: 30FPS

Following is the video output.

[^top]

4. Eye detection in a video

Eye detection works the same way as face detection, except that we will use the Haar cascade classifier trained for eye recognition instead.

In [12]:
# Path to Haar Cascade classifier for eye detection
haar_classifier="../../files/ml/003/haarcascade_eye.xml"
# Declaring cascade classifier
haar_cascade=cv2.CascadeClassifier(haar_classifier)
# Input video
input_video=cv2.VideoCapture("https://go.allika.eu.org/FaceDetection")

if input_video.isOpened():
    # Get input video properties
    width=int(input_video.get(cv2.CAP_PROP_FRAME_WIDTH))
    height=int(input_video.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps=int(input_video.get(cv2.CAP_PROP_FPS))
    print("Video size: {}x{} pixels\nFrame rate: {} FPS".format(width,height,fps))
    # Defining output object
    output_video=cv2.VideoWriter("../../files/ml/003/eye_detection.mp4", # Output file
                                cv2.VideoWriter_fourcc(*'X264'), # FOURCC codec
                                fps, # Frame rate
                                (width,height)) # video size
    while True:
        flag,frame=input_video.read() # reading input video frames
        if flag: # Process only if frame is read successfully
            gray_frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) # converting frames to grayscale
            eyes=haar_cascade.detectMultiScale(gray_frame,scaleFactor=1.3,minNeighbors=3) # eye detection
            # Drawing rectangles around eyes
            for (x,y,w,h) in eyes:
                cv2.rectangle(frame,(x,y),(x+w,y+h),color=(0,255,0),thickness=2)
            # write frame to output
            output_video.write(frame)
        else:
            break
input_video.release() # Release VideoCapture object (input file)
output_video.release() # Release VideoCapture object (output file)
cv2.destroyAllWindows() # close all display windows
Video size: 500x300 pixels
Frame rate: 30 FPS

Following is the video output:

[^top]

5. Face and Eye detection together in a video

Let's combine face recognition with eye detection. However, in this case, we will attempt to detect eyes only within faces. We first detect faces and then detect eyes in them.

In [13]:
# Path to Haar Cascade classifiers
haar_classifier_face="../../files/ml/003/haarcascade_frontalface_default.xml"
haar_classifier_eye="../../files/ml/003/haarcascade_eye.xml"
# Declaring cascade classifiers
haar_cascade_face=cv2.CascadeClassifier(haar_classifier_face)
haar_cascade_eye=cv2.CascadeClassifier(haar_classifier_eye)
# Input video
input_video=cv2.VideoCapture("https://go.allika.eu.org/FaceDetection")

if input_video.isOpened():
    # Get input video properties
    width=int(input_video.get(cv2.CAP_PROP_FRAME_WIDTH))
    height=int(input_video.get(cv2.CAP_PROP_FRAME_HEIGHT))
    fps=int(input_video.get(cv2.CAP_PROP_FPS))
    print("Video size: {}x{} pixels\nFrame rate: {} FPS".format(width,height,fps))
    # Defining output object
    output_video=cv2.VideoWriter("../../files/ml/003/face_eye_detection.mp4", # Output file
                                cv2.VideoWriter_fourcc(*'X264'), # FOURCC codec
                                fps, # Frame rate
                                (width,height)) # video size
    while True:
        flag,frame=input_video.read() # reading input video frames
        if flag: # Process only if frame is read successfully
            gray_frame=cv2.cvtColor(frame,cv2.COLOR_BGR2GRAY) # converting frames to grayscale
            faces=haar_cascade_face.detectMultiScale(gray_frame,scaleFactor=1.3,minNeighbors=3) # face detection
            # Eye detection and blue rectangles around faces
            for (x,y,w,h) in faces:
                cv2.rectangle(frame,(x,y),(x+w,y+h),color=(255,0,0),thickness=2)
                # Extract each face from the frame
                face=frame[y:y+h,x:x+w]
                # Convert face to grayscale for eye detection
                gray_face=gray_frame[y:y+h,x:x+w]
                # Eye detection using default parameters i.e. 1.1 , 3
                eyes=haar_cascade_eye.detectMultiScale(gray_face) 
                # Green rectangles around eyes
                for (ex,ey,ew,eh) in eyes:
                    cv2.rectangle(face,(ex,ey),(ex+ew,ey+eh),color=(0,255,0),thickness=2)
            # write frame to output
            output_video.write(frame)
        else:
            break
input_video.release() # Release VideoCapture object (input file)
output_video.release() # Release VideoCapture object (output file)
cv2.destroyAllWindows() # close all display windows
Video size: 500x300 pixels
Frame rate: 30 FPS

Following is the video output:

[^top]

Last updated 2020-12-16 17:16:50.874422 IST