04 Pandas 2

image.png Կարմիրքար (Մեծն Փառախադեմ) լուսանկարի հղումը, Հեղինակ՝ Zvart Baghdasaryan

Open In Colab (ToDo)

📌 Նկարագիր

📚 Ամբողջական նյութը

Նշում․ Եթե Pandas 1-ին դեռ չեք ծանոթացել՝ սկզբում դա արեք, նոր եկեք pandas 2:

Շարունակում ենք մեր պանդաների ուսումնասիրությունը։ Էս անգամ խոսում ենք՝

  1. Մի քանի df-ներ միավորելուց (concat, merge, join), ու իրենց տեսակներից (inner, outer, left, right)
  2. Excel ֆայլերի հետ աշխատանքից - ոնց կարդալ/save անել կոնկրետ sheet ․․․
  3. Կայքերից տվյալներ քաշելուց՝ read_html-ի օգնությամբ (Armstat-ի օրինակով)
  4. Long, wide աղյուսակների ֆորմատներից ու ոնց հալացնել (melt) մեր df
  5. Dask-ով գոյատևելուց երբ տվյալները ամպի չափ մեծ են ու չենք էլ կարա աշխատանքային հիշողության (RAM) մեջ տեղավորենք
  6. Ամսաթվերի հետ աշխատանքից Datetime օբյեկտների միջոցով
  7. Numpy vectorization vs .apply vs for loop-ի համեմատումից
  8. Արագ մակերեսային նկարագիր ստանալու համար profilingydata_profiling ու sweetviz գրադարաններից

📺 Տեսանյութեր

  1. Տեսություն
  2. Գործնական - Նշանավոր մարդկանց վերլուծություն (ToDo)

🏡 Տնային

Վերցնել ցանկացած դատասեթ ու փորփրել։

Կարող եք դատան վերցնել Kaggle-ից։ Կամ եթե հայկական եք ուզում՝ Armstat-ից

📚 Նյութը

  1. Docs
  2. Youtube video
  3. Kaggle mini course

image.png

image.png

Joining dfs

Concat

import pandas as pd

df1 = pd.DataFrame({
    'ID': [1, 2, 3],
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [25, 30, 35]
})

df2 = pd.DataFrame({
    'ID': [4, 5, 6],
    'Name': ['David', 'Eve', 'Frank'],
    'Age': [40, 50, 60]
})

print(df1)
print()
print(df2)
   ID     Name  Age
0   1    Alice   25
1   2      Bob   30
2   3  Charlie   35

   ID   Name  Age
0   4  David   40
1   5    Eve   50
2   6  Frank   60
# Concatenating vertically (default axis=0)
result = pd.concat([df1, df2])
result
ID Name Age
0 1 Alice 25
1 2 Bob 30
2 3 Charlie 35
0 4 David 40
1 5 Eve 50
2 6 Frank 60
result.reset_index(drop=True)
ID Name Age
0 1 Alice 25
1 2 Bob 30
2 3 Charlie 35
3 4 David 40
4 5 Eve 50
5 6 Frank 60
df3 = pd.DataFrame({
    'Salary': [50000, 60000, 70000]
})
print(df3)
   Salary
0   50000
1   60000
2   70000
# Concatenating horizontally
result = pd.concat([df1, df3], axis=1)
result
ID Name Age Salary
0 1 Alice 25 50000
1 2 Bob 30 60000
2 3 Charlie 35 70000
df4 = pd.DataFrame({
    'ID': [7, 8],
    'Salary': [55000, 75000]
})

# Concatenating with missing columns
print(df1)
print(df4)
   ID     Name  Age
0   1    Alice   25
1   2      Bob   30
2   3  Charlie   35
   ID  Salary
0   7   55000
1   8   75000
result = pd.concat([df1, df4], axis=0)
print(result)
   ID     Name   Age   Salary
0   1    Alice  25.0      NaN
1   2      Bob  30.0      NaN
2   3  Charlie  35.0      NaN
0   7      NaN   NaN  55000.0
1   8      NaN   NaN  75000.0
import numpy as np
result.isna()
ID Name Age Salary
0 False False False True
1 False False False True
2 False False False True
0 False True True False
1 False True True False
assert np.all(result.isna()), "Օ ոչ"
---------------------------------------------------------------------------
AssertionError                            Traceback (most recent call last)
Input In [20], in <cell line: 1>()
----> 1 assert np.all(result.isna()), "Օ ոչ"

AssertionError: Օ ոչ

Concatenating with keys (multi-index)

print(df1)
print()
print(df2)

result = pd.concat([df1, df2], keys=['Group 1', 'Group 2'], axis=0)
print(result)
   ID     Name  Age
0   1    Alice   25
1   2      Bob   30
2   3  Charlie   35

   ID   Name  Age
0   4  David   40
1   5    Eve   50
2   6  Frank   60
           ID     Name  Age
Group 1 0   1    Alice   25
        1   2      Bob   30
        2   3  Charlie   35
Group 2 0   4    David   40
        1   5      Eve   50
        2   6    Frank   60

Merge

df5 = pd.DataFrame({
    'ID': [1, 2],
    'Department': ['HR', 'IT']
})

print(df1)
print(df5)

# Merging DataFrames on 'ID' column
result = pd.merge(df1, df5, on='ID')
result
   ID     Name  Age
0   1    Alice   25
1   2      Bob   30
2   3  Charlie   35
   ID Department
0   1         HR
1   2         IT
ID Name Age Department
0 1 Alice 25 HR
1 2 Bob 30 IT

image.png

image.png
pd.merge(թրաշ, գլխի մազեր)

image.png

image.png
# DataFrame 1
df1 = pd.DataFrame({
    'ID': [1, 2, 3, 4],
    'Name': ['Alice', 'Bob', 'Charlie', 'David'],
    'Age': [25, 30, 35, 40]
})

# DataFrame 2
df2 = pd.DataFrame({
    'ID': [3, 4, 5, 6],
    'Department': ['HR', 'Finance', 'IT', 'Marketing'],
    'Salary': [50000, 60000, 70000, 80000]
})

print("DataFrame 1:\n", df1)
print("DataFrame 2:\n", df2)
DataFrame 1:
    ID     Name  Age
0   1    Alice   25
1   2      Bob   30
2   3  Charlie   35
3   4    David   40
DataFrame 2:
    ID Department  Salary
0   3         HR   50000
1   4    Finance   60000
2   5         IT   70000
3   6  Marketing   80000
result_inner = pd.merge(df1, df2, on='ID', how='inner')
print("Inner Join Result:\n", result_inner)
Inner Join Result:
    ID     Name  Age Department  Salary
0   3  Charlie   35         HR   50000
1   4    David   40    Finance   60000
result_outer = pd.merge(df1, df2, on='ID', how='outer')
print("Outer Join Result:\n", result_outer)
Outer Join Result:
    ID     Name   Age Department   Salary
0   1    Alice  25.0        NaN      NaN
1   2      Bob  30.0        NaN      NaN
2   3  Charlie  35.0         HR  50000.0
3   4    David  40.0    Finance  60000.0
4   5      NaN   NaN         IT  70000.0
5   6      NaN   NaN  Marketing  80000.0
result_left = pd.merge(df1, df2, on='ID', how='left')
print("Left Join Result:\n", result_left)
Left Join Result:
    ID     Name  Age Department   Salary
0   1    Alice   25        NaN      NaN
1   2      Bob   30        NaN      NaN
2   3  Charlie   35         HR  50000.0
3   4    David   40    Finance  60000.0
result_right = pd.merge(df1, df2, on='ID', how='right')
print("Right Join Result:\n", result_right)
Right Join Result:
    ID     Name   Age Department  Salary
0   3  Charlie  35.0         HR   50000
1   4    David  40.0    Finance   60000
2   5      NaN   NaN         IT   70000
3   6      NaN   NaN  Marketing   80000

Suffixes

df7 = pd.DataFrame({
    'ID': [1, 2, 3],
    'Name': ['Alice', 'Bob', 'Charlie'],
    'Age': [28, 35, 38]
})

print(df1)
print(df7)
# Merging with suffixes for overlapping columns
result = pd.merge(df1, df7, on='ID', suffixes=('_left', '_right'))
result
   ID     Name  Age
0   1    Alice   25
1   2      Bob   30
2   3  Charlie   35
3   4    David   40
   ID     Name  Age
0   1    Alice   28
1   2      Bob   35
2   3  Charlie   38
ID Name_left Age_left Name_right Age_right
0 1 Alice 25 Alice 28
1 2 Bob 30 Bob 35
2 3 Charlie 35 Charlie 38

Join

df8 = pd.DataFrame({
    'Salary': [50000, 60000, 70000]
}, index=[1, 2, 3])

# Joining DataFrames on index
print(df1)
print(df8)

result = df1.join(df8)
print(result)
   ID     Name  Age
0   1    Alice   25
1   2      Bob   30
2   3  Charlie   35
3   4    David   40
   Salary
1   50000
2   60000
3   70000
   ID     Name  Age   Salary
0   1    Alice   25      NaN
1   2      Bob   30  50000.0
2   3  Charlie   35  60000.0
3   4    David   40  70000.0
# Inner join (only matching indices)
result = df1.join(df8, how='inner')
print(result)

# Outer join (all rows, NaNs for non-matches)
result = df1.join(df8, how='outer')
print(result)
   ID     Name  Age  Salary
1   2      Bob   30   50000
2   3  Charlie   35   60000
3   4    David   40   70000
   ID     Name  Age   Salary
0   1    Alice   25      NaN
1   2      Bob   30  50000.0
2   3  Charlie   35  60000.0
3   4    David   40  70000.0

Append - Հնացած ա, նույնն ա ինչ ուղղակի տողերի concat-ը

result = df1.append(df2)
print(result)

result = pd.concat([df1, df2], axis=0)
print(result)
---------------------------------------------------------------------------
AttributeError                            Traceback (most recent call last)
~\AppData\Local\Temp\ipykernel_32508\1643112403.py in ?()
----> 1 result = df1.append(df2)
      2 print(result)
      3 
      4 result = pd.concat([df1, df2], axis=0)

c:\Users\hayk_\.conda\envs\lectures\lib\site-packages\pandas\core\generic.py in ?(self, name)
   6314             and name not in self._accessors
   6315             and self._info_axis._can_hold_identifiers_and_holds_name(name)
   6316         ):
   6317             return self[name]
-> 6318         return object.__getattribute__(self, name)

AttributeError: 'DataFrame' object has no attribute 'append'

Երբ որը օգտագործել

  • concat() - հասարակ տողեր/սյուներ ավելանցելու համար
  • merge() - ըստ ընդհանուր սյուների միավորումներ անելու համար
  • join() - ինդեքսով միավորելու, կամ merge գրել ալարելու դեպքում

Միշտ հիշեք ստուգել NA (Not available)-ներ առաջացել են թե չէ միավորումից հետո

Excel

!pip install uv
!uv pip install openpyxl
Using Python 3.10.18 environment at: C:\Users\hayk_\.conda\envs\lectures
Resolved 2 packages in 1.38s
Prepared 2 packages in 1.70s
Installed 2 packages in 277ms
 + et-xmlfile==2.0.0
 + openpyxl==3.1.5

Արհեստական տվյալների ստեղծում

import pandas as pd
import numpy as np
from datetime import datetime, timedelta

# Create a date range for one year of trading data (252 days)
date_range = pd.date_range(end=datetime.today(), periods=252, freq='B')

# Generate synthetic stock data for two different stocks
stock1 = pd.DataFrame({
    'date': date_range,
    'price': (np.random.rand(252) + 0.5).cumprod() * 100,
    'volume': np.random.randint(1000, 10000, 252)
}).set_index('date')

stock2 = pd.DataFrame({
    'date': date_range,
    'price': (np.random.rand(252) + 0.5).cumprod() * 200,
    'volume': np.random.randint(1000, 10000, 252)
}).set_index('date')

# Create a Pandas Excel writer using XlsxWriter as the engine
with pd.ExcelWriter('financial_data.xlsx', engine='openpyxl') as writer:
    # Write each DataFrame to a different worksheet
    stock1.to_excel(writer, sheet_name='Stock1')
    stock2.to_excel(writer, sheet_name='Stock2')

Reading Excel files

https://pandas.pydata.org/docs/reference/api/pandas.read_excel.html

df = pd.read_excel('financial_data.xlsx') # կարդումա առաջին sheetը
df
date price volume
0 2024-07-23 18:27:46.268 83.291510 7344
1 2024-07-24 18:27:46.268 103.498104 6112
2 2024-07-25 18:27:46.268 140.786008 2383
3 2024-07-26 18:27:46.268 92.593919 3448
4 2024-07-29 18:27:46.268 47.409393 5555
... ... ... ...
247 2025-07-03 18:27:46.268 0.002276 7439
248 2025-07-04 18:27:46.268 0.001610 8411
249 2025-07-07 18:27:46.268 0.001547 3468
250 2025-07-08 18:27:46.268 0.002221 8436
251 2025-07-09 18:27:46.268 0.002448 3467

252 rows × 3 columns

# Reading a specific sheet by its name
df = pd.read_excel('financial_data.xlsx', sheet_name='Stock2')
print(df.head())
# Reading a specific sheet by its index
df = pd.read_excel('financial_data.xlsx', sheet_name=1)
print(df.head())
                     date       price  volume
0 2024-07-23 18:27:46.268  127.596887    6301
1 2024-07-24 18:27:46.268  115.929836    2031
2 2024-07-25 18:27:46.268   71.762616    7162
3 2024-07-26 18:27:46.268   52.595189    2864
4 2024-07-29 18:27:46.268   58.587849    4034
                     date       price  volume
0 2024-07-23 18:27:46.268  127.596887    6301
1 2024-07-24 18:27:46.268  115.929836    2031
2 2024-07-25 18:27:46.268   71.762616    7162
3 2024-07-26 18:27:46.268   52.595189    2864
4 2024-07-29 18:27:46.268   58.587849    4034
# Reading a subset of columns by their names
df = pd.read_excel('financial_data.xlsx', usecols=['price', 'volume'])

print(df.head(1))

# Reading a subset of columns by Excel column letters
df = pd.read_excel('financial_data.xlsx', usecols='B,C')

print(df.head(1))
      price  volume
0  83.29151    7344
      price  volume
0  83.29151    7344
df = pd.read_excel("financial_data.xlsx", nrows=10, skiprows=[1,3,4])
df
date price volume
0 2024-07-24 18:27:46.268 103.498104 6112
1 2024-07-29 18:27:46.268 47.409393 5555
2 2024-07-30 18:27:46.268 40.650941 9911
3 2024-07-31 18:27:46.268 36.575252 7582
4 2024-08-01 18:27:46.268 46.275220 4444
5 2024-08-02 18:27:46.268 27.455644 4940
6 2024-08-05 18:27:46.268 38.418639 6160
7 2024-08-06 18:27:46.268 45.557481 9913
8 2024-08-07 18:27:46.268 53.532259 2306
9 2024-08-08 18:27:46.268 28.844730 5282

Writing to excel

df['price_in_AMD'] = df["price"] / 383
df
date price volume price_in_AMD
0 2024-07-24 18:27:46.268 103.498104 6112 0.270230
1 2024-07-29 18:27:46.268 47.409393 5555 0.123784
2 2024-07-30 18:27:46.268 40.650941 9911 0.106138
3 2024-07-31 18:27:46.268 36.575252 7582 0.095497
4 2024-08-01 18:27:46.268 46.275220 4444 0.120823
5 2024-08-02 18:27:46.268 27.455644 4940 0.071686
6 2024-08-05 18:27:46.268 38.418639 6160 0.100310
7 2024-08-06 18:27:46.268 45.557481 9913 0.118949
8 2024-08-07 18:27:46.268 53.532259 2306 0.139771
9 2024-08-08 18:27:46.268 28.844730 5282 0.075313
df.to_excel("file.xlsx", sheet_name='բաժնետոմս 1')
df.to_excel("file_no_index.xlsx", sheet_name='բաժնետոմս 1', index=False)

Multiple sheets

with pd.ExcelWriter('two_sheets.xlsx') as writer:
    df.to_excel(writer, sheet_name='բաժնետոմսեր')
    df.sample(10).to_excel(writer, sheet_name='Պատահական 10 տող', index=False)

html

!uv pip install lxml
Using Python 3.10.18 environment at: C:\Users\hayk_\.conda\envs\lectures
Resolved 1 package in 741ms
Downloading lxml (3.8MiB)
 Downloading lxml
Prepared 1 package in 2.41s
Installed 1 package in 262ms
 + lxml==6.0.0
!pip install html5lib
url_women = "https://armstat.am/am/?nid=12&id=19044&submit=%D5%93%D5%B6%D5%BF%D6%80%D5%A5%D5%AC"
url_men = "https://armstat.am/am/?nid=12&id=19045&submit=%D5%93%D5%B6%D5%BF%D6%80%D5%A5%D5%AC"

df_women = pd.read_html(url_women)
df_men = pd.read_html(url_men)
type(df_women)
list
df_women[1]
թվական բացարձակ արժեք նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)
0 2023 46728.0 103.0
1 2022 45373.0 145.6
2 2021 31171.0 70.5
3 2020 44187.0 106.5
4 2019 41486.0 95.6
5 2018 43390.0 88.0
6 2017 49327.0 97.7
7 2016 50463.0 94.1
8 2015 53601.0 104.9
9 2014 41579.0 92.8
10 2013 55044.0 99.6
11 2012 55246.0 94.1
12 2011 58679.0 89.3
13 2010 65678.0 97.8
14 2009 67177.0 102.4
15 2008 65618.0 102.4
16 2007 64099.0 105.9
17 2006 60549.0 108.8
18 2005 55640.0 113.1
19 2004 49178.0 109.8
20 2003 44780.0 111.8
21 2002 40067.0 108.2
22 2001 37026.0 111.1
23 2000 33325.0 99.8
df_men
թվական բացարձակ արժեք նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)
0 2023 33367.0 97.7
1 2022 34140.0 72.0
2 2021 47432.0 134.0
3 2020 35403.0 105.8
4 2019 33456.0 90.2
5 2018 37087.0 90.0
6 2017 41213.0 97.9
7 2016 42095.0 98.1
8 2015 42901.0 99.8
9 2014 38044.0 93.9
10 2013 45810.0 97.5
11 2012 47004.0 97.6
12 2011 48176.0 86.5
13 2010 55669.0 98.5
14 2009 56533.0 101.3
15 2008 55826.0 106.4
16 2007 52489.0 106.2
17 2006 49427.0 108.2
18 2005 45661.0 117.2
19 2004 38961.0 109.2
20 2003 35694.0 104.7
21 2002 34087.0 112.4
22 2001 30320.0 110.7
23 2000 27401.0 96.6
df_men = df_men[1]
df_women = df_women[1]

melt

pd.merge(df_men, df_women, on="թվական", how="outer")
թվական բացարձակ արժեք_x նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)_x բացարձակ արժեք_y նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)_y
0 2000 27401.0 96.6 33325.0 99.8
1 2001 30320.0 110.7 37026.0 111.1
2 2002 34087.0 112.4 40067.0 108.2
3 2003 35694.0 104.7 44780.0 111.8
4 2004 38961.0 109.2 49178.0 109.8
5 2005 45661.0 117.2 55640.0 113.1
6 2006 49427.0 108.2 60549.0 108.8
7 2007 52489.0 106.2 64099.0 105.9
8 2008 55826.0 106.4 65618.0 102.4
9 2009 56533.0 101.3 67177.0 102.4
10 2010 55669.0 98.5 65678.0 97.8
11 2011 48176.0 86.5 58679.0 89.3
12 2012 47004.0 97.6 55246.0 94.1
13 2013 45810.0 97.5 55044.0 99.6
14 2014 38044.0 93.9 41579.0 92.8
15 2015 42901.0 99.8 53601.0 104.9
16 2016 42095.0 98.1 50463.0 94.1
17 2017 41213.0 97.9 49327.0 97.7
18 2018 37087.0 90.0 43390.0 88.0
19 2019 33456.0 90.2 41486.0 95.6
20 2020 35403.0 105.8 44187.0 106.5
21 2021 47432.0 134.0 31171.0 70.5
22 2022 34140.0 72.0 45373.0 145.6
23 2023 33367.0 97.7 46728.0 103.0
df = pd.merge(df_men, df_women, on="թվական", how="outer", suffixes=('_men', "_women"))
df
թվական բացարձակ արժեք_men նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)_men բացարձակ արժեք_women նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)_women
0 2000 27401.0 96.6 33325.0 99.8
1 2001 30320.0 110.7 37026.0 111.1
2 2002 34087.0 112.4 40067.0 108.2
3 2003 35694.0 104.7 44780.0 111.8
4 2004 38961.0 109.2 49178.0 109.8
5 2005 45661.0 117.2 55640.0 113.1
6 2006 49427.0 108.2 60549.0 108.8
7 2007 52489.0 106.2 64099.0 105.9
8 2008 55826.0 106.4 65618.0 102.4
9 2009 56533.0 101.3 67177.0 102.4
10 2010 55669.0 98.5 65678.0 97.8
11 2011 48176.0 86.5 58679.0 89.3
12 2012 47004.0 97.6 55246.0 94.1
13 2013 45810.0 97.5 55044.0 99.6
14 2014 38044.0 93.9 41579.0 92.8
15 2015 42901.0 99.8 53601.0 104.9
16 2016 42095.0 98.1 50463.0 94.1
17 2017 41213.0 97.9 49327.0 97.7
18 2018 37087.0 90.0 43390.0 88.0
19 2019 33456.0 90.2 41486.0 95.6
20 2020 35403.0 105.8 44187.0 106.5
21 2021 47432.0 134.0 31171.0 70.5
22 2022 34140.0 72.0 45373.0 145.6
23 2023 33367.0 97.7 46728.0 103.0
df.columns
Index(['թվական', 'բացարձակ արժեք_men',
       'նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)_men',
       'բացարձակ արժեք_women',
       'նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)_women'],
      dtype='object')
df.drop(columns=['նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)_men',
                 'նախորդ տարվա համապատասխան ժամանակաշրջանի նկատմամբ (%)_women'], 
        inplace=True)
df.columns
Index(['թվական', 'բացարձակ արժեք_men', 'բացարձակ արժեք_women'], dtype='object')
df.rename(columns={"թվական": "year",
                   "բացարձակ արժեք_men": "men", 
                   "բացարձակ արժեք_women": "women"}, inplace=True)
df
year men women
0 2000 27401.0 33325.0
1 2001 30320.0 37026.0
2 2002 34087.0 40067.0
3 2003 35694.0 44780.0
4 2004 38961.0 49178.0
5 2005 45661.0 55640.0
6 2006 49427.0 60549.0
7 2007 52489.0 64099.0
8 2008 55826.0 65618.0
9 2009 56533.0 67177.0
10 2010 55669.0 65678.0
11 2011 48176.0 58679.0
12 2012 47004.0 55246.0
13 2013 45810.0 55044.0
14 2014 38044.0 41579.0
15 2015 42901.0 53601.0
16 2016 42095.0 50463.0
17 2017 41213.0 49327.0
18 2018 37087.0 43390.0
19 2019 33456.0 41486.0
20 2020 35403.0 44187.0
21 2021 47432.0 31171.0
22 2022 34140.0 45373.0
23 2023 33367.0 46728.0
long = pd.melt(df, id_vars=['year'], value_vars=['men','women'], 
               var_name="gender", value_name="students")
long
year gender students
0 2000 men 27401.0
1 2001 men 30320.0
2 2002 men 34087.0
3 2003 men 35694.0
4 2004 men 38961.0
5 2005 men 45661.0
6 2006 men 49427.0
7 2007 men 52489.0
8 2008 men 55826.0
9 2009 men 56533.0
10 2010 men 55669.0
11 2011 men 48176.0
12 2012 men 47004.0
13 2013 men 45810.0
14 2014 men 38044.0
15 2015 men 42901.0
16 2016 men 42095.0
17 2017 men 41213.0
18 2018 men 37087.0
19 2019 men 33456.0
20 2020 men 35403.0
21 2021 men 47432.0
22 2022 men 34140.0
23 2023 men 33367.0
24 2000 women 33325.0
25 2001 women 37026.0
26 2002 women 40067.0
27 2003 women 44780.0
28 2004 women 49178.0
29 2005 women 55640.0
30 2006 women 60549.0
31 2007 women 64099.0
32 2008 women 65618.0
33 2009 women 67177.0
34 2010 women 65678.0
35 2011 women 58679.0
36 2012 women 55246.0
37 2013 women 55044.0
38 2014 women 41579.0
39 2015 women 53601.0
40 2016 women 50463.0
41 2017 women 49327.0
42 2018 women 43390.0
43 2019 women 41486.0
44 2020 women 44187.0
45 2021 women 31171.0
46 2022 women 45373.0
47 2023 women 46728.0
long.groupby('year')["students"].sum().plot()

long
             students
year gender          
2000 men      27401.0
     women    33325.0
2001 women    37026.0
     men      30320.0
2002 men      34087.0
     women    40067.0
2003 women    44780.0
     men      35694.0
2004 men      38961.0
     women    49178.0
2005 women    55640.0
     men      45661.0
2006 men      49427.0
     women    60549.0
2007 women    64099.0
     men      52489.0
2008 men      55826.0
     women    65618.0
2009 women    67177.0
     men      56533.0
2010 men      55669.0
     women    65678.0
2011 women    58679.0
     men      48176.0
2012 men      47004.0
     women    55246.0
2013 women    55044.0
     men      45810.0
2014 men      38044.0
     women    41579.0
2015 women    53601.0
     men      42901.0
2016 women    50463.0
     men      42095.0
2017 men      41213.0
     women    49327.0
2018 women    43390.0
     men      37087.0
2019 men      33456.0
     women    41486.0
2020 women    44187.0
     men      35403.0
2021 men      47432.0
     women    31171.0
2022 women    45373.0
     men      34140.0
2023 men      33367.0
     women    46728.0

Dask

  • https://www.dask.org/
  • https://docs.dask.org/en/stable/dataframe.html

https://colab.research.google.com/drive/19X1gECPhcqUfACZQgU0-HtbPf_j1lrxj?usp=sharing

!conda install dask
^C
import dask.dataframe as dd
url = "https://raw.githubusercontent.com/mwaskom/seaborn-data/master/tips.csv"

tips = dd.read_csv(url)       # Parallelized under the hood

print(tips.columns)
tips.total_bill.describe()#.compute()

Datetime

import matplotlib.cbook as cbook

with cbook.get_sample_data("msft.csv") as fp:
    msft = pd.read_csv(fp)
msft
Date Open High Low Close Volume Adj. Close*
0 19-Sep-03 29.76 29.97 29.52 29.96 92433800 29.79
1 18-Sep-03 28.49 29.51 28.42 29.50 67268096 29.34
2 17-Sep-03 28.76 28.95 28.47 28.50 47221600 28.34
3 16-Sep-03 28.41 28.95 28.32 28.90 52060600 28.74
4 15-Sep-03 28.37 28.61 28.33 28.36 41432300 28.20
... ... ... ... ... ... ... ...
60 25-Jun-03 25.64 25.99 25.14 25.26 60483500 25.12
61 24-Jun-03 25.65 26.04 25.52 25.70 51820300 25.56
62 23-Jun-03 26.14 26.24 25.49 25.78 52584500 25.64
63 20-Jun-03 26.34 26.38 26.01 26.33 86048896 26.18
64 19-Jun-03 26.09 26.39 26.01 26.07 63626900 25.92

65 rows × 7 columns

msft["Date"] = pd.to_datetime(msft["Date"])        # parse strings → Timestamp
msft 
C:\Users\hayk_\AppData\Local\Temp\ipykernel_32508\50020301.py:1: UserWarning: Could not infer format, so each element will be parsed individually, falling back to `dateutil`. To ensure parsing is consistent and as-expected, please specify a format.
  msft["Date"] = pd.to_datetime(msft["Date"])        # parse strings → Timestamp
Date Open High Low Close Volume Adj. Close*
0 2003-09-19 29.76 29.97 29.52 29.96 92433800 29.79
1 2003-09-18 28.49 29.51 28.42 29.50 67268096 29.34
2 2003-09-17 28.76 28.95 28.47 28.50 47221600 28.34
3 2003-09-16 28.41 28.95 28.32 28.90 52060600 28.74
4 2003-09-15 28.37 28.61 28.33 28.36 41432300 28.20
... ... ... ... ... ... ... ...
60 2003-06-25 25.64 25.99 25.14 25.26 60483500 25.12
61 2003-06-24 25.65 26.04 25.52 25.70 51820300 25.56
62 2003-06-23 26.14 26.24 25.49 25.78 52584500 25.64
63 2003-06-20 26.34 26.38 26.01 26.33 86048896 26.18
64 2003-06-19 26.09 26.39 26.01 26.07 63626900 25.92

65 rows × 7 columns

msft.set_index("Date", inplace=True) 
msft
Open High Low Close Volume Adj. Close*
Date
2003-09-19 29.76 29.97 29.52 29.96 92433800 29.79
2003-09-18 28.49 29.51 28.42 29.50 67268096 29.34
2003-09-17 28.76 28.95 28.47 28.50 47221600 28.34
2003-09-16 28.41 28.95 28.32 28.90 52060600 28.74
2003-09-15 28.37 28.61 28.33 28.36 41432300 28.20
... ... ... ... ... ... ...
2003-06-25 25.64 25.99 25.14 25.26 60483500 25.12
2003-06-24 25.65 26.04 25.52 25.70 51820300 25.56
2003-06-23 26.14 26.24 25.49 25.78 52584500 25.64
2003-06-20 26.34 26.38 26.01 26.33 86048896 26.18
2003-06-19 26.09 26.39 26.01 26.07 63626900 25.92

65 rows × 6 columns

msft.columns
Index(['Open', 'High', 'Low', 'Close', 'Volume', 'Adj. Close*'], dtype='object')
msft.drop(columns=["High", "Low", "Open", "Volume", "Adj. Close*"], inplace=True)
msft["Year"]     = msft.index.year          # 2003
msft["Weekday"]  = msft.index.day_name()    # “Monday” …
msft 
Close Year Weekday
Date
2003-09-19 29.96 2003 Friday
2003-09-18 29.50 2003 Thursday
2003-09-17 28.50 2003 Wednesday
2003-09-16 28.90 2003 Tuesday
2003-09-15 28.36 2003 Monday
... ... ... ...
2003-06-25 25.26 2003 Wednesday
2003-06-24 25.70 2003 Tuesday
2003-06-23 25.78 2003 Monday
2003-06-20 26.33 2003 Friday
2003-06-19 26.07 2003 Thursday

65 rows × 3 columns

monthly = msft["Close"].resample("M").mean()
monthly
C:\Users\hayk_\AppData\Local\Temp\ipykernel_32508\2846096206.py:1: FutureWarning: 'M' is deprecated and will be removed in a future version, please use 'ME' instead.
  monthly = msft["Close"].resample("M").mean()
Date
2003-06-30    25.770000
2003-07-31    26.799545
2003-08-31    26.038571
2003-09-30    28.466429
Freq: ME, Name: Close, dtype: float64

Vectorization

import numpy as np
import pandas as pd

import math
import timeit

# ---------- Setup ----------
n = 1_000_000  # one‑million‑row Series
s = pd.Series(np.random.rand(n))

# ---------- Three approaches ----------
def vectorized(series):
    return np.log1p(series)          # NumPy ufunc (C speed)

def apply_method(series):
    return series.apply(math.log1p)  # Pandas .apply (per‑row call)

def python_loop(series):
    return pd.Series([math.log1p(x) for x in series], index=series.index)

# ---------- Benchmark helper ----------
def avg_seconds(func, series, reps=5, runs=3):
    times = timeit.repeat(lambda: func(series), repeat=reps, number=runs)
    return np.mean(times) / runs     # average seconds per single run

avg_vec   = avg_seconds(vectorized, s)
avg_apply = avg_seconds(apply_method, s)
avg_loop  = avg_seconds(python_loop, s)

# ---------- Summarize ----------
summary = pd.DataFrame({
    "Method": ["Vectorized (NumPy)", "Series.apply()", "Python loop"],
    "Avg seconds per run": [round(avg_vec, 4), round(avg_apply, 4), round(avg_loop, 4)],
    "Relative to vectorized": [1.0,
                               round(avg_apply / avg_vec, 1),
                               round(avg_loop / avg_vec, 1)],
})

print(f"• .apply is ~{avg_apply/avg_vec:.0f}× slower than vectorized, "
      f"but ~{avg_loop/avg_apply:.0f}× faster than a pure Python loop.")

summary
• .apply is ~11× slower than vectorized, but ~2× faster than a pure Python loop.
Method Avg seconds per run Relative to vectorized
0 Vectorized (NumPy) 0.0326 1.0
1 Series.apply() 0.3627 11.1
2 Python loop 0.8761 26.9

Բութ մատի օրենք > Vectorize if you can, .apply if you must, loop only when there’s no other way.

Profiling

!uv pip install sweetviz
# !pip install -U ydata-profiling
Using Python 3.10.18 environment at: C:\Users\hayk_\.conda\envs\lectures
Audited 1 package in 61ms
  • Sweetwiz - https://github.com/fbdesignpro/sweetviz
  • Pandas Profiling - https://docs.profiling.ydata.ai/latest/
from seaborn import load_dataset

df = load_dataset("penguins")
df
species island bill_length_mm bill_depth_mm flipper_length_mm body_mass_g sex
0 Adelie Torgersen 39.1 18.7 181.0 3750.0 Male
1 Adelie Torgersen 39.5 17.4 186.0 3800.0 Female
2 Adelie Torgersen 40.3 18.0 195.0 3250.0 Female
3 Adelie Torgersen NaN NaN NaN NaN NaN
4 Adelie Torgersen 36.7 19.3 193.0 3450.0 Female
... ... ... ... ... ... ... ...
339 Gentoo Biscoe NaN NaN NaN NaN NaN
340 Gentoo Biscoe 46.8 14.3 215.0 4850.0 Female
341 Gentoo Biscoe 50.4 15.7 222.0 5750.0 Male
342 Gentoo Biscoe 45.2 14.8 212.0 5200.0 Female
343 Gentoo Biscoe 49.9 16.1 213.0 5400.0 Male

344 rows × 7 columns

import sweetviz as sv

report = sv.analyze(df)
report.show_html("penguins_report.html")
my_report = sv.compare_intra(df, df["sex"] == "Male", ["Male", "Female"])
from ydata_profiling import ProfileReport

profile = ProfileReport(df, title="EDA report", explorative=True, )
profile.to_file("ydata_report.html")        # standalone HTML
profile.to_widgets()                        # Jupyter widgets

ՉՄՈՌԱՆԱԼ - անունների պրոեկտ ռեպո

🏡Տնային

Վերցնել ցանկցած դատասեթ ու փորփրել։

Կարող եք դատան վերցնել Kaggle-ից։ Կամ եթե հայկական եք ուզում՝ Armstat-ից

🎲 22 (04)

Flag Counter