Algoritma & Struktur Data
~ Mengenal Struktur Data ~
Nb: Untuk segala bentuk diskusi, kritik dan saran mengenai materi silahkan hubungi admin!
Kontak | Konsultasi & Diskusi ke : \(\downarrow\) |
dsciencelabs@outlook.com | |
https://www.instagram.com/dsciencelabs/ | |
RPubs | https://rpubs.com/dsciencelabs/ |
Github | https://github.com/dsciencelabs/ |
Telegram | @dsciencelabs |
List
Objek list pada dasarnya mirip seperti vector, hanya saja tipe elemennya bisa berbeda. Jika pada vector numeric semua elemennya harus berupa numerik. Pada vector character semuanya harus karakter. Pada objek list elemennya dapat berupa vector, factor, matriks, array, dataframe, bahkan list di dalam list atau objek lain seperti model prediktif yang dibuat di R dan Python.
Membentuk List
Hal terpenting yang harus dipelajari adalah bagaimana untuk membentuk list. Terdapat beberapa perbedaan mendasar yang harus diperhatikan saat membentuk list di dalam R dan Python. Perhatikan contoh berikut!.
R
Python
List dapat dibentuk seperti membuat variabel biasa, namun nilai
variabelnya diisi dengan tanda kurung siku []
.
Pengindeksan Nilai dari List
Setelah kita tahu cara membuat dan menyimpan data di dalam List, mari kita coba mengambil datanya. List sama seperti array, list juga memiliki nomer indeks untuk mengakses data atau isinya.
R
Nomer indeks list di dalam Python selalu dimulai dari satu (1). Nomer indeks ini yang kita butuhkan untuk mengambil isi (item) dari list.
Python
Sedikit berbeda dengan R, nomer indeks pada suatu list di dalam Python selalu dimulai dari nol (0). Sehingga diperlukan ketelitian atau perhatian yang lebih serius jika anda ingin memanggil suatu nilai dari List tersebut.
Menambahkan dan Menghapus
Untuk menambahkan atau mengganti atau menghapus nilai pada suatu List bersifat mutable, artinya isinya bisa kita ubah-ubah.
R
list4 = list("jeruk", "apel", "mangga", "duren") # list mula-mula
list4[4] = "anggur" # mengganti duren menjadi anggur
Selain cara di atas berikut ini terdapat dua metode atau fungsi lainnya yang dapat digunakan untuk menambahkan isi atau item ke List:
Python
Berikut ini diperlihatkan cara paling sederhana untuk menambahkan atau mengganti suatu nilai dengan Python.
list4 = ["jeruk", "apel", "mangga", "duren"] # list mula-mula
list4[3] = "anggur" # mengganti duren menjadi anggur
Selain cara di atas berikut ini terdapat dua metode atau fungsi lainnya yang dapat digunakan untuk menambahkan isi atau item ke List:
- append(item) menambahkan item dari belakang.
- insert(index, item) menambahkan item dari indeks tertentu
Tuple
Tuple dalam R dan Python adalah stuktur data yang digunakan untuk menyimpan sekumpulan data. Tupe bersifat immutable, artinya isi tuple tidak bisa kita ubah dan hapus. Namun, dapat kita isi dengan berbagai macam nilai dan objek, sebagai berikut:
- Cara Membentuk Tuple
- Cara Mengakses Nilai Tuple
- Slicing Nilai Tuple
- Nested Tuple
- Unpacking Sequence
R
Untuk membuat tuple di dalam R, anda perlu untuk mengistall packages
sets
sebelum menjalankan beberapa koding berikut:
library(sets) # panggil library terlebih dahulu
# Cara Membuat Tuple
tuple0 = tuple() # Membuat tuple 0 item (kosong)
tuple1 = tuple('Hi') # membuat tuple 1 item
tuple2 = tuple("Hi", "Juga") # membuat tuple 2 item
# Mengakses Nilai Tuple
print(tuple2[1])
# Memotong Tuple
tuple4 = tuple("Hi","guys","apa","kabar?") # membuat tuple 4 item
print(tuple4[2:4]) # memotong tuple 4 berdadarkan order
# Tuple bisa diisi dengan Tuple (Tuple Nested)
tuple5 = c(tuple4, tuple2)
tuple6 = rep(tuple4, 2)
Python
Tuple biasanya dibuat dengan tanda kurung ()
# Cara Membuat Tuple
tuple0 = () # Membuat tuple 0 item (kosong)
tuple1 = ('Hi',) # membuat tuple 1 item (harus ditambahkan koma)
tuple2 = "Hi", "Juga" # membuat tuple 2 item
# Mengakses Nilai Tuple
print(tuple2[0])
# Memotong Tuple
tuple4 = ("Hi", "guys", "apa", "kabar?") # membuat tuple 4 item
print(tuple4[1:4]) # membuat tuple 3 item
# Tuple bisa diisi dengan Tuple (Tuple Nested)
tuple5 = (tuple4, tuple2)
# Sequence Unpacking
nomor0,nomor1,nomor2,nomor3=tuple4
print(nomor0,nomor1,nomor2,nomor3)
Dictionary
Dictionary adalah stuktur data yang bentuknya seperti kamus. Ada kata
kunci kemudian ada nilaninya. Kata kunci harus unik, sedangkan nilai
boleh diisi denga apa saja. Adapun perbedaan list dan tuple adalah;
dictionary
memiliki kunci berupa teks (bisa juga angka),
sedangkan list
dan tuple
menggunakan indeks
berupa angka saja untuk mengakses nilainya.
R
Untuk membentuk Disctionary didalam R sangatlah mudah, silahkan perhatikan contoh berikut:
library(Dict)
# Membuat Dictionary
dsciencelabs = dict(
nama = "Bakti Siregar",
umur = as.integer(28),
hobi = list("coding", "badminton", "renang"),
menikah= FALSE,
sosmed = dict(facebook= "dsciencelabs",
instagram = "dsciencelabs"
)
)
# Mengakses isi dictionary
cat("Nama saya adalah :", dsciencelabs$get('nama'))
print(dsciencelabs$get('sosmed')['instagram'])
# Mengubah Nilai Item Dictionary
dsciencelabs["nama"] = "Bakti Siregar Ganteng"
# Menghapus item dari Dictionary
dsciencelabs$remove("sosmed") # cara 1
dsciencelabs$clear() # cara 2 ini untuk menghapus semua dictionary
Python
Hal yang wajib ada di dalam pembuatan Dictionary
dalam
Python adalah:
- nama dictionary,
- key,
- value,
- buka dan tutupnya menggunakan kurung kurawal.
Antara key dan value dipisah dengan titik dua (:) dan apabila terdapat lebih dari satu item, maka dipisah dengan tanda koma (,).
# Membuat Dictionary
dsciencelabs = {
"nama": "Bakti Siregar",
"umur": 28,
"hobi": ["coding", "badminton", "renang"],
"menikah": False,
"sosmed": {
"facebook": "dsciencelabs",
"instagram": "dsciencelabs"
}
}
# Mengakses isi dictionary
print("Nama saya adalah %s" % dsciencelabs["nama"])
print("Instagram: %s" % dsciencelabs["sosmed"]["instagram"])
# Mengubah Nilai Item Dictionary
dsciencelabs["nama"] = "Bakti Siregar Ganteng"
# Menghapus item dari Dictionary
del dsciencelabs["sosmed"] # cara 1
dsciencelabs.pop("menikah") # cara 2
dsciencelabs.clear() # cara 3 (menghapus semuanya sekaligus)
Data Frame
Bingkai data adalah tabel atau struktur seperti array dua dimensi di mana setiap kolom berisi nilai dari satu variabel dan setiap baris berisi satu set nilai dari setiap kolom. Berikut ini adalah ciri-ciri data frame:
- Nama kolom tidak boleh kosong.
- Nama baris harus unik.
- Data yang disimpan dalam bingkai data dapat berupa numerik, faktor, atau tipe karakter.
- Setiap kolom harus berisi jumlah item data yang sama.
R
Berikut ini diperlihatkan contoh data frame dengan menggunakan R:
# Membentuk data frame 1
df1_R <- data.frame(kode = c (1:5),
nama = c("Julian","Vanessa","Jeffry","Angel","Nikki"),
gaji = c(623.3,515.2,611.0,729.0,843.25),
mulai_kerja = as.Date(c("2022-01-01", "2022-09-23", "2022-11-15", "2022-05-11", "2022-03-27")),
divisi = c("DS","DS","BA","DA","DS"), stringsAsFactors = F)
# Membentuk data frame 2
df2_R <- data.frame(kode = c (6:10),
nama = c("Ardifo","Irene","Kefas","Sherly","Bakti"),
gaji = c(578.0,722.5,632.8,632.8,NA),
mulai_kerja = as.Date(c("2022-05-21","2022-07-30","2022-06-17", "2022-07-30","2018-09-03")),
divisi = c("Actuaries","Actuaries","CA","DE","Lecturer"),stringsAsFactors = F)
Beberapa operasi yang dapat dilakukan pada data frame R.
df3_R <- rbind(df1_R,df2_R) # gabungkan dua data frame
print(df3_R) # mencetak hasil `df3_R`
head(df3_R) # mencetak enam baris pertama
tail(df3_R) # mencetak enam baris terakhir
head(df3_R,6) # mencetak enam baris pertama
#View(df3_R) # menampilkan data di Rstudio layaknya Excel
class(df3_R) # check tipe data.frame
str(df3_R) # check struktur data frame
dim(df3_R) # periksa dimensi data
summary(df3_R) # summary statistik dasar
Data frame biasanya dibuat dengan membaca dataset menggunakan
read.table()
atau read.csv()
. Namun, data
frame juga dapat dibuat secara eksplisit dengan menggunakan fungsi
data.frame() atau dapat dipaksakan dari jenis objek lain seperti list
atau vektor.
Python
Pada situasi yang sebenarnya (Data science), DataFrame akan dibuat dengan memuat kumpulan data dari penyimpanan yang ada, penyimpanan dapat berupa Database SQL, file CSV, file Excel. DataFrame dapat dibuat dari daftar, kamus, dan dari daftar kamus, dll. Dataframe dapat dibuat dengan berbagai cara. Berikut adalah beberapa cara yang kami gunakan untuk membuat bingkai data:
# import libarary pandas
import pandas as pd
# kumpulan data
dt1_Py = {'kode' : range(5),
'nama' : ["Julian","Vanessa","Jeffry","Angel","Nikki"],
'gaji' : [623.3,515.2,611.0,729.0,843.25],
'mulai_kerja' : ["2022-01-01", "2022-09-23", "2022-11-15", "2022-05-11", "2022-03-27"],
'divisi' : ['DS','DS','BA','DA','DS']}
dt2_Py = {'kode' : range(5),
'nama' : ["Ardifo","Irene","Kefas","Sherly","Bakti"],
'gaji' : [578.0,722.5,632.8,632.8, 632.8 ],
'mulai_kerja' : ["2022-05-21","2022-07-30","2022-06-17","2022-07-30","2018-09-03"],
'divisi' : ["Actuaries","Actuaries","CA","DE","Lecturer"]}
# merubah kumpulan data menjadi Data frame
df1_Py = pd.DataFrame(dt1_Py)
df2_Py = pd.DataFrame(dt2_Py)
Beberapa operasi yang dapat dilakukan pada data frame Python.
df3_Py = df1_Py.append(df2_Py) # gabungkan dua data frame
print(df3_Py) # mencetak hasil `df3_Py`
df3_Py.head() # mencetak 5 baris pertama
df3_Py.tail() # mencetak 5 baris akhir
df3_Py.head(3) # mencetak 3 baris pertama
type(df3_Py) # check tipe data.frame
df3_Py.info() # check struktur data frame
df3_Py.shape # periksa dimensi data
df3_Py.describe() # summary statistik dasar
Rekayasa Data Frame
Sebagai seorang Data Scientist, secara intuitif anda bisa saja merasa perlu untuk membangun data frame sendiri. Tentu dengan memperhatikan kaidah-kaidah statistik atau matematimatik yang belaku, sehingga dapat memperkirakan kumpulan data atau sampel yang dapat dipercaya untuk mensimulasikan proses analisis data, pemodelan, dan bahkan prediksi. Perlu dicatat bahwa opsi ini haruslah menjadi pilihan terakhir, meskipun akan sangat membantu pekerjaan anda, terutama saat anda tidak memungkinkan untuk mengumpulkan data atau sampel yang dibutuhkan. Kondisi lain, yang mengharuskan anda membangun data frame (fake data frame) bisa juga dikarenakan anda tidak ingin mempersentasikan data yang bersifat rahasia kepada banyak orang. Oleh karena itu, berikut ini kita akan belajar bagaimana menghasilkan data farame dengan R dan Python.
R
Misalkan Anda ingin membangun kumpulan data karyawan di sebuah perusahaan dengan R, perhatikan contoh berikut:
No<-(1:52) # menghasilkan nomor 1-52
Nama<-c(LETTERS,letters) # Huruf Kapital dan Non-Kapital
Jenis_Kelamin<-sample(rep(c("Pria",
"Wanita"),times=26)) # Jenis Kelamin
# menghasilkan tanggal lahir dengan time series
Tiga_Tahun<-seq(as.Date("2000/01/01"), by="year", length.out=4)
Tanggal_Lahir<- rep(Tiga_Tahun, times=13)
# Kategori universitas
univ1<-rep("Negeri",times=26) # 26 universitas negeri
univ2<-rep("Swasta",times=16) # 16 universitas swasta
univ3<-rep("LN",times=10) # 10 universitas luar negerei
Universitas<-sample(c(univ1,univ2,univ3)) # menggabungkan vektor/list diatas
gpa<-runif(52,min=3.00,max=4.00) # menghasilkan 52 angka acak (min=3, dan maks=4)
GPA<-round(gpa,digits=2) # atur digit angka acak Anda
Gaji<-sample(600:1200,52,replace=T) # hasilkan sampel antara 600-1200 (izinkan nilai duplikat)
Karyawan_R<-data.frame(No,
Nama,
Tanggal_Lahir,
Jenis_Kelamin,
Universitas,
GPA,
Gaji)
print(Karyawan_R)
Python
Pertama-tama, import pandas, NumPy, dan beberapa library yang dibutuhkan. Dalam hal ini kita dapat menggunakan NumPy dan Faker untuk menghasilkan data palsu secara acak.
import numpy as np
import pandas as pd
from faker.providers.person.en import Provider
# Menghasilkan nomor
size = 100
No = range(100)
# menghasilkan data acak untuk nama
def random_names(name_type, size):
Nama = getattr(Provider, name_type)
return np.random.choice(Nama, size=size)
# menghasilkan data acak untuk jenis kelamin
def random_genders(size, p=None):
if not p:
p = (0.49, 0.49, 0.01, 0.01)
Jenis_Kelamin = ("Pria", "Wanita", "Lainnya", "")
return np.random.choice(Jenis_Kelamin, size=size, p=p)
# menghasilkan data acak untuk tanggal lahir
def random_dates(start, end, size):
# Stempel waktu python dituliskan dalam nanodetik secara default,
# sehingga kita perlu melakukan 24*60*60*10**9 untuk dikonversi ke hari
divide_by = 24 * 60 * 60 * 10**9
start_u = start.value // divide_by
end_u = end.value // divide_by
return pd.to_datetime(np.random.randint(start_u, end_u, size), unit="D")
# menghasilkan data acak untuk universitas
Universitas = np.random.choice(["Negeri", "Swasta", "LN"],size=size)
GPA = np.random.uniform(low=2.5, high=4, size=size)
Gaji = np.random.normal(loc=10000, scale=5000, size=size)
Karyawan_Py = pd.DataFrame(columns=['No',
'Nama_Depan',
'Nama_Belakang',
'Jenis_Kelamin',
'Tanggal_Lahir',
'Universitas',
'GPA',
'Gaji'
])
Karyawan_Py['No'] = No
Karyawan_Py['Nama_Depan'] = random_names('first_names', size)
Karyawan_Py['Nama_Belakang'] = random_names('last_names', size)
Karyawan_Py['Jenis_Kelamin'] = random_genders(size)
Karyawan_Py['Tanggal_Lahir'] = random_dates(start=pd.to_datetime('2000-01-01'), end=pd.to_datetime('2021-01-01'), size=size)
Karyawan_Py['Universitas'] = Universitas
Karyawan_Py['GPA'] = GPA
Karyawan_Py['Gaji'] = Gaji
print(Karyawan_Py)
Ekstraksi Data Frame
Selain keahlian membangun data frame sendiri, keahlian mendasar yang tak kalah pentingnya bagi seorang data scientist adalah proses ekstraksi data frame (Pengindeksan, Pengirisan, dan Subsetting) pada suatu data set (data frame). Dalam hal ini, tentu harus memperhatikan tipe data anda dengan baik. Berikut ini akan diperlihatkan beberapa hal mengenai Pengindeksan, Pengirisan, dan Subsetting data set dengan R dan Python.
R
R menyediakan banyak cara untuk mensubset dan mengekstrak elemen dari vektor, list, data frame, dan objek lainnya. Sebagai permulaan, Pengindeksan, Pengirisan, dan Subsetting dapat dilakukan dengan operator []. Operator ini dapat mengambil banyak jenis vektor.
typeof(Karyawan_R) # cek tipe datanya
class(Karyawan_R) # cek tipe datanya
Karyawan_R[1,5] # ekstrak elemen di baris ke-1 dan kolom ke-5.
Karyawan_R$Nama # ekstrak spesifik kolom (`Nama`)
Karyawan_R[,c('Nama','Jenis_Kelamin')] # ekstrak spesifik kolom (`Nama, Jenis Kelamin`)
Karyawan_R[1:5,] # ekstrak lima baris pertama Karyawan_R
Karyawan_R[,1:5] # ekstrak lima kolom pertama Karyawan_R
subset(Karyawan_R, select=GPA) # ekstrak/subset spesifik kolom
subset(Karyawan_R, select=6) # ekstrak/subset spesifik kolom
subset(Karyawan_R, select= c(6,7)) # ekstrak/subset kolom pertama & kedua
subset(Karyawan_R, select= c(2:5)) # ekstrak/subset Kolom tertentu
Menambahkan variabel baru ke data frame dapat dilakukan dengan menetapkan vektor baru. Salah satu keunggulan objek dalam data frame dengan R adalah ketersedian proses ekstraksi yang melibatkan operator dan juga berlaku untuk semua jenis vektor (tipe data), seperti halnya bilangan bulat, numerik, logis, faktor, dan karakter.
Karyawan_R$Pajak <- Karyawan_R$Gaji*0.03 # tambahkan variabel baru `Pajak`
Karyawan_R$Gaji_Bersih <- Karyawan_R$Gaji-Karyawan_R$Pajak # tambahkan variabel baru `Gaji_Bersih`
Karyawan_R$Gaji_Grup1 <- Karyawan_R$Gaji > 950 # tambahkan variabel baru `Gaji_Grup1`
Karyawan_R$Gaji_Grup2<-ifelse(Karyawan_R$Gaji > 950, # tambahkan variabel baru `Gaji_Grup2`
"Gaji Besar",
"Gaji Kecil")
Karyawan_R$Gaji_Grup3<-factor(Karyawan_R$GPA >3.5 & # tambahkan variabel baru `Gaji_Grup3`
Karyawan_R$Gaji>950,
labels = c("level1",
"level2"))
min(Karyawan_R$Gaji) # nilai minimum `Gaji`
max(Karyawan_R$Gaji) # nilai Maksimum `Gaji`
mean(Karyawan_R$Gaji) # nilai rerata `Gaji`
var(Karyawan_R$Gaji) # nilai variansi `Gaji`
sd(Karyawan_R$Gaji) # nilai standar deviasi `Gaji`
summary(Karyawan_R) # statistik dasar data frame `Gaji`
Pyhton
Sama hal dengan R, kita juga pasti akan sering ingin bekerja dengan subset dari suatu objek data frame di Python. Ada berbagai cara untuk melakukannya termasuk: menggunakan label (judul kolom), rentang numerik, atau lokasi indeks tertentu.
type(Karyawan_Py) # cek tipe datanya
Karyawan_Py.iloc[0,5] # ekstrak elemen di baris ke-1 dan ke-6.
Karyawan_Py['Nama_Depan'] # ekstrak spesifik kolom (`Nama_Depan`)
Karyawan_Py[['Nama_Depan','Jenis_Kelamin']] # ekstrak spesifik kolom (`Nama_Depan, Jenis_Kelamin`)
Karyawan_Py[:5] # ekstrak lima baris pertama
Karyawan_Py[5:] # ekstrak setelah lima baris pertama
Karyawan_Py[-5:] # ekstrak lima baris n-1 baris terakhir
Karyawan_Py[0:5] # ekstrak lima baris pertama
Karyawan_Py.iloc[0:5] # ekstrak lima baris pertama
Karyawan_Py.iloc[:, 0:5] # ekstrak enam kolom pertama
Karyawan_Py.iloc[:, [2,5]] # ekstrak kolom ke-2 dan kolom ke-5
Karyawan_Py.iloc[[2,5], :] # ekstrak baris ke-2 dan baris ke-5
Karyawan_Py.loc[0:3] # ekstrak baris ke-0 dan baris ke-3 (tidak berdasarkan index)
Karyawan_Py.loc[[1,5]] # ekstrak data baris 1 dan 5 (tidak berdasarkan index)
Karyawan_Py[Karyawan_Py.GPA > 3] # selksi data kolom GPA > 3
Karyawan_Py[(Karyawan_Py.GPA > 3) &
(Karyawan_Py.GPA < 3.5)]
Untuk menambahkan variabel, anda bisa menggunakan nama data frame[‘nama kolom baru’]
Karyawan_Py['pajak'] = Karyawan_Py.Gaji*0.03 # menambahkan variabel "pajak"
Karyawan_Py['gaji_bersih'] = Karyawan_Py.Gaji - Karyawan_Py.pajak # menambahkan variabel "gaji_bersih"
Karyawan_Py['gaji_grup1'] = Karyawan_Py.Gaji > 950 # menambahkan variabel "gaji_grup1"
Karyawan_Py['gaji_grup2'] = np.where(Karyawan_Py.Gaji > 950, # menambahkan variabel baru "gaji_grup2"
"Gaji Besar", "Gaji Kecil")
kondisi = (Karyawan_Py['GPA'] > 3.5) & (Karyawan_Py['Gaji'] > 950) # menambahkan variabel baru "gaji_grup3"
Karyawan_Py['gaji_grup3'] = np.where (kondisi, "level 1", "level 2")
Karyawan_Py
Untuk mencari statistik dasar adalah sebagai berikut:
min(Karyawan_Py.Gaji) # nilai minimum "Gaji"
max(Karyawan_Py.Gaji) # nilai maksimum "Gaji"
np.mean(Karyawan_Py.Gaji) # nilai rata-rata "Gaji"
np.var(Karyawan_Py.Gaji) # nilai variansi "Gaji"
np.std(Karyawan_Py.Gaji) # nilai standar deviasi "Gaji"
print(Karyawan_Py.describe()) # Statistik dasar data frame
Ganti Nama Variabel
Salah satu hal penting lainnya yang dimiliki proses data science adalah menyimpan data kedalam variabel. Variabel dapat diibaratkan seperti sebuah label untuk sebuah informasi. Variabel dapat juga terdiri dari beberapa informasi. Seringkali, kita sebagai data scientist perlu untuk mengganti nama variabel tertentu untuk memudahkan dalam menganalisa informasi yang terkandung pada suatu data yang dimiliki.
R
Objek R dapat memiliki nama, yang sangat berguna untuk menulis kode yang dapat dibaca dan objek yang menggambarkan dirinya sendiri. Di sini, Anda akan mempelajari cara mengganti nama kolom data frame di R menggunakan fungsi names().
rename_1<-Karyawan_R # merubah nama data frame
names(rename_1)<-c("no", # merubah nama variabel pada data frame
"nama",
"tgl.lahir",
"jenis.kelamin",
"univ",
"ipk",
"gaji")
rename_1
Ini juga dapat dilakukan dengan menggunakan fungsi
rename()
yang ada di [dplyr package].
Pyhton
Melakukan Rename pada data frame dengan menggunakan Python
import pandas as pd
Karyawan_Py1 = Karyawan_Py
Karyawan_Py1.rename(columns = { 'No' : 'no',
'Nama_Depan' : 'nama.depan',
'Nama_Belakang' : 'nama.belakang',
'Jenis_Kelamin' : 'jenis.kelamin',
'Tanggal_Lahir' : 'tanggal.lahir',
'Universitas' : "univ",
'GPA' : 'ipk',
'Gaji' : 'gaji'}, inplace = True)
Karyawan_Py1
Referensi
- https://www.tutorialspoint.com/r/index.htm
- https://www.tutorialspoint.com/python/index.htm
- https://www.kodefungsi.com/fungsi/PYTHON/
- https://www.petanikode.com/
- https://pynative.com/python-random-choice/
- https://docs.python.org/3/library/random.html
- https://datacarpentry.org/python-ecology-lesson/03-index-slice-subset/