<jupyter_start><jupyter_text>Introducere în Data Science: Laboratorul 2([https://github.com/MateiSirbu/IDS_Sirbu_Tataru/tree/master/Laborator2](https://github.com/MateiSirbu/IDS_Sirbu_Tataru/tree/master/Laborator2))<NAME>, _grupa 10LF383_Tătaru Dragoș Cătălin, _grupa 10LF383_ 1. (0.5 puncte) Pentru un vector NumPy dat, sa se determine care sunt elementele unice, in ordine descrescatoare. Exemplu: pentru `x = np.array([-4, 3,  5, 3, 2, 1, -3, -4, 2, -4])` functia scrisa de dvs va intoarce rezultatul `[ 5,  3,  2,  1, -3, -4]`.2. (0.5 puncte) Pentru un vector NumPy dat, sa se determine care e elementul cel mai frecvent si cel mai putin frecvent (tuplu de 2 valori). Daca exista mai multe numere cele mai frecvente (cele mai putin frecvente), se va raporta oricare din ele. Exemplu: pentru `x = np.array([-4, 3,  5, 3, 2, 1, -3, -4, 2, -4])` functia scrisa de dvs va intoarce rezultatul `(-4, -3)`. 3. (0.5 puncte) Plecand de la o matrice, sa se scrie o functie care returneaza vectorul minimelor de pe linii si vectorul maximelor de pe coloane. Exemplu: pentru matricea `mat = np.array([[1, 2, 3, 4], [1, -2, 3, -4], [3, 10, 3, 4]])` functia va returna tuplul de vectori: `(array([ 1, -4,  3]), array([ 3, 10,  3,  4]))`. Indicatie:  folositi-va de parametrul `axis`.4. (0.5 puncte) Pentru o matrice de numere, sa se determine produsul elementelor pe linii sau de pe coloane, in functie de valoarea unui parametru boolean `compute_on_lines`. Exemplu: pentru matricea `mat = np.array([[1, 2, 3, 4], [1, -2, 3, -4], [3, 10, 3, 4]])` si parametrul `compute_on_lines=True`, functia va returna vectorul `[ 24  24 360]`, iar pentru `compute_on_lines=False` se va returna `[  3 -40  27 -64]`.5. (0.5 puncte) Determinati daca macar unul din elementele unei matrice `a` este mai mare decat cel de pe pozitie corespondenta din `b` (adica daca avem macar o pereche de indecsi (i, j) pentru care a[i, j] > b[i, j]). Daca da, se va returna o astfel de pereche de indecsi; daca nu, se va returna None.6. (0.5 puncte) Construiti o functie care, primind o matrice, determina pe ce pozitii se afla valorile in afara unui interval [min, max] dat prin parametri.7. (1 punct) Se considera vectorul: `a = np.array([230, 10, 284, 39, 76])`. Folosind indexarea logica, sa se inmulteasca elementele din vector care sunt mai mici ca 100 cu 2 (restul raman neschimbate). Folosind ciclare, sa se aplice aceeasi operatie pana cand toate elementele devin mai mari ca 100. Sa se afiseze din vectorul final elementele care sunt mai mari de 150 si mai mici de 200.8. (1 punct) Sa se scrie o functie `pair_max` care preia doi vectori de aceeasi lungime si returneaza maximele pe pozitiile corespunzatoare:```pythona = np.array([3, 7, 9, 13, -10, 200, 3])b = np.array([4, 5, -9, 100, 300, 230, 1])pair_max(a, b)iesire dorita: array([  4,   7,   9, 100, 300, 230,   3])```. Functia va verifica cu `assert` ca vectorii au lungimi egale. 9. (1 punct) Descarcati setul de date Iris de la adresa 'https://archive.ics.uci.edu/ml/machine-learning-databases/iris/iris.data', si incarcati-l intr--o matrice NumPy, folosind `np.genfromtxt`.  Alegeti aleator 10 pozitii in matricea de 150 linii si 4 coloane (omiteti ultima coloana, de tip text), setati aceste valori pe NaN. Construiti o functie care, primind la intrare o matrice, returneaza un tuplu cu indicii de linii respectiv de coloane in care se gasesc valori NaN.10. (1 punct) Sa se construiasca o functie care returneaza cele mai mici `k` valori dintr-un vector de cel putin `k` elemente, impreuna cu pozitiile lor.  Exercițiul 1<jupyter_code>import numpy as np

def getUnique(x: np.array) -> np.array:
    """Determină elementele unice dintr-un numpy.array, în ordine descrescătoare.

    Parameters
    ----------
    x : np.array
        Vectorul analizat. 
  
    Returns
    -------
    np.array
        Elementele unice din vectorul analizat, sortate descrescător. 

    """
    result = np.unique(x)
    result = np.sort(result)[::-1]
    return result

if __name__ == "__main__":
    x = np.array([-4, 3, 5, 3, 2, 1, -3, -4, 2, -4])
    result = getUnique(x)
    print("Result: ", result)<jupyter_output>Result:  [ 5  3  2  1 -3 -4]<jupyter_text>Exercițiul 2<jupyter_code>import numpy as np

def getFreqInfreq(x: np.array) -> tuple:
    """
    Determină cel mai frecvent și cel mai puțin frecvent element dintr-un numpy.array.

    Parameters
    ----------
    x : np.array
        Vectorul analizat.

    Returns
    -------
    tuple
        Tuplu de două valori: cel mai frecvent și cel mai puțin frecvent element.

    """
    xUnique, counts = np.unique(x, return_counts=True)
    countsDescIndices = np.argsort(-counts)
    return xUnique[countsDescIndices[0]], xUnique[countsDescIndices[-1]]

if __name__ == "__main__":
    x = np.array([-4, 3, 5, 3, 2, 1, -3, -4, 2, -4])
    freq, infreq = getFreqInfreq(x)
    print("Most frequent item: ", freq)
    print("Most infrequent item: ", infreq)<jupyter_output>Most frequent item:  -4
Most infrequent item:  5<jupyter_text>Exercițiul 3<jupyter_code>import numpy as np

def MinrowMaxcol(*matrice:np.array) -> tuple:
    '''
    MinrowMaxCol determina minimul pe randuri, maximul pe coloane
    
    Parametrii 
    --------
    matrice:np.array
        matricea analizata

    Returneaza
    --------
    tuple:
        format din doua matrici
    '''

    minRow = np.min(matrice,axis=2)
    maxCol = np.max(matrice, axis=1)
    return minRow,maxCol

array =np.array([[1,2,3,4],
                [1,-2,3,-4],
                [3,10,3,4]])
arrayRowMin, arrayColMax = MinrowMaxcol(array)
print(arrayRowMin,arrayColMax)<jupyter_output>[[ 1 -4  3]] [[ 3 10  3  4]]<jupyter_text>Exercițiul 4<jupyter_code>import numpy as np

def product(mat:np.array, compute_on_lines:bool) -> np.array:
    """
    Determină produsul elementelor de pe liniile unei matrice (compute_on_lines = True).
    Altfel, produsul elementelor de pe coloane.

    Parameters
    ----------
    mat : np.array
        Matricea analizată.

    Returns
    -------
    np.array
        Vectorul de produse.
    """
    return np.product(mat, int(compute_on_lines)) # False = 0, True = 1

if __name__ == "__main__":
    mat = [[1, 2, 3, 4],
           [1, -2, 3, -4],
           [3, 10, 3, 4]]
    compute_on_lines = False
    products = product(mat, compute_on_lines)
    print(products)<jupyter_output>[  3 -40  27 -64]<jupyter_text>Exercițiul 5<jupyter_code>import numpy as np

def indices(a:np.array, b:np.array) -> tuple:
    """
    Identifică o pereche de indici i, j pentru care a[i][j] > b[i][j].

    Parameters
    ----------
    a : np.array, b : np.array
        Cele două matrici ale căror elemente se vor compara.

    Returns
    -------
    tuple:
        O pereche de indici (dacă există una). Altfel, None.

    """
    assert np.array(a).shape == np.array(b).shape
    idx = np.where((np.array(a) > np.array(b)) == True)
    if idx[0].size == 0 and idx[1].size == 0:
        return None
    else:
        return idx[0][0], idx[1][0]

if __name__ == "__main__":
    a = [[1, 2, 3],
         [4, 5, 6],
         [7, 8, 9],
         [10, 11, 12]]

    b = [[13, 14, 15],
         [16, 17, 18],
         [19, 2, 21],
         [22, 23, 24]]

    print(indices(a, b))<jupyter_output>(2, 1)<jupyter_text>Exercițiul 6<jupyter_code>import numpy as np

def OutsideMinMax(min, max, mat:np.array) -> np.array:
    """
    Functia preia o matrice si doua cutpointuri, returneaza indexul elementelor
    din afara intervalului descris de cele doua limite

     Parameters
    ----------
    array : np.array
        Matricea a carei elemente sunt utilizate.
    min:
        valoare primul cutpoint
    max:
        valoare al 2-lea cutpoint

    Returns
    -------
    array: np.array
        O matrice de indexuri pentru valorire din afara intervalului

    """
    if max > min:
        array_ouside_interval =np.array(np.where((mat > min) & (mat < max)))
    else:
        print("Intervalul selectat depaseste dimensiunea matricei")
    return array_ouside_interval


matrice =np.arange(20)
matrice_rand = np.random.choice(matrice,30)
print("Matricea generata random cu valori ",matrice_rand)
print("Matricea de indecsi",OutsideMinMax(10,18,matrice_rand))<jupyter_output>Matricea generata random cu valori  [18 16  8 15 18  3 15  6  7  3 13  9  5 16  7 12 12  4  1  0 11  5 11  8
 19 17 13  3  8 19]
Matricea de indecsi [[ 1  3  6 10 13 15 16 20 22 25 26]]<jupyter_text>Exercițiul 7<jupyter_code>import numpy as np
from copy import deepcopy

def IndexareLogica(matrice:np.array) -> np.array:
    """
    Foloseste indexarea logica si ciclarea pentru operatii cu elementele vectorului primit.

    Parameters
    ----------
    matrice: np.array
        Vectorul a caror elemente sunt modificate.

    Returns
    -------
    np.array:
        O matrice ce contine elementele modficate ale vectorului

    """
    #pentru ciclare
    matrice_ciclare =deepcopy(matrice)
    for index,cifra in enumerate(matrice_ciclare):
        while cifra<100:
            cifra*=2
        if cifra>150 and cifra<200:
            matrice_ciclare[index]=cifra
        else:
            matrice_ciclare[index]=0
    print("Rzultatul ciclului este...",matrice_ciclare)

    #pentru indexare logica
    matrice[matrice <100]*=2
    result=matrice[(matrice>150)&(matrice<200)]
    print("Rezultatul indexarii logice este...")
    return result 
    
a = np.array([230, 10, 284, 39, 76])
print(IndexareLogica(a))<jupyter_output>Rzultatul ciclului este... [  0 160   0 156 152]
Rezultatul indexarii logice este...
[152]<jupyter_text>Exercițiul 8<jupyter_code>import numpy as np

def pair_max(a: np.array, b: np.array) -> np.array:
    """
    Determină, pentru fiecare poziție, maximele dintre doi vectori np.array.
    Afișează eroare dacă vectorii nu sunt de aceeași lungime.

    Parameters
    ----------
    a : np.array
        Vector cu numere.
    b : np.array 
        Vector cu numere.

    Returns
    -------
    np.array
        Vector cu valorile maxime dintre a și b pentru fiecare poziție.
        
    """
    assert a.size == b.size
    return np.maximum(a, b)

if __name__ == "__main__":
    a = np.array([3, 7, 9, 13, -10, 200, 3])
    b = np.array([4, 5, -9, 100, 300, 230, 1])
    print(pair_max(a, b))<jupyter_output>[  4   7   9 100 300 230   3]<jupyter_text>Exercițiul 9 (necesită iris.data)<jupyter_code>import numpy as np

def randomlySetNaN(mat: np.array) -> np.array:
    """
    Setează valori NaN pe 10 poziții aleatoare.

    Parameters
    ----------
    mat : np.array
        Matricea care va fi modificată.

    Returns
    -------
    np.array
        Matricea inițială cu valorile modificate.
        
    """
    n, m = mat.shape
    randomLines = np.random.randint(0, n - 1, size=10)
    randomColumns = np.random.randint(0, m - 1, size=10)
    randomCoords = randomLines, randomColumns
    mat[randomCoords] = np.nan

def findNaN(mat: np.array) -> tuple:
    """
    Determină coordonatele la care se află valori NaN.

    Parameters
    ----------
    mat : np.array
        Matricea cu valori NaN care va fi analizată.

    Returns
    -------
    tuple
        Tuplu cu două np.array care conțin liniile, respectiv coloanele
        la care se găsesc valori NaN.

    """
    args = np.argwhere(np.isnan(mat))
    lines = [arg[0] for arg in args]
    columns = [arg[1] for arg in args]
    return np.unique(lines), np.unique(columns)
    

if __name__ == "__main__":
    mat = np.genfromtxt('iris.data', delimiter=',')
    mat = np.delete(mat, -1, axis=1)
    randomlySetNaN(mat)
    lines, columns = findNaN(mat)
    print("LINES   : ", lines)
    print("COLUMNS : ", columns)<jupyter_output>LINES   :  [  1  75  81  87  93 103 124 128 142]
COLUMNS :  [0 1 2]<jupyter_text>Exercițiul 10<jupyter_code>import numpy as np
def MinValues(vector, nr_valori_minime) ->tuple:
    """
    MinValue determina k valori minime dint-un vector dat impreuna 
    cu pozitia lor
    
    Parametrii 
    --------
    vector:np.array
        vectorul de valori initiale

    Returneaza
    --------
    matrice_valori:np.array ,matrice_indecsi:np.array
        matricea volorilor minime si indecsi lor
    """

    assert int(nr_valori_minime)<=len(vector)
    print("Vectorul initial: ",vector)
    result = np.argpartition(vector, nr_valori_minime)
    return vector[result[:nr_valori_minime]],result[:nr_valori_minime]
   

k=int(input("Introduceti numarul de valori minime pe care vreti sa il aflati"))
dimensiune_vector = int(input("Introduceti dimensiunea vectorului"))
print(dimensiune_vector)

print("Va fi generat un vector cu valori din intervalul specificat.....")

matrice_rand = np.unique(np.random.random_integers(-100,100,dimensiune_vector))
matrice_result,matrice_indecsi=MinValues(matrice_rand,k)
print("Cele",k)
print("valorile minime sunt...",matrice_result)
print("Indecsi lor sunt...",matrice_indecsi)<jupyter_output>Introduceti numarul de valori minime pe care vreti sa il aflati 10
Introduceti dimensiunea vectorului 20
{'fraction_non_alphanumeric': 0.12187620146097655, 'fraction_numerical': 0.040369088811995385, 'mean_word_length': 2.9269323671497585, 'pattern_counts': {'":': 6, '<': 38, '<?xml version=': 0, '>': 50, 'https://': 3, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 1, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '10', 'dir': 'jupyter-structured-clean-dedup', 'id': '162993', 'license': 'MIT', 'n_tokens_mistral': 5189, 'n_tokens_neox': 4812, 'n_words': 1435, 'path': 'Laborator2/IDS_Sirbu_Tataru.ipynb', 'repo_name': 'MateiSirbu/IDS_Sirbu_Tataru', 'size': '13014'}