Python: TOP 10 skorelowanych kolumn

2024-07-07

W analizie danych zależy nam na wykryciu ukrytych relacji między różnymi cechami danych. Pomocne są w tym wykresy w rodzaju „heat-map” i wszystko ładnie, póki dane, które przetwarzamy są w miarę małe. A co jeśli mamy, dajmy na to 100 kolumn? Oczywiście znajdowanie najbardziej skorelowanych danych i wybieranie tych najbardziej skorelowanych da się zautomatyzować. Zobaczymy taki przykład:

import pandas as pd
import numpy as np
# Create a sample DataFrame (replace with your actual data)
shape = (50, 100) # 50 rows, 100 columns
data = np.random.normal(size=shape)
data[:, 10] += data[:, 20]
# Introduce some correlation
df = pd.DataFrame(data)

Ten przykładowy zestaw danych ma 50 wierszy i 100 kolumn. Część kolumn została ze sobą sztucznie skorelowana. W następnym kroku możemy wyznaczyć macierz korelacji:

# Calculate the correlation matrix
correlation_matrix = df.corr().abs()

Ta macierz ma już 100 wierszy i 100 kolumn. Trudno by było jednak wyszukiwać maksymalnej wartości w tablicy 100×100. Łatwiej będziem jeśli wszystkie wartości umieścimy w jednej kolumnie

Pobawmy się tą tablicą korelacji, nim zbudujemy finalne rozwiazanie. Pozwoli to nam zrozumieć, co tutaj pod spodem się dzieje. To polecenie zamieni tablicę 100×100 na tablicę z indeksem, jedną kolumną i 10000 wierszami.

correlation_matrix.unstack()

Ten obiekt ma też ciekawy indeks, tzw. multiindeks:

correlation_matrix.unstack().index

Wygląda on mniej więcej tak:

MultiIndex([( 0,  0),
            ( 0,  1),
            ( 0,  2),
            ( 0,  3),
            ( 0,  4),
            ( 0,  5),
            ( 0,  6),
            ( 0,  7),
            ( 0,  8),
            ( 0,  9),
            ...
            (99, 90),
            (99, 91),
            (99, 92),
            (99, 93),
            (99, 94),
            (99, 95),
            (99, 96),
            (99, 97),
            (99, 98),
            (99, 99)],
           length=10000)

Każdy wiersz tej dłuuugiej listy jest adresowany dwiema wartościami, które odpowiadają numerowi wiersza i numerowi kolumny z oryginalnego data frame, od którego wystartowaliśmy.

Nas interesują najbardziej skorelowane kolumny, dlatego posortujemy dane w oparciu o wartości, pewnie wolelibyśmy też widzieć największe wartości na początku:

correlation_matrix.unstack().sort_values(kind="quicksort", ascending=False)

Wynik wygląda mniej więcej tak:

46  46    1.000000
99  99    1.000000
0   0     1.000000
45  45    1.000000
26  26    1.000000
            ...   
81  95    0.000093
21  75    0.000010
75  21    0.000010
19  70    0.000001
70  19    0.000001
Length: 10000, dtype: float64

Jak widać największa korelacja pojawia się między kolumną a nią samą… w wyjściowej matrycy korelacji te wartości znajdowały się na przekątnej. Mają one numer wiersza i kolumny taki sam. Trzeba by je wykluczyć. Na dodatek, matryca korelacji wykazuje taką samą wartość dla kolumn 3 i 13 oraz 13 i 3. Dlatego możnaby wyrzucić z danych jakie będziemy analizować te wartości, które znajdowałyby się na przekątnej lub są wartościami zdublowanymi:

m = correlation_matrix.unstack()
first = m[m.index.get_level_values(0) < m.index.get_level_values(1)]

No to teraz już będzie z górki. Wystarczy posortować dane, tak jak robiliśmy to wcześniej i wybrać tych dajmy na to 10 „naj”:

first.sort_values(kind=”quicksort”, ascending=False).head(10)

Oto wynik:

10  20    0.839781
13  36    0.485660
40  52    0.481521
11  77    0.479348
26  66    0.474195
69  93    0.471580
20  26    0.462138
53  72    0.456067
47  94    0.444600
8   74    0.443435
dtype: float64
By Rafał Kraik in SQL

Python: Pandas: melt na kolumnie z multi-indeksem

2024-07-02

Załóżmy, że dotarły do nas dane w takiej oto postaci:

Mamy więc „sztuczny” indeks wierszy 'MF’ o wartościach 0,1,2,3,4 oraz kolumny, które są opisane muli-indeksem.

  • piersza kolumna to („Age”,), bo jakakolwiek nazwa pojawia się tylko w zerowym poziomie nagłówka.
  • druga kolumna to („HalfSeconds”,”F”),
  • trzecia to („HalfSeconds”,”M”),
  • czwarta to („TotalSeconds”,”F”)
  • i ostatnia to („TotalSeconds”,”M”).

Chcielibyśmy taką pivot-table czyli tabelę przestawną „odpivotować” i zobaczyć ją w tzw. długim formacie:

Jeśli chcesz samodzilnie sobie takie dane wyczarować to użyj poniższego kodu:

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

df = pd.read_csv('./marathon_results_2016.csv',
index_col='Bib',
usecols=['Bib','40K','Half','Pace','Age','M/F',
'Country','State','City'])

df['40K'] = df['40K'].apply(pd.to_timedelta, errors='coerce')
df['Half'] = df['Half'].apply(pd.to_timedelta, errors='coerce')
df = df[df['40K'].notna() & df['Half'].notna()]
df['TotalSeconds'] = df['40K'].apply(lambda x: timedelta.total_seconds(x))
df['HalfSeconds'] = df['Half'].apply(lambda x: timedelta.total_seconds(x))

df = df.pivot_table(index="Age",columns="M/F",values="TotalSeconds")

df.reset_index(inplace=True)
df.head()

Plik zdanymi można pobrać stąd

W wersji Pandasa 2.2.0 dało się bez problemu uruchomić polecenie:

df.melt(id_vars="Age", value_name='Time')

Niestety, coś tam chłopaki namieszali: https://github.com/pandas-dev/pandas/issues/57663 i komenda kończy się błędem:

KeyError: „The following id_vars or value_vars are not present in the DataFrame: [’Age’]”


Wprawdzie w wersji 2.2.2 problem miał być rzekomo usunięty, ale u mnie nadal występuje. Ponieważ ostatnie czego bym chciał, to uzależniać działanie od tego w jakiej wersji bibliotek ten program jest uruchamiany, a może jeszcze nakłaniać do korzystania ze starych bibliotek, bo na nowych coś nie działa, to proponuję przekształcenie danych. Zobacz jakie:

Błąd KeyError poniekad ma rację. W kolumnie widocznej jako Age, kluczem jest („Age”,) i jakby nie patrzeć nie jest to po prostu napis „Age”. Może wobec tego by tak przed „odpiwotowaniem” spłaszczyć ten multiindex? No właśnie, da się to zrobić!

Jest sobie sprytna metoda to_flat_index, powoduje, że MultiIndex zostanie zamieniony na Index. Pozycjami nadal są tuple, ale przynajmniej pozbyliśmy się tego „Multi”:


Ale to jest ciągle coś dziwnego! Chcielibyśmy w kolumnach widzieć po prostu napisy. Da się to zrobić!

W następnym kroku można użyć str i wyciągnąć z tego obiektu wartości zrzutowane na string i połączyć je ze sobą pustym napisem. Oto, co dostaniemy patrząc tylko na wynik:

O rety! Mamy po prostu napisy! Tak, to jest to, czego nam było trzeba. Dlatego do osiągnięcia pożądanej formy „odpivotowanej” tabeli można teraz użyć kodu:

df.columns = df.columns.to_flat_index().str.join(”)
df.melt(id_vars=”Age”, value_name=’Time’).head()

No i proszę – trochę na piechotę, ale przynajmniej bez dodawania w instrukcji informacji „upewnij się, że pracujesz ze starą wersją Pandasa”.

By Rafał Kraik in Python

Python: jak zainstalować moduł (np. requests) w PyCharm

2024-06-26

Doinstalowywanie oprogramowania do Pythona jest proste, o ile się wie jak to robić, a przecież na początku nie wie się niczego. Spróbujmy więc krok po kroku zobaczyć, jak w PyCharm, w zupełnie nowym projekcie zaistalować moduł na przykładzie requests:

Na początku wybrałem polecenie „New project”

1 – nazywam projekt „jakoś tam”
2 – kontrolnie patrzę na ścieżkę, jakby trzeba było, to mogę ją zmienić
3 – tu też nic nie trzeba zmieniać, ale warto to zauważyć, że jest tworzone środowisko wirtualne
4 – na dole widać też pełną ścieżkę
5 – No i pozostaje kliknąć „Create”

Co to jest to dziwne środowisko wirtualne? Otóż jest to całkiem normalne, że programiści pracują nad różnymi projektami. Jedne wymagają takich modułów a inne innych. Na dodatek, niektóre starsze projekty będą wymagały dodatkowych modułów w nieco starszej wersji, a inne projekty będą wymagały tych samych modułów, ale w nowszej wersji. Gdyby wszystko tak po prostu intalować na komputerze, to szybko zrobiłby się bałagan i albo te starsze albo te nowsze projekty by nie działały. Dlatego wymyślono środowisko wirtualne. Jest to minimalny (choć duży) zbiór plików, który zapewnia stabilne środowisko dla tworzonego projektu. Jeśli mając to środowisko aktywne doinstalujesz jakiś moduł, to będzie on widoczny tylko w tym projekcie. Inne projekty będą miały swoje środowiska wirtualne i swoje wersje wymaganych modułów.

Idźmy dalej:

Podczas tworzenia projektu może na dłużej lub krócej mignąć takie właśnie okienko. Informuje ono o tworzeniu środowiska wirtualnego. Domyślnie zostanie ono zapisane w podkatalogu projektu. Ten podkatalog nazywa sie .env (tak! z kropką na początku)

Kiedy projekt się już utworzy zobaczysz mniej więcej to:

1 – W podkatalogu projektu znajdziesz podkatalog .env – teraz już wiesz, co to jest
2 – Przy pomocy menu kontekstowego możesz dodać
3 – plik pythona do swojego projektu. Ten plik nazwij, jak tam sobie uważasz

Co my tu teraz mamy:

1 – w treści pliku skorzystajmy z modułu, który niestety jeszcze nie jest zainstalowany. Z tego powodu „requests” jest podkreślone na czerwono
2 – na dole można kliknąć w „terminal” co wyświetli dolne okienko
3 – automatycznie w tym terminalu powinno się również aktywować środowisko wirtualne. Rozpoznasz to po napisie (.venv) na początku linijki
4 – ten napis (.venv) powinien być taki sam, jak nazwa podkatalogu
5 – teraz w terminalu można wpisać polecenie instalujące moduł requests:

pip install requests

Poleceniem do instalacji modułów jest pip. Dzięki temu, że to polecenie jest uruchamiane w środowisku wirtualnym .venv to ta instalacja nie wpłynie na pracę innych projektów, które powinny być skonfigurowane do pracy ze swoimi środowiskami

1 – kiedy instalacja się zakończy, powinien wyświetlić się komunikat o sukcesie. Może on być nieco ukryty między innymi komunikatami, więc dobrze go wypatrz. Gdyby nie było sukcesu tylko porażka, to zostanie też wyświetlony komunikat, który pozwoli dalej badać sprawę i rozwiązywać problemy
2 – może nie od razu, ale po jakieś chwili, powiedzmy po 30 – 60 sekundach słowo „requests” w edytorze kodu powinno już nie być podświetlone.
3 – wtedy można uruchomić skrypt. Poprawny wynik w przypadku naszego prymitywnego skryptu to „Process finished with exit code 0”

By Rafał Kraik in Python

Azure: Bicep – instalacja

2024-06-20

Bicep to łatwiejszy, od typowego ARM, sposób na definiowanie zasobów Azurowych za pomocą kodu. W odróżnieniu od np. Terraforma, Bicep działa tylko dla Azure, oraz praktycznie nie wymaga instalacji dodatkowego oprogramowania. No to jak go zainstalować?

  • Zacznijmy od rzeczy opcjonalnej. Pisząc skrypty Bicep fajnie jest używać wygodnego edytora. Dlatego warto zainstalować rozszerznie Bicep dla Visual Studio Code. Wybieramy oczywiście narzędzie opublikowane przez Microsoft
  • Druga sprawa to instalacja Bicepa, tylko, że instalacja nie odbywa sie poprzez uruchomienie jakiegoś dodatkowego programu. Zakładając, że masz już na swoim komputerze AZ CLI, to wystarczy wykonać polecenie:
  • az bicep install
  • Wersję Bicepa można sprawdzić uruchamiając:
  • az bicep version
  • Powyższe polecenia zadziałają tylko jeśli AZ CLI jest w odpowiednio wysokiej wersji – ale utrzymywanie na komputerze nowej wersji oprogramowania to chyba dość naturalny krok
By Rafał Kraik in Azure

Windows: Duży folder winSxS

2024-06-16

Na systemie Windows, każda kolejna aktualizacja dostarcza nowe pliki, które zamieniają stare pliki – to oczywiste, trzeba stare błędy zamienić nowymi 😉

Pliki dostarczane w aktualizacjach zapisują się w katalogu winSxS, który z czasem może urosnąć do sporych rozmiarów. Nie zaleca się wykasowania tych plików, ale można je już „na stałe” wbudować we wzorcowy system windows. Służy do tego komenda:

Dism.exe /online /Cleanup-Image /StartComponentCleanup

Komendę należy uruchomić jako administrator. Niestety, czasami można w efekcie zobaczyć komunikat:

The operation could not be completed due to pending operations.

W takim przypadku można spróbować:

  • uruchomić komputer ponownie (a jakże – przecież to Windows!). Ma to na celu zakończenie ciągle jeszcze niedokończonych operacji
  • wycofać takie niedokończone operacje posługując się poleceniem:
    Dism.exe /online /Cleanup-Image /StartComponentCleanup /RevertPendingActions
    (a po tej operacji uruchomić ponownie komputer – a jakże – to Windows!)

W moim przypadku te kroki pomogły. Można było wyczyścić spory katalog winSxS i odzyskać nieco przestrzeni dyskowej i przy okazji przyśpieszyć komputer.

By Rafał Kraik in Helpdesk

Linux: Hash hasła

2024-05-07

W Linuxie nowego użytkownika dodasz komendą

adduser new_user_name

Jedna z opcji tego polecenia pozwala na przesłanie hasła, ale to hasło nie jest w postaci tekstu, tylko w postaci zahaszowanej. A jak taki hash uzyskać? Można tak:

pass=$(echo „Pa$$w0rd” | openssl passwd -1 -stdin)

Korzystamy tu z polecenia openssl, które

  • wygeneruje hash hasła (słowo passwd)
  • hasło będzie hashowane algorytmem MD5 (-1), a gdyby przesłać parameter -6, to były to algorytm SHA512
  • hasło czyta ze standardowego wejścia. Tutaj tym standardowym wejściem jest komenda echo
  • hash będzie zapisany w zmiennej pass

Teraz więc można już utworzyć użytkownika z hasłem:

sudo adduser -m -p „$pass” $u

No i uwaga – zdecydowanie nie jest to zalecane rozwiązanie, bo… jeśli ktoś będzie sprawdzał jakie komendy są uruchamiane w czasie, kiedy ta komenda będzie uruchamiana to może przechwycić hash hasła, a stąd już otwiera sie droga do złamania hasła w oparciu o hash, ale w pewnych sytuacjach takie podejście też się może przydać 😉

By Rafał Kraik in Linuxy

Visual Studio Code pyta o konto GitHub

2024-05-06

Po reinstalacji systemu się zaczęło… za każdym razem, kiedy trzeba było skomunikować sie z GitHubem: fetch, pull, push… pojawiało się okienko pytające (zresztą bardzo uprzejmie) o to, które konto GitHub powinno być wykorzystane.

Przyczyna jest taka, że rzeczywiście w ramach różnych projektów wykorzystywałem różne konta GitHub. Tymczasem podczas połączenia w remote pojawiał się po prostu namiar na repo na github:

git remote -v
origin https://github.com/org/repo.git (fetch)
origin https://github.com/org/repo.git (push)

Jakby tu dodać informacje o użytkowniku? Da się! Trzeba tylko przedefiniować remote:

git remote set-url origin https://user-name@github.com/org/repo.git

Po tej zmianie git remote -v zwraca już poprawne wartości:

git remote -v
origin https://user-name@github.com/org/repo.git (fetch)
origin https://user-name@github.com/org/repo.git (push)

a Visual Studio Code przestalo pytac o uzytkownika!

By Rafał Kraik in Git