Sunteți pe pagina 1din 314

PYTHON

CURS 1
INTRODUCERE
INTRODUCERE
De la începutul acestui mileniu, creșterea accelerată a soluțiilor software de tip open source a produs
proiecte remarcabile.

Specialiștilor în data science li s-au deschis astfel oportunități enorme pentru prelucrarea volumelor mari de
date.

Cel mai important rezultat al proiectelor open source în domeniu este Python.

Pyhon își are rădăcinile în domeniile științific și al tehnicii de calcul și are o sintaxă foarte compactă.

Ultimii ani au fost marcați de o intensificare a implementărilor în care sunt folosite combinat tehnologii
proprietare și open source.

Este important să găsim modalități de combinare a capacitățile acestor limbajelor comerciale și open source
pentru a se completa reciproc.
CARACTERISTICI

Python este limbaj de


Necesită mai puține linii de Python rulează pe diferite
programare de ultimă
A fost inventat în 1991 de sisteme de operare:
generație, ușor de învățat, cod în comparație cu alte
Guido van Rossum; Windows, Mac, Linux,
ca urmare a sintaxei simple limbaje; Raspberry Pi etc.;
similare cu limba engleză;

Limbajul poate fi utilizat în Poate gestiona volume


Conține o bibliotecă vastă Python se poate conecta la
mai multe medii (IDE): mari de date (big data) și
de pachete: numpy, pandas, baze de date. Citește și
Eclipse, PyCharm, Spyder, efectua operații
matplotlib, scikit-learn etc. modifică fișiere;
Thonny, Netbeans etc.; matematice complexe.
ELEMENTE DE SINTAXA
• Spre deosebire de alte limbaje (R, C++, Java,
Perl etc.) care utilizeaza paranteze, Python
utilizeaza indentarea (tab sau spatii);

• Doua puncte (:) denota necesitatea unei


indentari;

• Nu solicita punct si virgula (;), dar sunt


necesare atunci cand utilizam mai multe
declaratii pe aceeasi linie;

• comentariu pe linie (#), pe mai multe linii (’ ’ ’).


TIPURI DE DATE
• int, float, complex. Functia type() verifica tipul de data;
• Specificarea tipului de dată pentru o variabilă: int(), float(), complex(), str();
• Tipul Boolean este un subtip al tipului integer, cu valorile True și False. Într-un context
numeric, de exemplu, atunci când este folosit ca argument pentru operații aritmetice, se
comportă ca niște numere întregi cu valori 0 pentru False și 1 pentru True.
• Siruri de caractere marcate cu ‘ ’ sau “ ”;
• Extragerea elementelor dintr-un sir: sir[ ];
• Cateva metode pentru siruri de caractere: sir.strip(), sir.strip(‘caractere’), len(sir),
sir.lower(), sir.upper(), sir.replace(“ ”, “”);
TIPURI DE DATE- PYTHON/SAS

Variabilele nu necesita declarare explicita si sunt case- Limbajului SAS nu este necesar să se declare variabile și tipurile
sensitive. de date asociate, deoarece sunt deduse din utilizarea lor.

Categorii generale de tipuri de date Python: a) Încorporate Limbajul SAS de bază nu face distincție între numere întregi și
în limbaj; b) Adăugate de terți; c) Create prin codul Python. float. Implementări mai noi, cum ar fi SAS Cloud Analytic
Services (CAS) definesc o gamă de tipuri de date numerice.
Permit manipularea unei mari varietăți de date și îi permit
să fie un limbaj de programare de nivel înalt (de uz general), Tipurile de date pentru SAS sunt fie numerice, fie de caractere.
pe lângă utilizarea sa ca limbaj de prelucrare a datelor. Intern, SAS reprezintă valorile numerice în virgulă mobilă.

Python permite operații aritmetice „mixte” – sunt permise Limbajul SAS efectuează multe procesări necesare pentru
în expresii tipuri de date diferite. conversia sau citirea datelor fără intervenția utilizatorului.
TIPURI DE DATE- PYTHON/SAS
COLECTII DE DATE – LISTE (ARRAY)
• Colecții de date care pot fi neomogene, ordonate și modificabile, permit elemente identice si sunt
reprezentate utilizând [ ];
• Modificare element: lista[index] = valoare → index incepe de la 0;
• Numar elemente: len(lista);
• Adaugare element la sfarsitul listei: lista.append(element);
• Adaugare element la un anumit index: lista.insert(index,element);
• Eliminare element:
- lista.remove(element)→elimina primul element daca in lista exista mai multe elemente identice;
- lista.pop(index) → elimina ultimul element daca nu se specifica indexul;
- del lista[index];
• Golire lista: lista.clear();
• Sterge lista: del lista.
ACCESARE LISTE
seq = [7, 2, 3, 7, 5, 6, 0, 1]
Index 0 1 2 3 4 5 6 7
-7 -6 -5 -4 -3 -2 -1 0
print(seq[1:5])
# Afiseaza elemente lista de la indexul 1 pana la 5 exclusiv [2, 3, 7, 5]
seq[3:4] = [6, 3]
print(seq)
# Modificare elemente de la pozitiile 3 si 4 [7, 2, 3, 6, 3, 5, 6, 0, 1]
seq[3:] = [6, 3]
print(seq)
# Inlocuirea tuturor elementelor incepand de la pozitia 3 a listei [7, 2, 3, 6, 3]
print(seq[:3])
# Afisare elemente lista pana la pozitia 3 exclusiv [7, 2, 3]
print(seq[3:])
# Afisare elemente lista incepand de la pozitia 3 [6, 3]
print(seq[-4:])
# Afisare elemente lista de la coada la cap pana la pozitia -4 exclusiv [2, 3, 6, 3]
print(seq[-4:-2])
# Afisare elemente lista de la coada la cap de la pozitia -2 la -4 exclusiv [2, 3]
print(seq[::2])
# Afisare elemente din 2 in 2 [7, 3, 3]
print(seq[::-1])
# Inversare elemente [3, 6, 3, 2, 7]
Metoda Descriere #Exemplu 1
b = ['saw', 'small', 'He', 'foxes', 'six']
append() Adaugă un element la sfârșitul listei b.sort(reverse = True)
clear() Elimină toate elementele listei print(b)
b.sort(key=len)
copy() Crează o copie a listei print(b)
count() Returnează numărul de apariții al elementului în listă #['small', 'six', 'saw', 'foxes', 'He’]
extend() Adăugă elemente la sfârșitul unei liste #['He', 'six', 'saw', 'small', 'foxes']
Ex: seq = [7, 2, 3, 6, 3]; seq.extend([1,2,3]); print(seq)
#Exemplu 2
→ [7, 2, 3, 6, 3, 1, 2, 3] import bisect as bi
index() Returnează indexul unui element b = ['saw', 'small', 'He', 'foxes',
'six']
insert() Adaugă un element la poziția specificată b.sort()
pop() Elimină elementul de la poziția specificată print(bi.bisect(b,'sell'))
bi.insort(b,'sell')
remove() Elimină primul element specificat print(b)
reverse() Inversează ordinea elementelor în listă
#3
sort() Sortează lista #['He', 'foxes', 'saw', 'sell', 'six',
'small']

COLECTII DE DATE
LISTE METODE
FUNCTII BUILD-IN ENUMERATE
b = ['saw', 'small', 'He', 'foxes', 'six']
for i, value in enumerate(b,3):
enumerate(iterable, start=0)
print(i, value)
permite parcurgerea unei colecții de
lista = list(enumerate(b,1)) elemente în timp ce păstrează indexul
print(lista) elementului curent într-o variabilă
contor. Parametri:
dictionar = dict(enumerate(b,1)) • iterable - o secvență, un iterator sau
print(dictionar) obiect care suportă iterație
• start (optional) - enumerate()
pornește numărarea de la acest număr.
'''3 saw
4 small
Implicit este 0.
5 He
6 foxes
7 six

[(1, 'saw'), (2, 'small'), (3, 'He'), (4, 'foxes'), (5, 'six’)]

{1: 'saw', 2: 'small', 3: 'He', 4: 'foxes', 5: 'six'}'''


FUNCTII BUILD-IN RANGE (GENERARE LISTE)
#range([start], stop[, step])
print(list(range(18))) [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
print(list(range(5,18))) [5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17]
print(list(range(5,18,2))) [5, 7, 9, 11, 13, 15, 17]
print(list(reversed(range(10))))
#[9, 8, 7, 6, 5, 4, 3, 2, 1, 0]

b = ['saw', 'small', 'He', 'foxes', 'six']


b_len = len(b)
for i in range(0, b_len):
print(b[i])
saw
small
He
foxes
six
FUNCTII BUILD-IN ZIP
#zip face perechi din elementele unor #Exercitiu 3
liste, tupluri sau secvente pentru a for i, (a, b) in enumerate(zip(seq1, seq2)):
genera o lista de tupluri print('{0}: {1}, {2}'.format(i, a, b))
#Exercitiu 1 '''0: one, cat
seq1 = ['one', 'two', 'three'] 1: two, dogs
seq2 = ['cat', 'dogs', 'mice'] 2: three, mice'''
zipped = zip(seq1, seq2)
print(list(zipped)) #Exercitiu 4
# [('one', 'cat'), ('two', 'dogs'), lista_tupluri = [('Popescu', 'Alexandru'),
('three', 'mice')] ('Constantinescu', 'Maria'), ('Stan', 'Gigel')]
nume, prenume = zip(*lista_tupluri)
#Exercitiu 2 print(nume)
seq3 = [False, True] #('Popescu', 'Constantinescu', 'Stan')
print(list(zip(seq1, seq2, seq3))) print(prenume)
#[('one', 'cat', False), ('two', 'dogs', #('Alexandru', 'Maria', 'Gigel')
True)]
COLECTII DE DATE - TUPLURI
• Colecții de date neomogene, ordonate și nemodificabile, permit elemente identice si sunt
reprezentate utilizând ( ) t = tuple(['four', [1, 2], True])

• Accesare element: tuplu[index] t = ((7,1), [1, 2], 'mar', False)


lista = list(t)
• Utilizand tuple, pot fi transformate liste in tupluri gen = range(10)
• Utilizand list, pot fi transformate tupluri in liste print(tuple(gen))
print(list(gen))
• Listele si tuplurile pot fi concatenate cu + t = tuple(['four', [1, 2], True])
gen =tuple(range(10))
Metoda Descriere print(t+gen)

count() Returnează numărul de apariții al l = ['four', [1, 2], True]


gen1 =list(range(10))
elementului în tuplu print(l+gen1)
index() Returnează poziția unui element în #l1 echivalent cu l
tuplu l1 = ['four', [1, 2], True]
gen1 =list(range(10))
l1.extend(gen1)
print(l1)
COLECTII DE DATE - DICTIONARE
• Colecții de date neordonate, modificabile și indexate. Nu sunt admise elemente duplicate.
Dicționarele sunt reprezentate prin { }, având elemente cheie-valoare;
• Accesare si modificare valoare: dictionar[cheie] = valoare noua.

Metoda Descriere
clear() Elimină toate elementele din dicționar
copy() Returnează o copie a dicționarului
fromkeys() Creează un dicționar cu chei și valori specificate
get() Returnează valoarea pentru o anumită cheie
items() Returnează o listă conținând un tuplu pentru fiecare pereche cheie-valoare
keys() Returnează o listă conținând cheile dicționarului
pop() Elimină elementul având o anumită cheie specificată
popitem() Elimină ultima pereche adăugată cheie-valoare
update() Actualizează dicționarul cu perechile cheie-valoare specificate
values() Returnează o listă cu toate valorile dicționarului
Exemple dictionare
d1 = {'a' : 'some value', 'b' : [1, 2, 3, 4]}; print(d1)
# Afiseaza d1 {'a': 'some value', 'b': [1, 2, 3, 4]}
d1[7] = 'an integer'
print(d1)
# Adauga un element la d1 {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer’}
print(d1['b'])
# Afiseaza valoarea pentru cheia respectiva [1, 2, 3, 4]
print('b' in d1)
# Verifica daca cheia respectiva face parte din dictionar True
d1[5] = 'some value’; d1['dummy'] = 'another value’ # Adauga noi elemente {'a': 'some
value','b': [1, 2, 3, 4],7: 'an integer',5: 'some value','dummy': 'another value’}
del d1[5] # Sterge elementul corespunzator {'a': 'some value','b': [1, 2, 3, 4],7: 'an
integer','dummy': 'another value’}
ret = d1.pop('dummy’); # Sterge {'a': 'some value', 'b': [1, 2, 3, 4], 7: 'an integer’}
list(d1.keys()) # Pune cheile intr-o lista ['a', 'b', 7]
list(d1.values()) # Pune valorile in lista ['some value', [1, 2, 3, 4], 'an integer’]
d1.update({'b' : 'four', 'c' : 12})
# Actualizeaza d1 {'a': 'some value', 'b': 'four', 7: 'an integer', 'c': 12}
Exemple dictionare
# Dictionare = colectii formate din doua tupluri
col2tup=dict(zip((0,1,2,3,4),(4,3,2,1,0)))
print(col2tup)
#{0: 4, 1: 3, 2: 2, 3: 1, 4: 0}
col2tup = dict(zip(range(5), reversed(range(5))))
print(col2tup)
#{0: 4, 1: 3, 2: 2, 3: 1, 4: 0}
# Clasificare lista de cuvinte pornind de la prima litera formand un dictionar de de
liste
words = ['dig','apple', 'bat', 'corn', 'dog', 'bar', 'atom', 'book', 'cat', 'cattle']
by_letter = {}
for word in words:
letter = word[0]
if letter not in by_letter:
by_letter[letter] = [word]
else:
by_letter[letter].append(word)
print(by_letter)
#{'d': ['dig', 'dog'], 'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book'], 'c':
['corn', 'cat', 'cattle']}
print(dict(sorted(by_letter.items())))
#{'a': ['apple', 'atom'], 'b': ['bat', 'bar', 'book'], 'c': ['corn', 'cat',
'cattle'], 'd': ['dig', 'dog']}
COLECTII DE DATE - SETURI
• Colecții de date neordonate, nemodificabile și neindexate. Nu sunt acceptate elemente identice. Seturile sunt
reprezentate prin { }. Se aseamana cu dictionarele, numai ca elementele nu sunt cheie-valoare.

Metoda Descriere
add() Adaugă un element
clear() Elimină toate elementele setului
copy() Returnează o copie a setului
difference() Returnează un set reprezentând diferența dintre două sau mai multe seturi
difference_update() Elimină elementele dintr-un set care sunt conținute de un alt set specificat
discard() Elimină un element specificat
intersection() Returnează un set reprezentând intersecția a două seturi
intersection_update() Elimină elementele dintr-un set care nu sunt în alt set
isdisjoint() Arată dacă două seturi se intersectează sau nu
issubset() Arată dacă un set este inclus într-un alt set sau nu
issuperset() Arată dacă un set conține un alt set sau nu
pop() Elimină un element
remove() Elimină elementul specificat
symmetric_difference() Returnează un set cu elemente necomune celor doua seturi
symmetric_difference_update() Inserează intr-un set diferențele dintre două seturi
union() Returnează un set reprezentând reuniunea a două seturi
update() Actualizează setul cu reuniunea dintre un set și altele
Exemple seturi
print(set([2, 2, 2, 1, 3, 3]))
#{1, 2, 3}
print({2, 2, 2, 1, 3, 3})
#{1, 2, 3}

a = {1, 2, 3, 4, 5}
b = {3, 4, 5, 6, 7, 8}
print(a.union(b)); print(a | b)
#{1, 2, 3, 4, 5, 6, 7, 8}

print(a.intersection(b)); print(a & b)


#{3, 4, 5}

print(a.symmetric_difference(b)); print(a^b)
#{1, 2, 6, 7, 8}

print(a.symmetric_difference_update(b))
print(a)
#{1, 2, 6, 7, 8}

my_data1 = [1, 2, 3, 4]
my_data2 = [4, 5]
my_set = {tuple(my_data1), tuple(my_data2)}
print(my_set)
#{(4, 5), (1, 2, 3, 4)}
Prelucrari colectii
1) strings = ['a', 'as', 'bat', 'car', 'dove', 'python']

# Transformarea elementelor a caror lungime > 2 in litere mari


SINTAXA [expr for val in collection if condition]
print([x.upper() for x in strings if len(x) > 2])
rezultat = []
for i in strings:
if len(i) > 2:
rezultat.append(i.upper())
print(rezultat)
#['BAT', 'CAR', 'DOVE', 'PYTHON’]

2) Dictionar generat din lista


SINTAXA dict = {key-expr : value-expr for value in collection if condition}
dict = {val : index for index, val in enumerate(strings)}
print(dict)
#{'a': 0, 'as': 1, 'bat': 2, 'car': 3, 'dove': 4, 'python': 5}

3) Afisare lungime elemente. SINTAXA set = {expr for value in collection if condition}
unique_lengths = {len(x) for x in strings}
print(unique_lengths)
#{1, 2, 3, 4, 6}

4) Afisare nume in care litera a apare de cel putin 2 ori #nested lists
nume = [['John', 'Emily', 'Michael', 'Mary', 'Steven'],['Maria', 'Juan', 'Javier', 'Natalia', 'Pilar']]
result = [name for names in nume for name in names if name.count('a') >= 2]
print(result)
#['Maria', 'Natalia’]
OPERATORI ARITMETICI, ATRIBUIRE,
COMPARATIE
Operator Denumire Exemplu
+ Adunare x+y Operator Exemplu Echivalent
- Scădere x-y
= x=5 x=5
* Înmulțire x*y
/ Împărțire x/y
+= x += 3 x=x+3
% Restul împărțirii x%y -= x -= 3 x=x-3
** Exponențial x ** y *= x *= 3 x=x*3
// Partea întreagă a x // y /= x /= 3 x=x/3
împărțirii %= x %= 3 x=x%3
//= x //= 3 x = x // 3
Operator Denumire Exemplu **= x **= 3 x = x ** 3
== Egal x == y
!= Diferit x != y
> Mai mare x>y
< Mai mic x<y
>= Mai mare sau egal x >= y
<= Mai mic sau egal x <= y
OPERATORI LOGICI, IDENTITATE,
APARTENENTA
Operator Descriere Exemplu
and Returnează True dacă ambele expresii sunt adevărate x < 5 and x < 10
or Returnează True dacă cel puțin o expresie este adevărată x < 5 or x < 4
not Negația, inversează rezultatul returnând False dacă rezultatul este not(x < 5 and x < 10)
adevărat

Operator Descriere Exemplu


is Returnează True dacă ambele variabile sunt același obiect x is y
is not Returnează True dacă ambele variabile nu sunt același obiect x is not y

Operator Descriere Exemplu


in Returnează True dacă o secvență cu o valoare specificată este x in y
prezentă în obiect
not in Returnează True dacă o secvență cu o valoare specificată nu este x not in y
prezentă în obiect
#Exemplu 1 # Exemplu 5
x = 15.0 x=30
y = 15 print(1<x<100)
if (x == y):
print ("Adevarat. 'x' si 'y' sunt # Exemplu 6
egale") x=30
else: print(1<x<30)
print("Fals. 'x' and 'y' nu sunt
egale") # Exemplu 7
x=4
# Exemplu 2 y=5
x = 15.0 print(x!=y)
y = 15
print (x is y) # Exemplu 8 comparatie siruri
s1='Sir'
# Exemplu 3 s2='sir'
x = 15.0 print(s1==s2)
y = x
print (x is y) #Exemplu 9 operatori booleeni si de
apartenenta
# Exemplu 4 Teste booleene pentru s3 = 'Sir Lung'
siruri print('r' and " " in s3)
print(bool('')) #sir gol
print(bool(' ')) #spatiu
print(bool('Un sir'))
FUNCTII
#Exemplu 1 #Exemplu 2
def my_function(x, y, z=1.5): def f():
if z > 1: a = 5
return z * (x + y) b = 6
else: c = 7
return z / (x + y) return a, b, c
print(my_function(1,2,3)) print(f())
#9 print(list(f()))
print(my_function(1,2)) print(set(f()))
#4.5
print(my_function(z=5, y=6, x=7)) #Exemplu 3
#65 def f():
print(my_function(y=6, x=5, z=7)) a = 5
#77 b = 6
print(my_function(y=6, x=7)) c = 7
#19.5 return {'a' : a, 'b' : b, 'c' : c}
print(f())
#Exemplu 4 - curatare siruri din lista #Exemplu 5
import re
def add(a, b):
states = [' Alabama ', 'Georgia!',
'Georgia', 'georgia', 'FlOrIda','south return a + b
carolina## ', 'West virginia?'] #map(function, iterables)
def clean_strings(strings): x = map(add, (0, 1, 2), (2, 1, 0))
result = [] print(list(x)) #[2,2,2]
for value in strings:
value = value.strip() #Exemplu 6 Functia anonima sau lambda
value = re.sub('[!#?%*]', '', def my_f(x):
value) return x * 2
value = value.title() echivalent = lambda x: x * 2
result.append(value) print(echivalent(5))
return result

print(clean_strings(states)) #Exemplu 7 Sortare in functie de lungime


#['Alabama', 'Georgia', 'Georgia', strings = ['curs', 'seminar', 'abba',
'Georgia', 'Florida', 'South Carolina', 'mere', 'pachete',' ' , 'software']
'West Virginia'] strings.sort(key=lambda x: len(x))
print(strings)

#Exemplu 8 Apel functie add cu lambda


add_five = lambda x: add(x,5)
print(add_five(20)) #25
STRUCTURA ALTERNATIVA (IF)
x= 10

if x < 0:
print('It is negative')
elif x == 0:
print('Equal to zero')
elif 0 < x < 5:
print('Positive but smaller than 5')
else:
print('Positive and larger than or equal to 5')
STRUCTURI REPETITIVE (FOR)
sequence = [1, 2, None, 4, None, 5]
total = 0 #12
for value in sequence:
if value is None:
continue
total += value
print(total) #13

sequence = [1, 2, 0, 4, 6, 5, 2, 1]
total_until_5 = 0
for value in sequence: (0, 0)
if value == 5: (1, 0)
break (1, 1)
total_until_5 += value (2, 0)
print(total_until_5) (2, 1)
(2, 2)
for i in range(4): (3, 0)
for j in range(4): (3, 1)
if j > i: (3, 2)
break (3, 3)
print((i, j))
STRUCTURI REPETITIVE (WHILE)
i = 1
while i < 6:
print(i)
if i == 3:
break
i += 1

i = 0
while i < 6:
i += 1
if i == 3:
continue
print(i)
GENERATOARE (SUPLIMENTAR)
#Functie care calculeaza x**2 import itertools
def squares(n=10):
print('Generating squares from 1 to
{0}'.format(n ** 2)) first_letter = lambda x: x[0]
for i in range(1, n + 1):
yield i ** 2 names = ['Alan', 'Adam', 'Wes', 'Will',
gen = squares() 'Albert', 'Steven', 'Simona', 'Ana’]
for x in gen:
print(x) names = sorted(names, key = first_letter)
#echivalent cu
gen = (x ** 2 for x in range(1,11)) for letter, names in
print(list(gen)) itertools.groupby(names, first_letter):
#Generatorul poate fi argumentul unei print(letter, list(names))
functii
print(sum(x ** 2 for x in range(1,11))) '''A ['Alan', 'Adam', 'Albert', 'Ana']
#385 S ['Steven', 'Simona']
W ['Wes', 'Will']'''
#dictionar format din valoare – patratul
valorii
print(dict((i, i **2) for i in range(5)))
#{0: 0, 1: 1, 2: 4, 3: 9, 4: 16}
BIBLIOGRAFIE

• Python for Data Analysis, DATA WRANGLING WITH PANDAS, NUMPY, AND IPYTHON,
Wes McKinney, 2nd edition, 2012, Ed. O’REILLY
• Data Science from Scratch, FIRST PRINCIPLES WITH PYTHON, Joel Grus, 2015, Ed. O’REILLY
• Python Data Science Handbook, ESSENTIAL TOOLS FOR WORKING WITH DATA, Jake
VanderPlas, 2016, Ed. O’REILLY
• Fundamentals of Python®: Data Structures, Kenneth A. Lambert, Cengage Learning PTR, 2014
PYTHON

CURS 2
1
ACCESARE DATE DIN FISIERE (I)
Fișiere: .txt, .csv, xlsx, .json

Fișiere text

Funcția open() returnează un obiect de tip fișier. f = open("C:/Data1.txt")


Metoda read() citește conținutul fișierului. print(f.read())

Funcția open()care doi parametri: numele fișierului sau calea și modul în care poate fi accesat:
"r" - Read - implicit. Deschide fișierul pentru citire, apare eroare dacă fișierul nu există.
"a" - Append - Deschide fișierul pentru adăugare, creează fișierul dacă nu există.
"w" - Write - Deschide fișierul pentru scriere, creează fișierul dacă nu există.
"x" - Create - creează fișierul, apare eroare dacă fișierul există.
Suplimentar, se pot specifica:
"t" - Text - Implicit. Modul text
"b" - Binary - Modul binar (de ex. imagine)

•Metoda readline()citește o singură linie


•Poate fi specificat numărul de caractere afișate: read(100) 2
ACCESARE DATE DIN FISIERE (II)
Fișiere comma separated values

import csv
with open('clienti_leasing.csv', 'r') as f:
reader = csv.reader(f)
for row in reader:
print (row)

import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
print(df)

3
ACCESARE DATE DIN FISIERE (III)
Fișiere .xlsx

from xlrd import open_workbook


book =
open_workbook('simple.xlsx',on_demand=True) import pandas as pd
for name in book.sheet_names(): df = pd.read_excel(io="simple.xlsx",
sheet = book.sheet_by_name(name) sheet_name="Sheet_names")
for cell in sheet.col(0): print(df.head(5))
print (cell.value)

from openpyxl import load_workbook


wb = load_workbook('simple.xlsx')
print (wb.get_sheet_names())

worksheet1 = wb['Sheet_names'] # one way to load a worksheet


#worksheet2 = wb.get_sheet_by_name('Sheet_names') # another way to load a worksheet
print(worksheet1['A4'].value)
worksheet1['A4'] = 'Corina'
print(worksheet1['A4'].value)
for row in worksheet1.iter_rows():
print(row[1].value)
4
ACCESARE DATE DIN FISIERE (IV)
Fișiere .json
import json
from pprint import pprint
with open ('clienti_daune.json') as f:
data=json.load(f)
pprint(data)

import json
from pprint import pprint
json_data=open('clienti_daune.json').read()
data = json.loads(json_data)
pprint(data)

import json
import pandas as pd
with open("clienti_daune.json") as f:
data = json.load(f)
dataframe = pd.DataFrame(data)
print(dataframe)
5
NUMPY
• NumPy prescurtarea pentru Numerical Python sau calcule numerice
Python.
• NumPy contine:
- Tipul de obiect multidimensional ndarray
- Functii pentru calcule cu vectori sau operatii matematice cu vectori
- Instrumente pentru citirea si scrierea seturilor de date bazate pe
vectori
- operatii din algebra liniara, transformata Fourier si generare de
numere aleatoare
- API pentru C sau C++

6
MATPLOTLIB & SCIPY
• Matplotlib este cea mai populara biblioteca Python pentru realizarea reprezentarilor grafice
• SciPy reprezinta o colectie de pachete pentru rezolvarea unor probleme standard din diferite
domenii
- scipy.integrate: Ofera rutine pentru integrare numerica si calculul ecuatiilor diferentiale;
- scipy.linalg: Rutine din algebra relationala, prelucrarea avansata matricelor, fiind superior
pachetului numpy.linalg;
- scipy.optimize. Functii de optimizare (minimizare) si algoritmi de identificare a drumului
critic;
- scipy.signal. Instrumente de procesare a semnalului;
- scipy.sparse. Calcule cu matrice si sisteme de ecuatii liniare (sparse);
- scipy.special. O biblioteca Fortran pentru implementarea celor mai populare functii
matematice, cum ar fi functia gamma;
- scipy.stats. Distributii de probabilitati, teste statistice, statistici descriptive.

7
SCIKIT-LEARN
• Instrumente pentru machine learning in Python, ce include submodule pentru diverse modele:
• Clasificare: SVM, nearest neighbors, random forest, logistic regression etc.
• Regresia: Lasso, ridge regression etc.
• Clustering: k-means, spectral clustering etc.
• Reducerea dimensionalitatii (Dimensionality reduction): PCA, feature selection, matrix
factorization etc.
• Selectie model: Grid search, cross-validation, metrics
• Preprocesare: Feature extraction, normalizare

8
STATSMODELS
• In comparatie cu scikit-learn, statsmodels continue algoritmi clasici din statistica si
econometrie. Include submodule, cum ar fi:
• Regresie: liniara, modele liniare generalizate , modele liniare robuste, linear mixed effects
models etc.
• ANOVA
• Analize pe serii de timp: AR, ARMA, ARIMA,VAR etc.
• Nonparametric methods: Kernel density estimation, kernel regression
• rezultatele analizelor realizate cu statsmodels sunt axate pe indicatori statistici, p-values, in
timp ce rezultatele analizelor efectuate cu scikit-learn, se axeaza mai mult pe predictii.

9
PACHETUL PANDAS (I)
Reprezintă elementul
central pentru Oferă două structuri Detectarea și Operații ușoare de
înțelegerea Python în de date de tip masiv: manipularea ușoară a feliere și creare de
contextul prelucrării Series și Dataframe valorilor lipsă subseturi
datelor

Obiecte index
Încărcătoare pentru
Combinarea și automat pentru
intrare / ieșire
îmbinarea mai multor rânduri și coloane cu
acceptând o gamă
Dataframe mai multe niveluri /
largă de date tabelare
indexare ierarhică

10
PACHETUL PANDAS (II)
Contine structuri de date (Dataframe), orientate pe coloane,si instrumente pentru
manipularea datelor, proiectate pentru a realiza mai rapid si mai usor curatarea si
analiza datelor in Python;

Dataframe = container de vectori unidimensionali (Series);

Se utilizeaza deseori in tandem cu alte pachete de calcul numeric, cum ar fi NumPy


and SciPy, biblioteci analitice, cum ar fi statsmodels si scikit-learn, si instrumente
pentru vizualizarea datelor, cum ar fi matplotlib.

11
Pandas adaopta stilul de calcul bazat pe vectori,
in special functii pe vectori, specific NumPy,
precum si procesarea datelor in stil pythonian,
fara a utiliza structuri repetitive;

Care este cea mai mare diferenta dintre Pandas


si NumPy? Pandas lucreaza cu date tabelare,
eterogene, in timp ce NumPy este adecvat
pentru vectori de date numerice, omogene;
PACHETUL
PANDAS (III)
Pandas imbina posibilitatile specifice NumPy
de calcul la nivelul vectorilor cu manipularea
flexibila a datelor din spreadsheet-uri si baze
de date relationale, oferind functionalitati
sofisticate de indexare, care permit
rearanjarea, felierea, sectionarea, agregarea si
selectarea subseturilor de date.

12
DATAFRAME
▪ În multe situații, ca și structură și comportament, un Dataframe se comportă similar unui
set de date SAS.
▪ Există mai multe metode pentru a încărca valori într-un DataFrame dintr-o gamă largă de
surse de intrare, precum fișiere .csv, tabele DBMS, API-uri REST, seturi de date SAS
(.sas7bdat ) etc. Acestea sunt similare liniei de produse SAS/Access.
▪ Pentru vizualizarea stucturii unui DataFrame se folosesc: atributul shape și metoda info()
care oferă informații similare cu PROC CONTENTS din SAS

#%%DataFrame
#import din sursa locala Pandas SAS
import pandas as pd DataFrame Set de date
file_loc = "E:\\Date\\uk_accidents.csv" Rând Observație
#file_loc=r"E:\Date\uk_accidents.csv" Coloană Variabilă
df = pd.read_csv(file_loc)
#df = pd.read_csv("uk_accidents.csv")
Groupby By-Group
print(df.shape) NaN . (punct)
Felie Subset
(266776, 27)
13
DATAFRAME – VIZUALIZARE ȘI PARSARE
#import din sursa web
import pandas as pd
df = pd.read_csv("https://raw.githubusercontent.com/AncaAndreescu/Date/main/uk_accidents.csv")
print(df.shape)
print(df.info())
#parsare data
import pandas as pd
file_loc = "E:\\Date\\uk_accidents.csv"
df = pd.read_csv(file_loc, parse_dates=['Date'])
print(df['Date'].dtype)

14
VALORI LIPSĂ
Pandas folosește două tipuri de obiecte pentru tratarea valorilor lipsă: obiectul None și obiectul NaN (not a
number).

La introducerea datelor folosim obiectul None pentru valori nule.

La afișarea datelor vor apărea None sau NaN în funcție de tipul de date.

#Construirea unui Dataframe cu valori lipsa


import pandas as pd
df2 = pd.DataFrame([['rece','incet', None, 2.7, 6.6, 3.1],
['cald', 'mediu', 4.2, 5.1, 7.9, 9.1],
['canicula', 'repede', 9.4, 11.0, None, 6.8],
['rece', None, None, None, 9.1, 8.9],
['rece', 'mediu', 6.1, 4.3, 12.2, 3.7],
[None, 'incet', None, 2.9, 3.3, 1.7],
[None, 'incet', None, 2.9, 3.3, 1.7]],
columns=['Temp', 'Viteza', 'Masura1', 'Masura2','Masura3', 'Masura4'])
print(df2)
#tipurile coloanelor
print(df2.dtypes) 15
VALORI LIPSĂ- REZULTATE
Temp Viteza Masura1 Masura2 Masura3 Masura4
0 rece incet NaN 2.7 6.6 3.1
1 cald mediu 4.2 5.1 7.9 9.1
2 canicula repede 9.4 11.0 NaN 6.8
3 rece None NaN NaN 9.1 8.9
4 rece mediu 6.1 4.3 12.2 3.7
5 None incet NaN 2.9 3.3 1.7
6 None incet NaN 2.9 3.3 1.7

Temp object
Viteza object
Masura1 float64
Masura2 float64
Masura3 float64
Masura4 float64

16
FUNCȚII PENTRU LUCRUL CU
VALORI LIPSĂ
Funcție Acțiune
isnull( ) Generează o mască booleană care indică valorile lipsă
print(df2.isnull()) notnull( ) Are efect opus funcției isnull()
dropna( ) Returnează o copie filtrată a Dataframe-ului inițial
#elemente lipsa pe coloane fillna( ) Returnează o copie a Dataframe-ului inițial având valorile
for col_name in df2.columns: nule completate în funcție de opțiunile funcției.
print (col_name, end="---->")
print (sum(df2[col_name].isnull()))

# elemente lipsa pe coloane var2


print (df2.isnull().sum())

17
OPERAȚII CU VALORI LIPSĂ
#operatia de adunare cu valori lipsa
• Într-un Datafame, comportamentul valorilor lipsă utilizate în operații și
df2['Sum_M3_M4'] = df2['Masura3'] + funcții matematice este similar cu comportamentul SAS.
df2['Masura4']
print(df2[['Masura3', 'Masura4', • În cazul Dataframe:
'Sum_M3_M4']])
– Într-o operație aritmetică la nivel de rând, valorile lipsă sunt propagate.
– Pentru metode și funcții, valorile lipsă sunt tratate ca fiind zero.
#functia sum() cu valori lipsa
print(df2['Sum_M3_M4'].sum()) – Dacă lipsesc toate valorile datelor, rezultatul unei metode sau funcții va fi zero.
#functia sum() cu valori lipsa cu skipna
print(df2['Sum_M3_M4'].sum(skipna=False)) • Parametrul skipna = False forțează sum () să returneze un NaN dacă o
valoare NaN este întâlnită în operație.
#functia sum() numai cu valori lipsa • Funcția sum() care primește ca intrare doar valori lipsă, returnează valoarea
df2['Masura5'] = None zero.
print(df2['Masura5'])
print(df2['Masura5'].sum())

18
PANDAS READERS (CITITORI)

• Cititorii pandas sunt o colecție de metode de intrare / ieșire pentru scrierea și încărcarea
valorilor în DataFrames.
• Facilitatea principală pandas pentru scrierea și citirea în/din DataFrames sunt cititorii, precum
read_csv (), read_json () și read_sql_table (), printre altele.
• Acești cititori folosesc o sintaxă similară. Primul argument este calea sau locația către țintă,
care poate fi nume de fișiere complet calificate, nume de fișiere relative (relativ la directorul de
lucru curent care execută Python), tabele din baze de date, adrese URL (inclusiv metode de
acces HTTPS, SFTP și S3) etc. În multe cazuri, valorile implicite pentru argumentele cititorilor
sunt suficiente pentru operațiile de citire / scriere.

19
METODELE CITITORULUI AU
ARGUMENTE DE SPECIFICAT:
• Locații de intrare și ieșire
• Locația și numele coloanei și indexului
• Reguli de parsare pentru gestionarea datelor primare
• Reguli pentru datele lipsă
• Manipularea datelor calendaristice
• Tratarea erorilor
• Reguli de citire
• Formate pentru fișiere

• Lista argumentelor: https://pandas.pydata.org/docs/reference/api/pandas.read_csv.html


20
ARGUMENTUL na_values
import pandas as pd
df = pd.read_csv('clienti_leasing_na.csv')
print(df.head())
lipsa = {'JOB' : ['NaN','-']}
df2 = pd.read_csv('clienti_leasing_na.csv', na_values=lipsa)
print(df2.head())

lipsa = {'JOB' : ['NaN','-']} creează obiectul lipsa ca o pereche cheie-valoare de tip dicționar
(dictionary): în care valoarea cheie JOB este numele coloanei DataFrame urmată de valorile 'NaN'și'-',
utilizate pentru a desemna ambele ca valori lipsă. Parametrul na_values = folosește acest dicționar lipsa pentru a
mapa valorile care sunt considerate lipsă atunci când sunt întâlnite în coloana JOB.

21
READ_SAS
Organizațiile au adesea un număr mare de seturi de date SAS
permanente, stocate pe sistemul de fișiere. pandas oferă cititorul
read_sas () pentru crearea de DataFrame, citind seturi de date SAS
permanente. Seturile de date SAS permanente sunt adesea denumite
fișiere .sas7bdat (după extensia utilizată de SAS pentru denumirea
fișierelor de seturi de date din sistemele de fișiere Windows și Unix).

import pandas as pd
df = pd.read_sas('produse.sas7bdat', encoding = 'latin-1')
print(df.head())
print(df.info())
df.Cod = df.Cod.astype(int)
print(df.head())
print(df.info()) 22
INDEXARE (I)
Pandas creează automat o structură de tip index la momentul creării unui DataFrame, atât pentru
rânduri, cât și pentru coloane.

Obiectul RangeIndex este folosit ca index implicit de rând. Aceste obiecte index sunt responsabile
pentru păstrarea etichetelor asociate axelor, precum și a altor metadate.

Una sau mai multe coloane din DataFrame pot fi utilizate pentru a defini un index.

Un index în Pandas poate fi considerat ca un mijloc pentru etichetarea rândurilor dintr-un


DataFrame.

Sintaxa parțială definire index:


DataFrame.set_index(drop=True, inplace=False)
• drop – scoate coloana indexată din DataFrame (implicit este advărată)
• inplace – arată dacă se fac modificările pe DataFrame sau se generează altul nou (implicit
este falsă)
23
INDEXARE (II)
#index implicit fara definire de coloane
import pandas as pd
df = pd.DataFrame([['0071', 'Patton' , 17, 27],
['1001', 'Joyner' , 13, 22],
['0091', 'Williams', 111, 121],
['0110', 'Jurat' , 51, 55],
['1106', 'Haskins', 51, 55],
['1189', 'Aden', 71, 70],
['1203', 'Tanner', 113, 122],
['1240', 'Jenkins', 99, 99]])
print(df)
print(' Index Rand: ', df.index, '\n', 'Index Coloana:', df.columns)

Index Rand: RangeIndex(start=0, stop=8, step=1)


Index Coloana: RangeIndex(start=0, stop=4, step=1)

24
INDEXARE (III)
#indesci cu definire de coloane
import pandas as pd
df = pd.DataFrame([['0071', 'Patton' , 17, 27],
['1001', 'Joyner' , 13, 22],
['0091', 'Williams', 111, 121],
['0110', 'Jurat' , 51, 55],
['1106', 'Haskins', 51, 55],
['1189', 'Aden', 71, 70],
['1203', 'Tanner', 113, 122],
['1240', 'Jenkins', 99, 99]]
,columns = ['ID', 'Nume', 'Inainte', 'Dupa'])
print(' Index Rand: ', df.index, '\n', 'Index Coloana:', df.columns)
df.set_index('ID', inplace=True)
print(df)
print(' Index Rand: ', df.index, '\n', 'Index Coloana:', df.columns)

Index Rand: RangeIndex(start=0, stop=8, step=1)


Index Coloana: Index(['ID', 'Nume', 'Inainte', 'Dupa'], dtype='object’)
-------------
Index Rand: Index(['0071', '1001', '0091', '0110', '1106', '1189',
'1203', '1240'], dtype='object', name='ID')
Index Coloana: Index(['Nume', 'Inainte', 'Dupa'], dtype='object') 25
CREAREA DE SUBSETURI
• Crearea de subseturi de date prin selectarea de rânduri și/sau coloane este o activitate
esențială pentru orice formă de analiză a datelor.
• Pandas oferă trei opțiuni pentru selectarea de rânduri și/sau coloane:

1. Operatorul [] - permite selectarea de coloane sau de rânduri (unidimensională).

2. loc - folosește etichete de rânduri și coloane pentru generarea de subseturi. Eticheta unei coloane
reprezintă numele acesteia, iar etichetele rândurilor sunt atribuite de un index (fie indexul implicit de la
momentul creării DataFrame, fie cel creat cu metoda set_index (). Dacă nu există nume atribuite coloanelor,
atunci, conform indexului implicit, se etichetează coloanele începând de la 0.

3. iloc - folosește poziții reprezentate prin numere întregi (de la 0 la lungime axă - 1) pentru selectarea
rândurilor și coloanelor. Această metodă rămâne disponibilă chiar dacă este definit un index definit de
utilizator.

26
OPERATORUL []
• Operatorul [] permite selectarea de linii sau coloane
• Selectarea coloanelor
▪ Folosește numele unei coloane sau o listă de nume de coloane( df[‘A’] sau df[[‘A’,’B’]])
▪ Poate folosi indexul implicit dacă nu au fost denumite coloanele (df[0] sau df[[0,1]])
• Selectarea înregistrărilor
• Sintaxa generală pentru felierea înregistrărilor folosind operatorul [] este: df [start: stop: step]
• Poziția de pornire este inclusă în ieșire, iar poziția de oprire nu este inclusă în ieșire (df[:3] sau
df[::2]).
• Pentru selectarea înregistrărilor pornind de la poziție sau valori se folosesc cu preponderență loc
și iloc deoarece oferă o gamă mult mai largă de opțiuni de selectare.
# Coloane:
df["Nume"] # coloana Nume
df[["Nume", "Inainte", "Dupa"]] # listă de coloane

# Inregistrari:
df[:4] # primele patru înregistrări
27
df[1::2] # înregistrările de pe poziții pare
ILOC (I)
Selectare cu iloc – selectare bazată pe poziție

• iloc folosește poziții întregi (de la 0 la lungime axă –1) pentru selectarea
rândurilor și coloanelor.
• Intrările permise pentru iloc sunt :
▪ un număr întreg, de exemplu, 12
▪ o listă Python de numere întregi [4, 2, 22]
▪ un domeniu de numere întregi 2:22 (în acest caz 2, este inclusiv, iar
poziția de oprire 22 este exclusivă)
• Absența selectării rândurilor se substituie prin caracterul “:”

28
ILOC (II)
• iloc integer-location based indexing: selecteaza linii si coloane dupa index/pozitie

# Selectie singulara cu iloc


# Inregistrari:
data.iloc[0] # prima inregistrare
data.iloc[1] # a doua inregistrare
data.iloc[-1] # ultima inregistrare a setului de date
# Coloane:
data.iloc[:,0] # prima coloana
data.iloc[:,1] # a doua coloana
data.iloc[:,-1] # ultima coloana a setului de date

# Selectie multipla cu iloc


data.iloc[0:5] # primele cinci inregistrari
data.iloc[:, 0:2] # primele doua coloane
data.iloc[[0,3,6,24], [0,5,6]] # inregistrarile 1, 4, 7, 25, coloanele 1, 6 si 7
data.iloc[0:5, 5:8] # primele cinci inregistrari si coloanele 6, 7 si 8).
29
DATAFRAME SI SERIES
Examinarea - activitatea de a afișa porțiuni din valorile incluse în DataFrame pentru a facilita
înțelegerea conținutului datelor.

În SAS, acest lucru se realizează cu funcții precum PROC PRINT și PROC SQL.

Funcțiile head () și tail () afișează în mod implicit primele cinci rânduri, respectiv ultimele cinci rânduri
ale unui DataFrame.

import pandas as pd

#setul de date de test poate fi gasit aici https://www.briandunning.com/sample-data/ si


contine date fictive
data = pd.read_csv('https://s3-eu-west-1.amazonaws.com/shanebucket/downloads/uk-500.csv’)

data.to_csv("output.csv")

print (type(data.head(3)))
print (type(data.iloc[:,1]))

<class 'pandas.core.frame.DataFrame'>
<class 'pandas.core.series.Series'> 30
LOC (I)
Selectare cu loc – selectare bazată pe etichete

• loc este o metodă utilizată în principal pentru returnarea rândurilor și coloanelor


folosind etichete.
• Intrările permise pentru loc sunt :
▪ o singură etichetă, cum ar fi 12 sau “Nume”. Rețineți că 12 este interpretat ca
eticheta rândului și nu ca locație întreagă de-a lungul indexului.
▪ o listă Python de etichete [‘A’, ‘B’, ‘C’].
▪ un domeniu de etichete ‘a’: ‘z’. În acest caz, atât limita ‘a’ cât și ‘z’ sunt inclusive
▪ evaluări condiționale
• Absența selectării rândurilor se substituie prin caracterul “:”
• Operatorul [] și iloc pot accesa rânduri folosind valoarea indexului implicit. Și loc poate
folosi valoarea indexului implicit, dar numai în absența unor alți indecși definiți pe linii
și/sau coloane.
• Pentru a permite selectarea în funcție de valorile datelor, loc necesită crearea unui
index definit de utilizator pentru a crea etichete la nivel de rând. 31
LOC (II)
• loc : selecteaza linii si coloane dupa etichetă/valoare
import pandas as pd
data = pd.read_csv('https://s3-eu-west-1.amazonaws.com/shanebucket/downloads/uk-500.csv')
#fixarea indexului pe coloana first_name
data.set_index("first_name", inplace=True)
#selectarea inregistrarilor, fiind afisata doar inregistrarile corespunzatoare
print(data.loc["Antonio"])
print(data.loc[["Antonio", "Peter"]])

import pandas as pd
data = pd.read_csv('https://s3-eu-west-1.amazonaws.com/shanebucket/downloads/uk-500.csv')
#fixarea indexului pe coloana first_name
data.set_index("first_name", inplace=True)
#selectarea coloanelor, first_name este afisata implicit
print(data.loc[["Antonio", "Peter"],['last_name', 'address', 'city']])

import pandas as pd
data = pd.read_csv('https://s3-eu-west-1.amazonaws.com/shanebucket/downloads/uk-500.csv')
#fixarea indexului pe coloana first_name
data.set_index("last_name", inplace=True)
print(data.loc[['Andrade', 'Veness'], 'city':'email'])
print(data.loc['Andrade':'Veness', ['first_name', 'address', 'city']]) 32
LOC (III)
• loc poate include expresii pentru selectarea conditionala a inregistrarilor.
• In expresiile conditionale se foloseste sintaxa: df[‘nume_coloana’]
• Nu este necesară indexarea

import pandas as pd
data = pd.read_csv('https://s3-eu-west-1.amazonaws.com/shanebucket/downloads/uk-500.csv')
print(data.loc[data['first_name'] == 'Antonio'])

import pandas as pd
data = pd.read_csv('https://s3-eu-west-1.amazonaws.com/shanebucket/downloads/uk-500.csv')

print(data.loc[data['first_name'] == 'Antonio', 'city':'email'])

print(data.loc[data['email'].str.endswith("hotmail.com"), 'phone1':'email'])

print(data.loc[data['first_name'].isin(['France', 'Tyisha', 'Eric'])])

print(data.loc[data['email'].str.endswith("gmail.com") & (data['first_name'] ==


'Antonio'), 'first_name':'email'])

print(data.loc[data['company_name'].apply(lambda x: len(x.split(' ')) == 1),


'company_name']) 33
SELECTAREA COLOANELOR
import pandas as pd • Pot fi utilizate patru metode pentru selectarea coloanelor:
df = pd.read_csv('clienti_leasing.csv')
#variante echivalente pentru selectarea – df.nume_coloana
coloanelor
print(df.SEX) – df['nume_coloana’]
print(df["SEX"])
print(df.iloc[:,3])
– df.iloc[:, index_coloana]
print (df.loc[:,"SEX"]) – df.loc[:, 'nume_coloana’]
• Cand se selecteaza o coloana, rezulta un vector de date unidimensional
print(df.DEPOSIT_AMOUNT.mean()) pandas.Series cu care se pot realiza mai multe operatii de:
(.sum()), (.mean()), (.count()), (.median()), inlocuire valori nule
import pandas as pd (.fillna(new_value)).
df = pd.read_csv('clienti_leasing.csv')
print(df[['SEX', 'DEPOSIT_AMOUNT']]) • Prin selectarea mai multor coloane se defineste un nou set de date. Sintaxa
#printeaza coloanele SEX, AGE si pentru selectarea multipla a coloanelor este:
DEPOSIT_AMOUNT
print(df.iloc[:, [3,10,14]])
– df[['nume_coloana_1', 'nume_coloana_2']]
– df.iloc[:, [0,1,20,22]]

34
SELECTAREA INREGISTRARILOR

• Se poate realiza metodele de selectare iloc/loc sau prin


selectori logici (selectare bazata pe valoarea unei
coloane sau variabile).
import pandas as pd
df = • Metodele de baza pentru selectarea inregistrarilor sunt:
pd.read_csv('clienti_leasing.csv')
print(df.iloc[0:10, :]) – df.iloc[0:10, :], selecteaza primele 10 inregistrari;
print(df.loc[44, :]) – df.loc[44, :], selecteaza inregistrarea 45
print(df.loc[[2, 44], :])
print(df[df["SEX"] == "m"]) – df[df[“SEX"] == “m"], selecteaza inregistrarile care
indeplinesc conditia.
– Simbolurile “, :” in metodele iloc si loc, pentru a specifica
selectarea tururor coloanelor, sunt opționale

35
ACTUALIZAREA VALORILOR DIN SETUL DE DATE
import pandas
df = pandas.read_csv('clienti_leasing20.csv', nrows=6, usecols =
['NAME_CLIENT','VENIT_PER_YEAR'])
print(df)
df.loc[1,'VENIT_PER_YEAR'] = 1500
print(df.loc[1,'VENIT_PER_YEAR'])
print(df)

import pandas as pd
data = pd.read_csv('clienti_leasing.csv')

data.loc[data['VENIT_PER_YEAR'] > 10000, "PRESCORING"] = 7

print(data.loc[data['PRESCORING'] == 7,'NAME_CLIENT'])

data.loc[(data['VENIT_PER_YEAR'] > 10000) & (data['SEX'] == 'm'), "PRESCORING"] = 8

print(data.loc[data['PRESCORING'] == 8,'NAME_CLIENT'])

36
STERGEREA COLOANELOR (DROP)
• Stergerea inregistrarilor sau a coloanelor dintr-un set de date se realizeaza prin functia drop.
• Pentru stergerea unei coloane sau a mai multor coloane, se utilizeaza numele coloanelor
specificand axis=I sau se utilizeaza parametrul ‘columns’ (nemaifiind necesar ‘axis’).
– Stergerea coloanei "Area" din set:
df = df.drop("Area", axis=1)
– Stergerea coloanei cu parametrul ‘columns’:
df = df.drop(columns=“Area")
• Stergerea unei coloane duce la crearea unui alt set de date. Pentru a modifica setul original
(curent), se utilizeaza parametrul inplace = True, nefiind returnata nicio valoare.
df.drop("Area", axis=1, inplace=True).
• Stergerea multipla a coloanelor
data = data.drop(["Y2001", "Y2002", "Y2003"], axis=1)

37
STERGEREA INREGISTRARILOR (DROP)
• Inregistrarile pot fi sterse utilizand functia drop si specificand axis=0.
import pandas as pd
df = pd.read_csv('clienti_leasing20.csv')
df.drop([1,2], axis = 0, inplace=True)
print(df)

• Drop() poate sterge inregistrarile pe baza unor expresii. Stergerea inregistrarilor care contin “ROL“.
In cazul stergerii bazate pe expresii, se va seta mai intai coloana indexata (CURRENCY) :
import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
df = df.set_index("CURRENCY")
df = df.drop("ROL", axis=0)
print(df)
• Pentru a sterge inregistrarile in functie de pozitia sau indexul acestora, se utilizeaza iloc. Stergerea
primelor cinci inregistrari utilizand iloc
import pandas as pd
df = pd.read_csv('clienti_leasing20.csv')
df = df.iloc[5:,].drop
print(df) 38
REDENUMIREA COLOANELOR (RENAME)
• Redenumirea coloanelor in pandas se realizeaza in doua moduri prin intermediul functiei rename.
• Redenumirea prin maparea denumilor vechi cu denumirile noi, astfel {“denumire_veche”:
“denumire_noua”, …}
import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
df.rename(columns={"ID_CLIENT": "COD"}, inplace=True)
print(df)

import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
df.rename(columns={"ID_CLIENT": "COD","AGE": "VARSTA"}, inplace=True)
print(df)
• Redenumirea printr-o functie care sa schimbe denumirile coloanelor si care se aplica pentru fiecare
coloana.
import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
df = df.rename(columns=str.lower)
#df = df.rename(columns=lambda x: x.lower().replace(' ', '_'))
print(df) 39
FUNCTII DE AGREGARE
import pandas as pd
df =
pd.read_csv('clienti_leasing.csv',usecols=['NAME_CLIENT','JOB','SEX','DEPOSIT
_AMOUNT','AGE’])

print('Suma depozitelor ', df['DEPOSIT_AMOUNT'].sum(), '\nMedia depozitelor',


df['DEPOSIT_AMOUNT'].mean())

print('Valoarea mediana ', df['DEPOSIT_AMOUNT'].median())

print('Valori unice ', df['DEPOSIT_AMOUNT'].nunique())

print('Venitul maxim ', df['DEPOSIT_AMOUNT'].max())

print('Numar observatii ', df['DEPOSIT_AMOUNT'].count())

40
IMPUNERE (FILLNA)
Decât să renunțe la un întreg rând sau coloană, valorile lipsă pot fi înlocuite (impuse) folosind funcții
matematice și statistice.

Metoda fillna () returnează un DataFrame (sau None dacă inplace=True) prin înlocuirea valorilor lipsă cu
anumite valori sau cu valori derivate.

import pandas as pd
df =
pd.read_csv('clienti_leasing20.csv',usecols=['NAME_CLIENT','JOB','SEX','VENIT_PER_YEAR'])
print(df['VENIT_PER_YEAR'])
print(df['VENIT_PER_YEAR'].fillna(0))

import pandas as pd
df =
pd.read_csv('clienti_leasing20.csv',usecols=['NAME_CLIENT','JOB','SEX','VENIT_PER_YEAR'])
print(df['VENIT_PER_YEAR'])
v_m = df['VENIT_PER_YEAR'].mean()
print(df['VENIT_PER_YEAR'].fillna(value=v_m))
41
PRELUCRARE DATE TRADITIONAL VS. PANDAS
from pprint import pprint
import pandas as pd
df = pd.read_csv('clienti_daune.csv')
set_clienti=[]
for index, row in df.iterrows():
if row['VALOARE_DAUNA'] > 2000:
set_clienti.append(row['ID_CLIENT'])
pprint (set_clienti)

from pprint import pprint


import pandas as pd
df = pd.read_csv('clienti_daune.csv')
set_clienti=[]
for index, row in df.iterrows():
if row['VALOARE_DAUNA'] > 1000:
set_clienti.append(row)
pprint (set_clienti)
v_marca = input("Introduceti marca: ");
print ("Marca selectata este : ", v_marca)
total_daune=0
for row in set_clienti:
if str(row['MARCA']).find(v_marca.upper())!=-1:
total_daune=total_daune+row['VALOARE_DAUNA']
print ("Valoarea totala a daunelor pentru marca", v_marca, " este: ", total_daune)
/
print ("Valoarea totala a daunelor pentru marca", v_marca, " este: ",
df['VALOARE_DAUNA'][(df['MARCA'] == v_marca.upper()) & (df['VALOARE_DAUNA']
42
>1000)].sum())
EXPORTUL (SALVAREA) SETURILOR PANDAS
• Functia to_csv pentru a salva un set de date intr-un fisier .csv
• Functia to_excel pentru a salva un set de date intr-un fisier Microsoft Excel
• Salvarea prelucrarilor intr-un fisier .csv
• Eliminarea indexului implicit Pandas la nivelul inregistrarilor, se realizeaza cu optiunea index=False.
• Pentru a Evita probleme de afisare a caracterelor, se poate utiliza optiunea encoding.
data.to_csv("output_filename.csv", index=False, encoding='utf8’)
• Salvarea prelucrarilor intr-un fisier Excel necesita instalarea pachetului “openpyxl” sau "xlsxwriter".
data.to_excel("output_excel_file.xlsx", sheet_name="Sheet 1", index=False)

43
TO_CSV
from pprint import pprint
import pandas as pd
df = pd.read_csv('clienti_daune.csv')
set_clienti=[]
for index, row in df.iterrows():
if row['VALOARE_DAUNA'] > 2000:
set_clienti.append(row['ID_CLIENT'])
pprint (set_clienti)
df = pd.DataFrame(set_clienti)
df.to_csv("output_clienti.csv")

#Varianta pandas
df=df.loc[df['VALOARE_DAUNA']>2000,'ID_CLIENT']
print(df)
df.to_csv("output_clienti.csv")

44
PRELUCRARE DATE PANDAS
from pprint import pprint
import pandas as pd
df = pd.read_csv('clienti_daune.csv')

pprint (df.loc[(df['AN_FABRICATIE'] < 2010) & (df['COMPONENTA'] =='BATTERY'), 'PRET_MANOPERA'])

df.loc[(df['AN_FABRICATIE'] < 2010) & (df['COMPONENTA'] =='BATTERY'), 'PRET_MANOPERA']=\


df.loc[(df['AN_FABRICATIE'] < 2010) & (df['COMPONENTA'] =='BATTERY'), 'PRET_MANOPERA']*1.10

pprint(df.loc[(df['AN_FABRICATIE'] < 2010) & (df['COMPONENTA'] =='BATTERY'), 'PRET_MANOPERA'])

df.to_csv('clienti_daune_mod.csv')

from pprint import pprint


import pandas as pd
df = pd.read_csv('clienti_daune.csv’)

#crearea unei coloane PROCENT_MANOPERA


df['PROCENT_MANOPERA'] =df['PRET_MANOPERA'] / df['VALOARE_DAUNA']*100
pprint (df)

df.to_csv('clienti_daune_mod.csv')
45
PYTHON

CURS 3
GRUPAREA SI AGREGAREA DATELOR (I)
• Pandas are un sistem de opțiuni care permite personalizarea unor aspecte ale comportamentului său. Cele mai
frecvente sunt opțiunile legate de afișare.
pandas.set_option (parametru, valoare)
• Exemplu: Setează numărul maxim de rânduri afișate. Variante: pd.set_option ("display.max_rows", 100)
sau pd.options.display.max_rows = 100

Prelucrări statistice simple


import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
pd.set_option("display.max_columns",5)
print(df.head())
print('Numarul de clienti')
print(df['ID_CLIENT'].count())
print('Venit maxim')
print(df['VENIT_PER_YEAR'].max())
print('Suma venitului pentru persoanele de sex masculin')
print(df['VENIT_PER_YEAR'][df['SEX'] == 'm'].sum())
print('Numarul valorilor distincte din coloana starea civila')
print(df['MARITAL_STATUS'].value_counts())
print('Numarul total de valori distincte din coloana starea civila')
print(df['MARITAL_STATUS'].nunique())
GRUPAREA SI AGREGAREA DATELOR (II)
Statistici descriptive
count 18239
unique 126
top Muncitor necalificat import pandas as pd
freq 5086 df = pd.read_csv('clienti_leasing.csv')
Name: JOB, dtype: object pd.set_option("display.max_columns",5)
count 18239.000000 print('Statistici descriptive')
mean 8344.006629 print(df['JOB'].describe())
std 11234.428174 print(df['VENIT_PER_YEAR'].describe())
min 0.070000
25% 2500.000000
50% 5000.000000 • Funcția describe () este utilizată pentru a genera statistici
descriptive care rezumă tendința centrală, dispersia și forma
75% 10000.000000 distribuției unui set de date, excluzând valorile lipsă.
max 408560.000000 • Pentru coloanele de tip object se calculează alți indicatori decât
Name:VENIT_PER_YEAR, dtype: float64 pentru coloanele numerice.
• Implicit se calculează indicatori pentru toate coloanele numerice.
GRUPAREA SI AGREGAREA DATELOR (III)
Funcțiile max(), min(), mean(), first(), last() pot fi utilizate cu GroupBy
import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
pd.set_option("display.max_columns",5)
df['DATA'] = pd.to_datetime(df['DATA'])
df['MONTH'] = pd.DatetimeIndex(df['DATA']).month
print('Prima inregistrare din coloana CURRENCY pe valori distincte')
print(df.groupby('CURRENCY').first())
print('Venitul anual insumat pentru fiecare luna')
print(df.groupby(pd.DatetimeIndex(df['DATA']).month)['VENIT_PER_YEAR'].sum())
print('Valoarea insumata a depozitului pentru ingineri pe sexe')
print(df[df['JOB'] == 'Inginer'].groupby('SEX')['VENIT_PER_YEAR'].sum())

• Când este importat un fișier CSV și se realizează un DataFrame, • Funcția groupby() împarte datele din DataFrame
obiectele Datetime din fișier sunt citite ca un obiect șir. Pe în diferite grupuri, în funcție de anumite criterii.
acestea este foarte greu să efectăm operații precum diferența de
timp. Metoda pandas to_datetime() ajută la convertirea șirului • Returnează un obiect de tip GroupBy.
în obiecte Python Datetime. • Funcții precum max(), min(), mean(), first(), last()
• pd.DatetimeIndex – permite efectuarea de operații complexe pot fi aplicate obiectului GroupBy pentru a obține
pe obiecte Datetime și conține metadate specifice acestora. statistici rezumative pentru fiecare grup.
GRUPAREA Grupări complexe
SI import pandas as pd
AGREGAREA df = pd.read_csv('clienti_daune.csv')
pd.options.display.max_rows = 999
D AT E LO R
(IV) print('Numarul de marci pentru fiecare
tara producatoare’)

print(df.groupby(['TARAPRODUCATOR',
'MARCA'])['MARCA'].count())
GRUPAREA
SI
AGREGAREA
D AT E LO R Sursa: https://www.shanelynn.ie/summarising-aggregation-and-grouping-data-in-
(V) python-pandas/

Gruparea și agregarea datelor cu agg – creare de noi coloane


import pandas as pd
df = pd.read_csv('clienti_daune.csv')
df[df['TARAPRODUCATOR']=='Canada'].groupby('MARCA').agg(
DAUNA_MAXIMA=pd.NamedAgg(column='VALOARE_DAUNA', aggfunc=max),
DAUNA_MINIMA=pd.NamedAgg(column='VALOARE_DAUNA', aggfunc=min),
DAUNA_TOTALA=pd.NamedAgg(column='VALOARE_DAUNA', aggfunc=sum)
)
GRUPAREA SI AGREGAREA DATELOR (VI)
Funcționalitatea de agregare oferită de funcția agg () permite calcularea mai multor
statistici pe grup într-un singur calcul.

Instrucțiunile pentru agregare sunt furnizate sub forma unui dicționar sau listă python.

Cheile dicționarului sunt utilizate pentru a specifica coloanele pe care se efectuează


operații, iar valorile dicționarului pentru a specifica funcția care se aplică.

Gruparea și agregarea datelor cu agg


import pandas as pd
df = pd.read_csv('clienti_daune.csv')
pd.options.display.max_rows = 999
print(df.groupby(['TARAPRODUCATOR','MARCA']).agg({'VALOARE_DAUNA':sum,
'ID_CLIENT': "count", 'MODEL': 'first'}))
df1 = df.groupby(['TARAPRODUCATOR','MARCA']).agg({'VALOARE_DAUNA':sum,
'ID_CLIENT': "count", 'MODEL': 'first'})
df1.to_csv('agregare.csv')
GRUPAREA SI AGREGAREA DATELOR (VII)

Pentru a aplica mai multe funcții unei singure coloane din datele grupate, se va specifica o
listă de funcții ca și valori ale dicționarului.

Aplicarea unor funcții multiple unei singure coloane din grup


import pandas as pd
df = pd.read_csv('clienti_daune.csv')
df['DATA_CERERE'] = pd.to_datetime(df['DATA_CERERE'])
print(df.groupby(['TARAPRODUCATOR', 'MARCA']).agg({'PRET_MANOPERA': [min,
max, sum], 'MODEL': "count", 'DATA_CERERE': [min, 'first', 'nunique']}))
GRUPAREA SI AGREGAREA DATELOR (IX)
import pandas as pd
pd.set_option('display.max_rows', None)
pd.set_option('display.max_columns', None)
df = pd.read_csv('clienti_daune.csv')
print('Grupare dupa MARCA, pentru fiecare marca afisam nr de modele')
print(df.groupby("MARCA")['MODEL'].count())
print("========================================")
print('Grupare dupa MARCA, pentru fiecare marca afisam nr de modele unice')
print(df.groupby("MARCA")['MODEL'].nunique())
print("========================================")
print('Afisam primele 5 marci cu cele mai multe modele')
print(df.groupby(['MARCA'])['MODEL'].count().nlargest(5))
print("========================================")
print('Grupare dupa MARCA, pentru fiecare marca afisam toate modelele')
print(df.groupby(["MARCA"])['MODEL'].apply(lambda x: ','.join(x)))
print("========================================")
• nunique – returnează numărul de observații distincte.
• nlargest - returnează primele n rânduri ordonate pe coloane în ordine descrescătoare.
• Se pot defini funcții inlinie folosind funcțiile „lambda” pentru a extrage statistici care nu sunt furnizate de opțiunile built-in.
• join () - returnează un șir prin unirea tuturor elementelor unui iterabil, separate printr-un separator de șiruri.
CONCAT, MERGE, JOIN
• Combinarea seturilor de date cu concat, merge / join dataframes
Concat – lipire seturi cu continut similar pe verticala sau pe orizontala
pd.concat([df_a, df_b])

pd.concat([df_a, df_b], axis=1)


CONCATENAREA

Biblioteca pandas implementează o metodă concat () similară în comportament cu


instrucțiunea SAS SET. Este folosit pentru a „lipi” DataFrames în funcție de rânduri sau de
coloane, similar declarației SAS MERGE.
Antetul metodei concat () este:
pd.concat(objs, axis=0, join='outer', join_axes=None, ignore_index=False, keys=None,
levels=None, names=None, verify_integrity=False, sort=None, copy=True)

• axis – axa pe care se realizează concatenarea {0-verticală, 1-orizontală}, implicit 0


• join – cum să se gestioneze indecșii pe axe {‘inner’, ‘outer’}, implicit ‘outer’

Sintaxa generala: https://pandas.pydata.org/docs/reference/api/pandas.concat.html


CONCAT()
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']},
index=[0, 1, 2, 3])
df4 = pd.DataFrame({'B': ['B2', 'B3', 'B6', 'B7'],
'D': ['D2', 'D3', 'D6', 'D7'],
'F': ['F2', 'F3', 'F6', 'F7']},
index=[2, 3, 6, 7])
rezultat = pd.concat([df1, df4], axis=1, join='inner')
print(rezultat)
print("---------------")
rezultat_ = pd.concat([df1, df4], axis=0, join='inner')
print(rezultat_)
INDEXAREA IERARHICĂ CU METODA
CONCAT()
• Metoda concat () permite construirea unui index ierarhic oferind argumentul keys= pentru a forma cel
mai exterior nivel.
import pandas as pd
df1 = pd.DataFrame({'A': ['A0', 'A1', 'A2', 'A3'],
'B': ['B0', 'B1', 'B2', 'B3'],
'C': ['C0', 'C1', 'C2', 'C3'],
'D': ['D0', 'D1', 'D2', 'D3']},
index=[0, 1, 2, 3])
df4 = pd.DataFrame({'B': ['B2', 'B3', 'B6', 'B7'],
'D': ['D2', 'D3', 'D6', 'D7'],
'F': ['F2', 'F3', 'F6', 'F7']},
index=[2, 3, 6, 7])
rezultat = pd.concat([df1,df4], keys=['df1', 'df4'])
print(rezultat)
print(rezultat.loc['df4’])

Având indexul ierarhic în poziție, putem identifica cu ușurință subseturi folosind indexatorul loc (). În acest
exemplu, loc () împarte acele rânduri care aparțin initial DataFrame-ului df4.
MERGE (I)
Antetul metodei merge () este:
pd.merge(left, right, how='inner', on=None, left_on=None, right_on=None, left_index=False,
right_index=False, sort=False. suffixes=('_x', '_y'), copy=True, indicator=False, validate=None)

• left, right – DataFrame plasat în stânga, respectiv dreapta


• how - definește tipul de combinare ('inner’ - implicit, alte opțiuni: 'outer', 'left’, și 'right’)
• on – după ce coloane sau indecși se face combinarea
• left_on și right_on - ce coloane sau indecși sunt prezenți doar în partea stângă sau dreaptă (implicit
None)
• sort – sortează cheile de joncțiune lexicografic în rezultat.
• indicator – dacă este True, adaugă o coloană la rezultat cu denumirea ''_merge'' sau o denumire
furnizată. Conține informații privind sursa fiecărui rând: ''left_only”/ ''right_only” / ''both''.
• validate – atunci când este specificat, verifică dacă se efectuează o combinare de un anumit tip:
''one_to_one'' sau ''1:1'', ''one_to_many'' sau ''1:m'', ''many_to_one'' or ''m:1''.
MERGE (II)
import pandas as pd
pd.options.display.max_columns = 10
df = pd.read_csv('clienti_leasing.csv')
df1 = pd.read_csv('clienti_daune.csv')
rezultat = pd.merge(df[['ID_CLIENT','NUME_CLIENT', 'PROFESIA',
'SEX','VENIT_ANUAL', 'VARSTA']],
df1[['ID_CLIENT', 'MARCA', 'PRET_MANOPERA',
'VALOARE_DAUNA']],
on='ID_CLIENT')
print(rezultat)
print('Structura fisier clienti_leasing.csv', df.shape)
print('Structura fisier clienti_daune.csv', df1.shape)
print(df['ID_CLIENT'].isin(df1['ID_CLIENT']).value_counts())

În cod se folosește argumentul on = „ID_CLIENT” pentru a indica folosirea coloanei ID_CLIENT ca o coloană cheie
găsită în ambele DataFrames. Argumentul on = ” ID_CLIENT” nu este necesar în acest exemplu, deoarece metoda
merge () detectează prezența unei coloane etichetate ID_CLIENT în ambele DataFrames și le atribuie automat ca și
coloană cheie. Argumentul how = efectuează implicit o joncțiune internă. Argumentul sort = este setat la False din
oficiu. Nu este surprinzător faptul că operațiile merge () pe DataFrames mari obțin îmbunătățiri substanțiale ale
performanței prin faptul că nu trebuie să returneze rândurile în ordine sortată.
MERGE (III)
#rez2 = pd.merge(df, df1, on='ID_CLIENT', how='outer', sort=False, validate="one_to_one" )
#rez2 = pd.merge(df, df1, on='ID_CLIENT', how='outer', sort=False, validate="one_to_many" )
#rez2 = pd.merge(df, df1, on='ID_CLIENT', how='inner', sort=False, validate="many_to_one" )
rez2 = pd.merge(df, df1, on='ID_CLIENT', how='outer', sort=False, validate="many_to_many" )
print(rez2)

În acest exemplu, argumentul validate = determină dacă îmbinarea are un tip specific de relație. Valorile
valide pentru validate = sunt:
• one_to_one sau 1: 1: Verifică dacă cheile sunt unice atât în DataFrame-ul din stânga, cât și în dreapta.
• one_to_many sau 1: m: Verifică dacă cheile sunt unice în Dataframe-ul din stânga.
• many_to_one sau m: 1: Verifică dacă cheile sunt unice în Dataframe-ul din dreapta.
• many_to_many sau m: m: Este permis, dar nu are ca rezultat o verificare.
Valoarea implicită este None. În acest exemplu, validate = ”one_to_one” generează o eroare
pandas.errors.MergeError și raportează că cheile, ID_CLIENT, nu sunt unice în setul de date din stânga sau
din dreapta.
MERGE (IV)
Data analytics pe clienti si daune
import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
df1 = pd.read_csv('clienti_daune.csv')
result = pd.merge(df[['ID_CLIENT','NUME_CLIENT', 'PROFESIA', 'SEX','VENIT_ANUAL',
'VARSTA']],
df1[['ID_CLIENT', 'VIN','MARCA', 'PRET_MANOPERA', 'VALOARE_DAUNA']],
on='ID_CLIENT')
print('Grupare dupa Id_client si Marca, calcul min, max, suma pentru Valoare_dauna si
numar daune (VIN)')
print(result.groupby(['ID_CLIENT', 'MARCA']).agg({'VALOARE_DAUNA': [min, max, sum],
'VIN': "count"}))
print('Afisam primele 5 marci cu cele mai multe daune')
print(result.groupby(['MARCA'])['VALOARE_DAUNA'].count().nlargest(5))
print(result.groupby(['MARCA'])['VALOARE_DAUNA'].size().nlargest(5))
print('Afisam primii 15 clienti cu cele mai multe daune')
print(result.groupby(['ID_CLIENT'])['VIN'].count().nlargest(15))
print('Afisam primii 15 clienti cu cea mai mare valoare totala a daunelor')
print(result.groupby(['ID_CLIENT'])['VALOARE_DAUNA'].sum().nlargest(15))

size() include valorile lipsă, count() nu face acest lucru


MERGE (V)
Left merge
import pandas as pd
pd.options.display.max_columns = 10
df = pd.read_csv('clienti_leasing.csv')
df1 = pd.read_csv('clienti_daune.csv')
result = pd.merge(df[['ID_CLIENT','NUME_CLIENT', 'PROFESIA',
'SEX','VENIT_ANUAL', 'VARSTA']],
df1[['ID_CLIENT', 'MARCA', 'PRET_MANOPERA',
'VALOARE_DAUNA']],
on='ID_CLIENT',
how='left')
print(result)
print(result.shape)
print('Structura fisier clienti_leasing.csv', df.shape)
print('Structura fisier clienti_daune.csv', df1.shape)
print(df['ID_CLIENT'].isin(df1['ID_CLIENT']).value_counts())
MERGE (VI)
Right merge
import pandas as pd
pd.options.display.max_columns = 10
df = pd.read_csv('clienti_leasing.csv')
df1 = pd.read_csv('clienti_daune.csv')
result = pd.merge(df[['ID_CLIENT','NUME_CLIENT', 'PROFESIA',
'SEX','VENIT_ANUAL', 'VARSTA']],
df1[['ID_CLIENT', 'MARCA', 'PRET_MANOPERA',
'VALOARE_DAUNA']],
on='ID_CLIENT',
how='right')
print(result)
print(result.shape)
print('Structura fisier clienti_leasing.csv', df.shape)
print('Structura fisier clienti_daune.csv', df1.shape)
print(df['ID_CLIENT'].isin(df1['ID_CLIENT']).value_counts())
MERGE (VII)
Full outer merge
import pandas as pd
pd.options.display.max_columns = 10
df = pd.read_csv('clienti_leasing.csv')
df1 = pd.read_csv('clienti_daune.csv')
result = pd.merge(df[['ID_CLIENT','NUME_CLIENT', 'PROFESIA',
'SEX','VENIT_ANUAL', 'VARSTA']],
df1[['ID_CLIENT', 'MARCA', 'PRET_MANOPERA',
'VALOARE_DAUNA']],
on='ID_CLIENT',
how='outer')
print(result)
print(result.shape)
print('Structura fisier clienti_leasing.csv', df.shape)
print('Structura fisier clienti_daune.csv', df1.shape)
print(df['ID_CLIENT'].isin(df1['ID_CLIENT']).value_counts())
MERGE (VIII)
Full outer merge cu indicația _merge
import pandas as pd
pd.options.display.max_columns = 10
df = pd.read_csv('clienti_leasing.csv')
df1 = pd.read_csv('clienti_daune.csv')
result = pd.merge(df[['ID_CLIENT','NUME_CLIENT', 'PROFESIA',
'SEX','VENIT_ANUAL', 'VARSTA']],
df1[['ID_CLIENT', 'MARCA', 'PRET_MANOPERA',
'VALOARE_DAUNA']],
on='ID_CLIENT',
how='outer',
indicator=True)
print(result)
print(result.shape)
print('Structura fisier clienti_leasing.csv', df.shape)
print('Structura fisier clienti_daune.csv', df1.shape)
print(df['ID_CLIENT'].isin(df1['ID_CLIENT']).value_counts())
MERGE (IX)
Merge utilizând trei seturi de date
import pandas as pd
df = pd.read_csv('clienti_leasing.csv')
df1 = pd.read_csv('clienti_daune.csv')
df2 = pd.read_csv('cars.csv')
result = pd.merge(df[['ID_CLIENT','NUME_CLIENT', 'PROFESIA',
'SEX','VENIT_ANUAL', 'VARSTA']],
df1[['ID_CLIENT', 'MARCA', 'PRET_MANOPERA',
'VALOARE_DAUNA']],
on='ID_CLIENT',
how='outer')
df2.rename(columns={"Motor": "CAPACITATE_MOTOR"}, inplace=True)
result = pd.merge(result[['ID_CLIENT','NUME_CLIENT', 'MARCA']],
df2,
left_on='MARCA',
right_on='MARCA_CARS',
how='left')
print(result)
print(result.shape)
MATPLOTLIB (I)
Grafic cu gruparea și sortarea datelor cu matplotlib.pyplot
import pandas as pd
import matplotlib.pyplot as plt
df = pd.read_csv('clienti_leasing20_r.csv')
plot_data=df[df['SEX']=='m']
plot_data=plot_data.groupby('PROFESIA')['VENIT_ANUAL'].sum()
plot_data.sort_values().plot(kind='bar', color = 'lightpink')
plt.show()
MATPLOTLIB (II)
Reprezentare grafică cu bare cu matplotlib.pyplot
import pandas as pd
import matplotlib.pyplot as plt
from matplotlib import cm
df = pd.read_csv('clienti_leasing20.csv')
print(df['AGE'])
#all_colors = list(plt.cm.colors.cnames.keys())
colors = cm.hsv( df['AGE']/ float(max(df['AGE'])))
df['AGE'].plot(kind='bar',color=colors)
plt.xlabel('ID_CLIENT')
plt.ylabel('AGE')
plt.show()
JOIN (I) - SUPLIMENTAR
Biblioteca pandas implementează metoda join () pentru a combina coloane, din două DataFrames indexate diferit, într-un
singur DataFrame. Metoda join () este o alternativă bună la apelarea metodei merge () în acele cazuri în care unui
DataFrame îi lipsește un index (altul decât RangeIndex implicit) sau în care coloanele cheie au nume diferite.

DataFrame-ul df1 este creat apelând metoda join () care face joncțiunea fie pe un index (ca în acest caz), fie pe
o coloană cheie desemnată.
În acest exemplu, apelul metodei join () efectuează implicit o joncțiune de stânga, cu argumentul how = ‘left’.
Indecșii din ambele coloane sunt păstrați pe noul DataFrame df1, în funcție de tipul de joncțiune numită.
Observați cum funcția print () afișează coloana index ca etichete de rând în df1.
import pandas as pd
left = pd.DataFrame(
{ 'Style' : ['S1', 'S2', 'S3', 'S4'],
'Size' : ['S', 'M', 'L', 'XL']},
index = ['01', '02', '03', '05'])
right = pd.DataFrame(
{ 'Color' : ['Red', 'Blue', 'White', 'Black'],
'Brand' : ['Polo', 'Motor', 'Zara', 'Bershka']},
index = ['01', '02', '03', '04'])
print(left)
print(right)
df1 = left.join(right, how='left')
print(df1)
#df1 = left.merge(right, how='left', left_index=True, right_index=True)
#print(df1)
JOIN (II)
Metoda join () prevede patru metode de joncțiune:

• Left: folosește indexul DataFrame apelant sau o coloană cheie, dacă este specificată. Aceasta este metoda
implicită pentru join ().

• Right: folosește celălalt index al DataFrame-ului.

• Outer: returnează uniunea de apelare a indexului DataFrame cu celălalt index DataFrame și sortează indexul.

• Inner: returnează intersecția indexului DataFrame apelant cu celălalt index DataFrame și păstrează ordinea
indexului DataFrame apelant.
JOIN (III)

df2 = left.join(right, how='outer')


print(df2)

df3 = left.join(right, how='inner')


print(df3)
JONCȚIUNEA COLOANEI CHEIE CU UN
INDEX
• În acele cazuri în care un DataFrame nu este indexat, utilizați argumentul on = pentru a identifica coloana
cheie utilizată într-o operațiune de joncțiune. Observați în exercițiul următor că Dataframe-ul din stânga
nu are un index și că DataFrame-ul din dreapta are.
import pandas as pd
left = pd.DataFrame(
{ 'Style' : ['S1', 'S2', 'S3', 'S4'],
'Size' : ['S', 'M', 'L', 'XL'],
'id' : ['01', '02', '03', '05']})
right = pd.DataFrame(
{ 'Color' : ['Red', 'Blue', 'White', 'Black'],
'Brand' : ['Polo', 'Motor', 'Zara', 'Bershka']},
index = ['01', '02', '03', '04'])
print(left)
print(right)
df1 = left.join(right, on='id', how='outer')
print(df1)
df2 = pd.merge(left, right, left_on='id', how='outer',
right_index=True)
print(df2)
SURSE BIBLIOGRAFICE

• https://matplotlib.org/index.html
• https://www.shanelynn.ie/summarising-aggregation-and-grouping-data-in-python-pandas/
• https://www.shanelynn.ie/merge-join-dataframes-python-pandas-index-1/
• Python for Data Analysis, DATA WRANGLING WITH PANDAS, NUMPY, AND IPYTHON,
Wes McKinney, 2nd edition, 2012, Ed. O’REILLY
• Data Science from Scratch, FIRST PRINCIPLES WITH PYTHON, Joel Grus, 2015, Ed. O’REILLY
• Python Data Science Handbook, ESSENTIAL TOOLS FOR WORKING WITH DATA, Jake
VanderPlas, 2016, Ed. O’REILLY
• Betancourt, R. and Chen, S., Python for SAS Users, Apress, 2019.
PYTHON
CURS 4
CONECTAREA LA BAZE DE DATE ORACLE –
PACHETUL CX_ORACLE
• Pachetul cx_Oracle conține metode pentru realizarea unei conexiuni cu o bază de date
Oracle, pentru gestiunea interogărilor și a tranzacțiilor (comenzile
SELECT/INSERT/UPDATE/DELETE/MERGE și COMMIT/ROLLBACK).
• Pentru realizarea conexiunii cu o bază de date Oracle se precizează userul, parola,
serverul (host/ip) și denumirea bazei de date (service name/SID). De exemplu, pentru
realizarea conexiunii cu serverul oracle care rulează pe IP-ul 37.120.250.20 cu service_name
oracle, nume utilizator student_ps și parola oracle se inițializează conexiunea următoare:
• connection = cx_Oracle.connect("student_ps", "oracle", "37.120.250.20/oracle")
• Pentru gestiunea interogărilor sau a tranzacțiilor este
necesară utilizarea unui cursor:
cursor = connection.cursor()
• Variabila de tip cursor dispune de toate metodele
CURSORUL necesare gestiunii tranzacțiilor și procesării interogărilor.
• Lista completă a metodelor acestuia este disponibilă aici:
https://cx-oracle.readthedocs.io/en/latest/cursor.html
METODE ALE CURSORULUI
Metoda Explicații
cursor.execute(comanda SQL, Execută comanda SQL specificată împreună cu lista de parametrii. Ca rezultat,
parametri) în cazul SELECT, cursorul este încărcat cu înregistrările returnate;

cursor.close() Închide cursorul și eliberează zona de memorie alocată;


cursor.fetchone() Încarcă înregistrările din cursor în variabile locale Python (de obicei în liste de
cursor.fetchmany(n) tupluri);
cursor.fetchall()
cursor.prepare(comanda SQL) Transmite comanda SQL către cursor fără a o executa;
cursor.rowcount Returnează numărul de înregistrări parcurse din cursor, inițial este 0, iar pe
măsură ce se utilizează comanda fetch(), numărul crește.

cursor.bindarraysize Precizează dimensiunea cursorului, utilizată în special la comanda INSERT;

cursor.setinputsizes() Precizează tipul de date, utilizată în special la comanda INSERT.


REALIZAREA INTEROGĂRILOR
• Realizarea interogărilor
• Pentru exemplificare se utilizează tabelele T_CLIENTI_DAUNE și T_CLIENTI_LEASING din
schema utilizatorului STUDENT_PS. Acestea au fost create prin importul fișierelor .csv Clienti_daune
și Clienti_leasing.
• Instrucțiunile SELECT sunt executate în cadrul cursorului astfel: cursor.execute("""SELECT *
FROM t_clienti_leasing""")
• Cursorul este încărcat cu tuplurile returnate de interogare, parcurgerea sa se poate realiza în cadrul
unui for:
for rec in cursor:
print("Values:", rec)
• După prelucrarea cursorului se recomandă închiderea sa, iar la final închiderea conexiunii cu baza de
date:
cursor.close()
connection.close()
METODELE FETCH, INTEROGARI CU PARAMETRI

• Pentru prelucrarea unui cursor se pot utiliza listele de tupluri, înregistrările putând fi încărcate
cu ajutorul metodelor cursorului:
fetchone() – încarcă o singură înregistrare;
fetchmany(n) – încarcă n înregistrări;
fetchall() – încarcă toate înregistrările din cursor.
• Interogări cu parametri:
• Parametrii se pot specifica direct în cadrul metodei execute() (a se vedea exemplul 2);
• O altă variantă presupune utilizarea metodei prepare () pentru realizarea interogării cu
parametru (a se vedea exemplul 3).
EXEMPLUL 1 INTEROGARI
Să se returneze numele, profesia, venitul anual și suma solicitată în cazul clienților care au solicitat mai mult de
5000 lei credit.
import cx_Oracle
from pprint import pprint

# Realizarea conexiunii cu serverul Oracle


# Conexiunea - user student_ps, parola oracle, host:37.120.250.20,
service_name oracle
connection = cx_Oracle.connect("student_ps", "oracle",
"37.120.250.20/oracle")
cursor = connection.cursor()
cursor.execute("""SELECT nume_client, profesia, venit_anual FROM
t_clienti_leasing WHERE suma_solicitata>5000""")
lista_clienti=cursor.fetchall()
# Inchidere cursor si conexiune
cursor.close()
connection.close()
# Afisare lista clienti
pprint (lista_clienti)
EXEMPLUL 2 INTEROGARI
Să se returneze valoarea totală a daunelor înregistrate pentru o anumită marcă auto introdusă de utilizator de la
tastatură.
import cx_Oracle
from pprint import pprint

# Realizarea conexiunii cu serverul Oracle


#Conexiunea - user student_ps, parola oracle, host:37.120.250.20, service_name
oracle
connection = cx_Oracle.connect("student_ps", "oracle", "37.120.250.20/oracle")
cursor = connection.cursor()
v_marca = input("Introduceti marca: ");
cursor.execute("""SELECT marca, sum(valoare_dauna) Total_daune FROM
t_clienti_daune where lower(marca) like :p_marca group by marca""",
p_marca='%'+v_marca.lower()+'%')
lista_daune=cursor.fetchall()
#inchidere cursor si conexiune
cursor.close()
connection.close()
#afisare lista marci cu daune
pprint (lista_daune)
EXEMPLUL 3 INTEROGARI
Să se returneze valoarea totală a daunelor pe fiecare marcă auto, dacă această valoare este mai mare decât o anumită valoare
prag. De la tastatură se va introduce valoarea prag pentru 2 apeluri succesive.
import cx_Oracle
from pprint import pprint
connection = cx_Oracle.connect("student_ps", "oracle", "37.120.250.20/oracle")
cursor = connection.cursor()
#pregatirea interogarii cu parametru
cursor.prepare("""SELECT marca, sum(valoare_dauna) Total_daune FROM t_clienti_daune
group by marca having sum(valoare_dauna)>:p_val""")
#primul apel
v_val = input("Introduceti valoarea: ")
cursor.execute(None, {'p_val': v_val})
lista_daune=cursor.fetchall()
#afisare lista marci cu daune
pprint (lista_daune)
#al doilea apel
v_val = input("Introduceti valoarea: ")
cursor.execute(None, {'p_val': v_val})
lista_daune=cursor.fetchall()
#afisare lista marci cu daune
pprint (lista_daune)
#inchidere cursor si conexiune
cursor.close()
connection.close()
CONTROLUL TRANZACTIILOR

• Operațiile de INSERT, UPDATE și DELETE sunt realizate tot prin intermediul unui cursor cu
ajutorul metodei execute().
• În cazul INSERT, se pot transmite mai multe înregistrări prin metoda executemany(). În acest caz
se recomandă să se precizeze numărul de înregistrări prin proprietatea bindarraysize și
tipul parametrilor prin metoda setinputsizes.
• Tranzacțiile se pot finaliza sau anula prin precizarea opțiunilor COMMIT sau ROLLBACK ale
conexiunii: connection.commit() sau connection.rollback()
EXEMPLUL 4 INSERT
Să se adauge o listă de tupluri în tabela CLIENTI_NOI care are următoarea structură: id_client number, nume_client varchar2(150),
profesia varchar2(150), sex varchar2(3), varsta number, stare_civila varchar2(1), suma_solicitata number. Să se finalizeze tranzacția și
apoi să se returneze înregistrările noi adăugate. Modificați secvența de cod și anulați tranzacția.
import cx_Oracle
from pprint import pprint
connection = cx_Oracle.connect("student_ps", "oracle", "37.120.250.20/oracle")
lista_clienti_noi = [(100, "Popa Marcel", "Inginer", "m", 34, "C", 230),
(101, "Popa Vasilica", "Coafeza", "f", 32, "C", 200),
(102, "Popa Ion", "Instalator", "m", 64, "C", 120)]
cursor = connection.cursor()
#adaugarea listei de clienti noi in tabela
cursor.bindarraysize = 3
cursor.setinputsizes(int, 150, 150, 3, int, 1, float)
cursor.executemany("insert into clienti_noi(id_client, nume_client, profesia, sex, varsta,
stare_civila,suma_solicitata) values (:1, :2, :3, :4, :5, :6, :7)", lista_clienti_noi)
cursor.close()
#finalizarea tranzactiei
connection.commit()
#interogarea bazei de date pentru vizualizarea inregistrarilor noi adaugate
cursor2 = connection.cursor()
cursor2.execute("""SELECT * from clienti_noi where nume_client like 'Popa%'""")
lista_clienti=cursor2.fetchall()
pprint(lista_clienti)
cursor2.close()
connection.close()
E X E M P L U L 5 U P D AT E
Să se majoreze cu 10% suma solicitată de clienții al căror nume este introdus de utilizator de la tastatură.
Actualizările se vor realiza pe tabela CLIENTI_NOI. Să se finalizeze/anuleze tranzacția și să se re-deschidă un
cursor pentru verificarea rezultatelor tranzacției.
import cx_Oracle
from pprint import pprint
connection = cx_Oracle.connect("student_ps", "oracle", "37.120.250.20/oracle"
cursor = connection.cursor()
#adaugarea listei de clienti noi in tabela
statement="update clienti_noi set suma_solicitata=suma_solicitata*1.10 where
lower(nume_client) like :p_nume"
v_nume=input("Introduceti numele clientului:")
cursor.execute(statement,p_nume='%'+v_nume.lower()+'%')
cursor.close()
#finalizarea tranzactiei
connection.commit()
#interogarea bazei de date pentru vizualizarea inregistrarilor noi adaugate
cursor2 = connection.cursor()
cursor2.execute("""SELECT * from clienti_noi where lower(nume_client) like :p_nume""",
p_nume='%'+v_nume.lower()+'%')
lista_clienti=cursor2.fetchall()
pprint(lista_clienti)
cursor2.close()
connection.close()
EXEMPLUL 6 DELETE
Să se șteargă din tabela CLIENTI_NOI clienții cu numele de familie Popa. Să se finalizeze tranzacția.

import cx_Oracle

# Realizarea conexiunii cu serverul Oracle


#Conexiunea - user student_ps, parola oracle, host 37.120.250.20, service_name oracle
connection = cx_Oracle.connect("student_ps", "oracle", "37.120.250.20/oracle")

cursor = connection.cursor()

#stergerea clientilor cu numele Popa


statement="delete from clienti_noi where nume_client like 'Popa%'"
cursor.execute(statement)
cursor.close()

#finalizarea tranzactiei
connection.commit()
connection.close()
EXEMPLUL 7 INCARCARE IN PANDAS
• Înregistrările returnate de o interogare SQL se pot încărca direct într-un DataFrame Pandas prin metoda
pandas.read_sql(comanda SQL, conexiunea, lista de parametri).
• În acest caz nu mai este necesară încărcarea înregistrărilor în cursor, acestea fiind gestionate automat de
către DataFrame.
Să se selecteze din tabela T_CLIENTI_DAUNE marca, modelul, anul de fabricație, componenta, prețul
manoperei și valoarea daunei pentru autoturismele mai noi de 2010.
import pandas as pd
import cx_Oracle
from pprint import pprint
# Connect to oracle.
connection = cx_Oracle.connect("student_ps", "oracle",
"37.120.250.20/oracle")
#incarcam in DataFrame inregistrarile returnate de SELECT
an=2010
query ="""Select marca, model, an_fabricatie, componenta, pret_manopera,
valoare_dauna
from t_clienti_daune
where an_fabricatie>:an"""
df = pd.read_sql(query, con=connection, params={'an': an})
pprint(df)
connection.close()
EXEMPLUL 8 PRELUCRARE IN PANDAS
Pornind de la exemplul anterior, în exemplul de mai sus să se adauge o nouă coloană în df pentru a calcula
ponderea manoperei din valoarea totală a daunei. Să se afișeze marca și componentele înlocuite în cazul în
care ponderea depășește 30% din valoarea daunei.
import pandas as pd
import cx_Oracle
from pprint import pprint
# Connect to oracle.
connection = cx_Oracle.connect("student_ps", "oracle",
"37.120.250.20/oracle")
#incarcam in DataFrame inregistrarile returnate de SELECT
an=2010
query ="""Select marca, model, an_fabricatie, componenta, pret_manopera,
valoare_dauna
from t_clienti_daune
where an_fabricatie>:an"""
df = pd.read_sql(query, con=connection, params={'an': an})
connection.close()

df["PROCENT"]=df["VALOARE_DAUNA"]/df["PRET_MANOPERA"]
pprint(df.loc[(df["PROCENT"]>30), ["MARCA","COMPONENTA"]])
EXERCIȚII PROPUSE (I)
1. Să se returneze într-un df componenta, anul de fabricatie și pretul manoperei
pentru autoturismele Ford și Jeep. Pe setul din df, majorați cu 10% pretul
manoperei pentru autoturismele fabricate inainte de 2010 și care au
componenta BATTERY defectă. Salvați modificările într-un fișier .csv.
EXERCIȚII PROPUSE (II)
2. Încărcați într-un df marca, modelul, valoarea medie și numărul de daune pe
fiecare model și marcă. Afișați numărul de autoturisme pentru care valoarea
medie depășește 400 lei. Reprezentați grafic modelele care au înregistrat mai
mult de 200 de daune.
EXERCIȚII PROPUSE (III)
3. Încărcați într-un df numele, suma solicitată, suma din depozite și fidelitatea
clienților cu vârsta > 30 de ani care au solicitat un credit mai mare de 10.000 lei.
Verificați în df dacă suma din depozit este mai mare decât suma solicitată și
pentru acești clienți modificați fidelitatea în 5 (doar în df).
EXERCIȚII PROPUSE (IV)
4. Încărcați într-un df profesia, venitul anual, suma din depozite și suma solicitată
pe fiecare profesie. În df adăugați o nouă coloană pentru a calcula gradul de
îndatorare pe fiecare profesie (suma_solicitata/(venit_anual+suma_depozit)*100).
EXERCIȚII PROPUSE (V)
5. Încărcați într-un df starea civilă, profesia și suma totală solicitată grupată în
funcție de aceste atribute. Introduceți de la tastatură profesia și pentru aceasta
reprezentați grafic suma solicitată în funcție de starea civilă.
• Using Python with Oracle Database 11g,
https://www.oracle.com/technetwork/articles/dsl/python-
091105.html
• Developing a Python Web Application with Oracle Database 11g,
SURSE https://www.oracle.com/webfolder/technetwork/tutorials/obe/db/
BIBLIOGRAFICE OOW11/python_django/python_django.htm
• https://learncodeshare.net/2015/06/26/insert-crud-using-
cx_oracle/
Introducere
în SAS
CUPRINS Curs

1. Prelucrări analitice
2. Sistemul integrat SAS
3. Programea în limbajul SAS
Definirea conceptului

• Prelucrările analitice (engl. Analytics) reprezintă punerea în


aplicare a tehnologiei informaţiei, a cercetărilor operaţionale şi a
statisticii pentru rezolvarea problemelor din diverse domenii.
• Pot constitui intrări pentru deciziile umane sau pot determina
decizii complet automatizate.

• Sunt considerate o parte a ceea ce este cunoscut sub denumirea


de Inteligenţa afacerii.
Optimizări Cum este cel mai
bine?
Modelare predictivă Ce se va Prelucrări
întâmpla? analitice
Dacă tendinţa
Prognoze
continuă?
Analize
statistice De ce se întâmplă?
competitive

Alerte
Avantaje

Ce se poate face?
Unde este
Interogări/descompuneri
problema? Accesare şi
Cât, cât de des, raportare
Rapoarte ah-hoc
unde?
Rapoarte standard Ce şi când s-a
întâmplat?

Niveluri de prelucrare a datelor


Categorii de software pentru prelucrări analitice

• Instrumente bazate pe foi de calcul


• Instrumente OLAP
• Software pentru analize statistice - SAS, SPSS, SYSTAT,
STATISTICA, MINITAB, JMP
• Limbaje de programare cu capabilități extinse pentru
prelucrări analitice: R, Python
• Software pentru optimizări
• Instrumente de data mining
• Instrumente de text mining
Sistemul integrat SAS
• A fost dezvoltat la începutul anilor 1970 la North Carolina State
University.
• Intenţia iniţială a fost dezvoltarea unui sistem pentru
managementul şi analiza experimentelor în domeniul agricol.
• La momentul actual este cel mai utilizat software statistic.
• Iniţial a fost acronimul pentru “Statistical Analysis System”,
acum nu mai are acest sens.
• Conţine o mare varietate de module care acoperă aria
prelucrării analitice a datelor şi nu numai.
Soluții SAS
Funcţii de bază ale SAS
• Introducerea, regăsirea şi managementul datelor
• Realizarea de rapoarte şi grafice
• Analize statistice şi matematice
• Previziuni şi suport decizional
• Cercetări operaţionale şi managementul proiectelor
• Dezvoltarea de aplicaţii
Soluţii SAS dedicate
• Managementul riscurilor
• Detectarea fraudelor
• Managementul clienților
Modularizarea SAS
▪ SAS constă dintr-un număr mare de module, pe care
organizaţiile le pot achiziţiona şi instala separat, în funcţie de
necesităţi.
▪ În centrul soluţiilor SAS se află modulul Base SAS. Acesta este
un mediu software integrat, având facilităţi pentru accesul la
date, analiza datelor, crearea de rapoarte etc.
▪ Base SAS beneficiază şi de suportul unui limbaj de
programare proprietar de generaţia a patra.
▪ Există o gamă largă de module sau pachete care extind
capabilităţile motorului de bază Base SAS.
Exemple de module SAS
• Base SAS – managementul datelor şi proceduri de bază
• SAS/STAT – analize statistice
• SAS/GRAPH – grafice şi hărţi
• SAS/OR – cercetări operaţionale
• SAS/ETS – econometrie şi analiza seriilor de timp
• SAS/IML – limbaj specializat pentru lucrul cu matrice
• SAS/QC – controlul calităţii
Caracteristici principale
• SAS poate citi orice sursă de date
• Are foarte multe facilități pentru transformarea și modelarea
datelor în scopul prelucrării analitice
• Compania are unii dintre cei mai inovatori angajați în cercetare și
dezvoltare din industrie
• Are avantajul unor investiții de mare anvergură în dezvoltarea
produselor oferite
• Produsele sale sunt bine susținute de suport tehnic
• Foarte multă documentație disponibilă
• Parteneriate educaționale bine susținute
Moduri de lucru în SAS
• Programabil: SAS 9.4, SAS Studio
• Folosind interfeţe generatoare de cod: SAS Enterprise Guide
• Utilizând medii de dezvoltare în cloud: SAS Viya, SAS Studio

Interacţiunea dintre SAS Enterprise Guide şi un motor SAS


Programe SAS
Un program SAS constă dintr-o succesiune de secțiuni (steps) distincte
trimise către execuţie motorului SAS. În SAS există două tipuri de
secțini: de date și de proceduri.

Secţiunile de date (DATA steps) sunt, de


obicei, folosite pentru a crea și modifica
Fişier tabele SAS.
Text
Secţiune de Secţiune de
date Tabelă proceduri
Raport
SAS
nouă
Tabele
SAS Secţiunile de proceduri (PROC steps) sunt, de
existente obicei, folosite pentru a efectua prelucrări şi
interogări.

Un program SAS poate conține orice combinație de secțiuni de date și


13
de proceduri, în funcție de problema care trebuie rezolvată.
Tipuri de fişiere cu care lucrăm în SAS

ASCII
Externe Fişiere generate de alte aplicaţii

Fişiere în SAS
Interne Temporare – nume pe un nivel
Permanente - nume pe nouă niveluri
(libref.nume)

14
Reguli de sintaxă
Declarațiile SAS au următoarele caracteristici:
◼ Încep, de obicei, cu un cuvânt cheie.

◼ Întotdeuna se termină cu punct şi virgulă.

libname ad_data '/home/nume.prenume';


data ad_data.comenzi;
infile '/home/nume.prenume/comenzi.txt';
input Nr_Comanda 1-5 ID_Produs $ 2-10
Cantitate 13-15 PretVanzare 17-22
Venit 25-32;
run;
proc print data=ad_data.comenzi;
run;
proc means data=ad_data.comenzi;
title 'Analiza comenzilor';
var PretVanzare;
run;
15
Reguli de sintaxă

16
SAS Studio

17
Reguli de sintaxă
◼ Unul sau mai multe caractere de spaţiere pot fi folosite pentru
a separa cuvintele.
◼ Declarațiile pot începe şi se pot termina în orice coloană.
◼ O singură declarație se poate scrie pe mai multe rânduri.
◼ Mai multe declarații pot fi scrise pe aceeaşi linie.

libname ad_data '/home/nume.prenume';


data ad_data.comenzi;
infile '/home/nume.prenume/comenzi.txt';
input Nr_Comanda 1-5 ID_Produs $ 2-10
Cantitate 13-15 PretVanzare 17-22
Venit 25-32;
run;
proc print data=ad_data.comenzi;
run;
proc means data=ad_data.comenzi;
title 'Analiza comenzilor';
var PretVanzare; run; 18
Comentarii
◼ Comentarii bloc: /*comentariu*/
◼ Comentarii care pot fi incluse in cod: * comentariu;
◼ cod * comentariu; cod…

/* Creaza tabela SAS ad_data.orders */


libname ad_data '/home/nume.prenume';
data ad_data.comenzi;
infile '/home/nume.prenume/comenzi.txt';
input Nr_Comanda 1-5 ID_Produs $ 2-10
Cantitate 13-15 PretVanzare 17-22 Venit 25-32;
run;
/* Realizeaza un raport lista
pentru ad_data.orders */
proc print data=ad_data.comenzi;
run;

19
Limite ale unei secţiuni

◼ SAS compilează şi execută fiecare secţiune în mod


independent bazându-se pe ceea ce poartă denumirea de
limite ale unei secţiuni.
◼ Limitele unei secţiuni:
◼ Limite explicite: RUN şi QUIT au rolul de a executa
secţiunea anterioară;
◼ Limite implicite: DATA şi PROC indică începutul unei
secţiuni.
◼ O secţiune de date sau de proceduri se termină atunci
când se întâlneşte o altă secţiune, ceea ce înseamnă că
prezenţa declaraţiilor RUN şi QUIT nu este obligatorie.
◼ Se recomandă, ca bună practică în scrierea de cod și
pentru depanare, specificarea limitelor explicite.
20
Crearea seturilor de date din fișiere
externe
Pentru a aplica proceduri specifice SAS, datele trebuie să fie
disponibile în seturi de date SAS.
Dacă datele nu se regăsesc în formatul specific SAS, atunci
există următoarele alternative de lucru:
➢ Crearea de seturi de date prin introducerea de date în
codul sursă prin care se crează setul de date (cu
DATALINES).
➢ Citirea datelor disponibile în fișiere flat. Acestea nu sunt
fișiere proprietare, iar înregistrările conțin valori care sunt
organizate în câmpuri.
➢ Accesarea datelor create prin intermediul altor aplicații,
spre exemplu MS Excel, Oracle, SPSS.
Indiferent de modalitatea de introducere a datelor sursă, se va
folosi secțiunea de date pentru a citi datele de intrare și a crea
21
setul de date rezultat.
Date furnizate în codul sursă
◼ Trebuie furnizate valorile datelor în interiorul secțiunii de date prin
declarația DATALINES (sau CARDS – un alias al acestei declarații,
provenit dintr-o versiune mai veche a limbajului).
◼ Setul de date de mai jos se salvează în biblioteca WORK (are numele pe
un singur nivel), fiind deci temporar.

data comanda;
input varsta gen $ id_prod cantitate data mmddyy8.;
format data yymmdds10.;
datalines;
25 f 02344 2 05/27/10
37 m 08798 4 04/29/10
45 f 09876 1 05/27/10
19 m 07897 3 05/30/10
proc sort data=comanda; by descending data;
proc print data=comanda;
title ‘Comenzi neonorate';
22
D AT E F U R N I Z AT E Î N
CODUL SURSĂ
23
Înțelegerea structurii seturilor de date
Un set de date SAS este format din două zone:
➢ Zona de descriere = conține informații care caracterizează setul
de date per ansamblu, cum ar fi numele setului de date, data
creării, descrierea fiecărei variabile (nume, tip, lungime) etc.
Aceste informații poartă denumirea de metadate și pot fi
vizualizate cu procedura CONTENTS.
PROC CONTENTS DATA = set_date;
➢ Zona de date = conține datele propriu-zise ale setului de date,
care pot fi vizualizate cu o multitudine de proceduri, printre care
cea mai utillizată este PRINT.
PROC PRINT DATA = set_date;

24
Convenții de denumire specifice SAS

Numele specificate de către utilizatori în SAS pentru o multitudine


de elemente ale limbajului, precum seturi de date, variabile,
proceduri, referințe la bibiloteci, formate etc. trebuie să respecte o
serie de convenții de denumire:
▪ numele începe cu o literă sau cu caracterul ” _” underscore;
▪ conţine litere, cifre sau caracterul underscore;
▪ are o lungime de maximă predefinită (spre exemplu, 32 de
caractere pentru numele de variabile și seturi de date, 8
caractere pentru referințe la biblioteci);
▪ nu este case sensitive;
▪ nu poate conține spații.

25
Tipuri de date
SAS a simplificat lucrul cu tipuri de date, existând date de tipul
numeric și de tipul caracter. Implicit, variabilele unui set de date
pot fi de tip numeric sau caracter.
▪ Variabilele numerice pot memora și valori în format științific și
sunt implicit stocate pe 8 octeți. Variabilele de tip caracter pot
memora până la 32.767 de caractere, fiecare caracter fiind stocat
pe un octet.
▪ Valorile de tip dată și timp sunt stocate în SAS ca și valori
numerice. Valoarea unei date calendaristice SAS este stocată
intern sub forma numărului de zile dintre data de 1 ianuarie 1960
și data specificată, putând fi un număr pozitiv sau negativ.
Valoarea de tip timp în SAS este stocată sub forma numărului de
secunde care s-au scurs de la miezul nopții în ziua curentă, deci
este o valoare între 0 și 86400.

26
Biblioteci SAS -1
◼ O bibliotecă SAS este o colecţie care include unul sau mai multe
fişiere SAS care sunt recunoscute de SAS şi care sunt referite şi
stocate în mod unitar.
◼ Sintaxa este:
LIBNAME libref ‘Biblioteca-SAS‘;
▪ LIBNAME – defineşte o bibliotecă.
▪ libref – este o referinţă la o bibliotecă, un alias pentru o locaţie fizică
unde se găsesc fişierele incluse în bibliotecă.
▪ ‘Bilioteca-SAS‘ – este locaţia fizică propriu-zisă
LIBNAME exemple ‘C:\curs‘;
◼ LIBNAME nu este parte a unei secţiuni de date sau de proceduri şi
nu are nevoie de RUN pentru a rula.
◼ Referința la o bibliotecă rămâne valabilă până când aceasta se
anulează sau se schimbă sau până când se termină sesiunea SAS.

27
Biblioteci SAS -2
◼ Libref trebuie să refere un director existent, deoarece prin această
declarație nu se creează un nou director.
◼ Se pot defini oricâte declaraţii LIBNAME.
◼ Biblioteca Work este temporară şi se iniţializează la deschiderea
sesiunii de lucru SAS.
◼ Vizualizarea conținutului unei biblioteci se face cu procedura
CONTENTS.

PROC CONTENTS DATA= lifref._ALL_ NODS;


RUN;

◼ Opțiuni: _ALL_ include toate fișierele din bibliotecă, iar NODS nu


include zona de descriere a unui set de date.

28
Crearea seturilor de date din fișiere flat

Delimitatorul spaţiu
Considerând că avem un fişier numit exemplu1.txt care conţine
numele, preţul şi categoria a șase tipuri de copaci vândute,
fiecare având valoarea separată printr-un spaţiu, acesta ar avea
următoarea formă:
brad 40 conifer
molid 25 conifer
fag 42 foios
stejar 27 foios
liliac 33 arbust
alun 38 arbust
data exemplu1;
infile '/home/nume.prenume/exemplu1.txt';
input Nume $ Pret Categorie $;
run;
29
CREAREA SETURILOR DE DATE DIN
FIȘIERE FL AT-
DELIMITATORUL SPAŢIU

30
Delimitatorul virgulă

Pentru fişierul de date:


brad,40,conifer
molid,25,conifer
fag,42,foios
stejar,27,foios
liliac,33,arbust
alun,38,arbust
Se vor folosi următoarele declaraţii pentru a obţine setul de date exemplu2:
data exemplu2;
infile '/home/nume.prenume/exemplu2.txt' dsd;
input Nume $ Pret Categorie $;
run;
31
Alţi delimitatori

• Pentru orice alt tip de delimitatori, instrucţiunea infile


trebuie folosită împreună cu opţiunea dlm sau delimiter.
Au aceeaşi seminificaţie, prima fiind abrevierea celeilalte.
Exemplu:
infile 'c:\date sas\produse.txt' delimiter='/';
sau
infile 'c:\date sas\produse.txt' dlm='/';.

32
Fişiere cu date în coloane cu lăţime fixă

Cel de-al doilea tip de fişiere flat pe care SAS poate să le


citească sunt cele care conţin date în coloane cu lăţime
fixă. Pentru acestea există două modalităţi de citire:
▪ coloane de intrare (column input)
▪ intrări formatate (formatted input)
Avantajul folosirii datelor în coloane cu lăţime fixă este acela
că datele pot fi citite în orice ordine este necesară, iar
valorile lipsă pot fi specificate prin tot atâtea spaţii libere
cât are şi lăţimea coloanei.

33
Fişiere cu date în coloane cu lăţime fixă
- exemplu
Considerăm un fișier în care valorile din fiecare câmp încep de la o
anumită poziție:
brad 40 conifer
molid 25 conifer
fag 42 foioase
stejar 27 foioase
liliac 33 arbusti
alun 38 arbusti

Aşa cum se poate observa, numele are maxim 6 caractere, preţul 2, iar
categoria 7.

34
Fişiere cu date în coloane cu lăţime fixă

• Metoda 1: Coloane de intrare foloseşte declaraţia


INPUT specificând pentru fiecare variabilă numele său,
semnul $ pentru variabilele caracter, precum şi poziţia de
început şi de sfârşit a fiecărei variabile în linia de date.
*citire fisier text cu latime fixa metoda coloane
de intrare;
data exemplu3;
infile "/home/nume.prenume/exemplu3.txt";
input Nume $ 1-6
Pret 8-9
Categorie $ 10-17;
run;

35
Fişiere cu date în coloane cu lăţime fixă

36
Fişiere cu date în coloane cu lăţime fixă

• Metoda 2: Intrări formatate poate citi diferite tipuri de


formate, cum ar fi monedă (numere având semnul dolar sau
euro), numere cu zecimale, date în diferite formate.
• Declaraţia INPUT are umătoarele opţiuni: semnul @ urmat de
poziţia de început a variabilei în linia de date, numele variabilei,
formatul variabilei, dacă acesta este necesar, precum şi lăţimea
coloanei asociată variabilei.

INPUT @pozitie nume_varialilă format lăţime.

37
Exemplu metoda 2
*citire fisier text cu latime fixa metoda intrari
formatate;
data exemplu4;
infile '/home/nume.prenume/exemplu4.txt';
input @1 Nume $6.
@8 Pret dollar3.
@12 Categorie $7.;
format Pret dollar6.2;
/*
datalines;
brad $40 conifer
molid $25 conifer
fag $42 foioase
stejar $27 foioase
liliac $33 arbusti
alun $38 arbusti */
run;

38
Asignarea de etichete

▪ Declarația LABEL asignează etichete variabilelor din setul de


date de ieșire.
▪ Multe proceduri SAS folosesc etichetele variabilelor pentru a
îmbunătăți întelegerea semnificației datelor.
▪ Echichetele se pot crea și în secțiunile de date, și în cele de
proceduri.
LABEL variabila1 = “Eticheta1”….. ;
▪ Într-o singură declarație LABEL se pot defini etichete pentru
oricâte variabile.
▪ Pot avea până la 256 de caractere scrise între ghilimele simple
sau duble.
▪ Redefinirile ulterioare suprascriu definirile inițiale ale valorilor
etichetelor. 39
Asignarea de etichete - exemplu
***Definire etichete in sectiunea de date;
DATA agenti;
INPUT Cod Oras$ Vanzari;
LABEL Cod = "Cod agent"
Vanzari = "Vanzari trim I";
DATALINES;
1101 BZ 100000
1102 CJ 250000
1103 BU 400000
1104 CJ 270000
1105 BU 150000
1106 BZ 80000
;
RUN;
***Utilizare etichete in sectiunea de proceduri;
PROC PRINT DATA =agenti LABEL;
RUN;
***Definire si utilizare etichete in sectiunea de proceduri;
PROC PRINT DATA =agenti LABEL;
LABEL Oras = "Filiala" Cod = "Cod agent vanzari";
40
RUN;
Asignarea de etichete - exemplu

Etichetele definite în
secțiunea de date rămân
asignate setului de date.

Etichetele definite în
secțiunea de proceduri sunt
valabile doar în interiorul
acesteia.

41
Formate SAS de afișare
În SAS există formate de citire și formate de afișare. Formatele de
citire oferă instrucțiuni despre modul cum se citesc datele din
fișierele externe. Formatele de afișare oferă instucțiuni despre
modul cum se vor afișa datele din setul de date.
▪ Ambele tipuri de formate pot fi predefinite în SAS sau definite
de utilizator.
▪ Atunci când se creează un format definit de utilizator, acesta nu
este asociat unei anumite variabile sau set de date, ci bazându-
ne pe valorile pe care vrem să le afișăm diferit.
▪ Formatele vor fi disponibile pe parcursul unei sesiuni SAS, cu
excepția cazului în care se crează formate persistente.
▪ După definire, formatele se aplică variabilelor în diferite
proceduri SAS.
42
Sintaxa formate SAS de afișare
❖ Definirea de formate
PROC FORMAT;
VALUE <$>nume_format listă_valori_iniţiale1 = val_afis1
<_same_>
listă_valori_iniţiale2 = val_afis2
other = val_afis3;
– Valorile din listă se separă prin virgulă şi, pentru cele de tip
caracter, se includ între ghilimele.
– Se pot defini mai multe formate de afişare în aceeaşi procedură.
❖ Utilizarea formatului în alte proceduri

FORMAT variabila <$> nume_format. ;


❖ Formate persistente
libname formate '/home/nume.prenume';
options fmtsearch=(formate);
proc format library = formate;
43
Formate SAS de afișare
❖ Valori - valori singulare, precum 2 sau ‘CJ’. Pentru valorile de
tip caracter, acestea sunt incluse între ghilimele simple

❖ Domenii

❖o listă de valori (de exemplu, 10–45 sau ‘A’-’Z’). Pentru


intervalele cu șiruri de caractere, trebuie să includeți fiecare șir
între ghilimele simple.

❖Dacă specificați ‘A-Z’, atunci procedura îl interpretează ca un șir


de trei caractere cu A ca prim caracter, o cratimă (-) ca al doilea
caracter și un Z ca al treilea caracter.

❖Pentru intervalele cu valori numerice, se pot utiliza LOW sau


HIGH , LOW include cea mai mică valoare numerică, excluzând
valorile lipsă. HIGH include cea mai mare valoare din interval.
Se poate utiliza intervalul LOW-HIGH pentru a cuprinde toate
valorile. Exemple de intervale valide: low- 40, 35-high, low-high

44
Formate SAS de afișare
❖ Domenii

❖Puteți utiliza simbolul mai mic decât (<) pentru a exclude valori
din intervale. Dacă excludeți prima valoare dintr-un interval,
atunci puneți operatorul de excludere < după valoare. Dacă
excludeți ultima valoare dintr-un interval, puneți operatorul de
excludere < înaintea valorii.:

❖0<-100 (intervalul nu include 0)

❖0-<100 (intervalul nu include 100)

❖Dacă se suprapun valori în intervale, atunci PROC FORMAT


returnează un mesaj de eroare, cu excepția cazului în care,
pentru declarația VALUE, este specificată opțiunea MULTILABEL.
De exemplu, următoarele intervale vor provoca o eroare: 'AA'-
'AK’=1 'AJ'-'AZ'=2.

45
Utilizare formate SAS de afișare
***Definire formate definite de utilizator;
PROC FORMAT;
VALUE $oras 'BU'='Bucuresti'
'BZ'='Buzau'
'CJ'= 'Cluj'
other='Gresit';

VALUE nivel low-<100000='Nivel1'


100000-200000='Nivel2'
200000<-high='Nivel3';
RUN;

***Aplicare formate definite de utilizator;


PROC PRINT DATA =agenti LABEL;
FORMAT oras $oras. Vanzari nivel.;
RUN;

46
U T I L I Z A R E F O R M AT E S A S D E
AFIȘARE
47
Declarația INPUT - Omiterea locației unei
coloane
Pentru a putea omite locația unei coloane dintr-un fișier flat, la
citirea datelor în vederea creării unui set de date SAS, datele
trebuie să satisfacă următoarele condiții:
• Fiecare valoare este separată de următoarea prin cel puțin un
spațiu liber sau un delimitator (dacă folosim opțiunea DLM).
• Orice valoare lipsă este reprezentată prin spații (pentru
ambele tipuri de variabile).
• Valorile tuturor variabilelor de tip caracter au maxim 8
caractere și nu includ spații, în caz contrar se produc
trunchieri ale datelor.
Observație! În seturile de date SAS valorile lipsă sunt
reprezentate prin punct pentru variabilele numerice și spațiu
pentru cele de tip caracter. 48
Declarația INPUT - Plasarea mai multor
observații scurte pe aceeași linie
Pentru fișierele cu puține variabile și observații scurte, este o
practică des întâlnită plasarea mai multor observații pe
aceeași linie. Pentru a folosi această abordare, trebuie avute în
vedere următoarele aspecte:
• Datele de intrare trebuie să îndeplinească cele trei condiții
amintite în slide-ul anterior.
• Se pot pot pune numere diferite de observații pe linii
diferite.
• Se poate folosi declarația INPUT fără a preciza locația
coloanei plasând la sfârșitul declarației simbolurile “@@”
înainte de “;”.

49
Plasarea mai multor observații scurte pe
aceeași linie - exemplu
*Plasarea mai multor observatii pe aceeasi linie;
DATA studenti;
INPUT cod nota @@;
DATALINES;
1101 7 1102 9 1103 10 1104 7 1105 5 1106 8 1107 6 1108 10
1109 9 1110 7 1111 8 1112 5 1113 9 1114 10 1115 8 1116 7
;
RUN;

50
De lucru!
❖Dorim să importăm datele din fișierul exemplu5.txt:
brad 40 conifere
molid 25 conifere
fag 42 foiaose
stejar 27 foiaose
liliac 33 arbusti
alun 38 arbusti
cires 39 fructifere
mar 25 fructifere

❖Rulăm codul:
LIBNAME date "/home/nume.prenume";
data date.exemplu5;
infile '/home/nume.prenume/exemplu5.txt';
input Nume $ Pret Categorie $; 51
run;
De lucru!
❖Ce observați în rezultate?
❖Care credeți că este cauza?
❖O soluție o reprezintă stabilirea lățimii unei variabile prin
declarația LENGTH, având următoarea sintaxă:
LENGTH variabil_1 ... variabila_n <$> latime
Semnul $ indică faptul că variabilele dinaintea lui sunt de tip
caracter.
❖Rulăm din nou codul:
data date.exemplu5;
infile '/home/nume.prenume/exemplu5.txt';
length Categorie $ 10;
input Nume $ Pret Categorie $;
run;
52
De lucru!

53
1. Care variantă produce un set de date de ieșire corect?
*1;
data iesire;
INPUT var1 var2$ @@;
DATALINES;
01 aaaaaaaaa 02 bbbbbbbbb 03 ccccccccc
;
*2;
data iesire;
INPUT var1 var2$ @@;
DATALINES;
01 aaaaaaaa 02 bbbbbbbb 03 cccccccc
;
*3;
data iesire;
INPUT var1 var2 @@;
DATALINES;
01 aaaaaaaa 02 bbbbbbbb 03 cccccccc
54
;
2. Dacă nu specificați opțiunea LIBRARY = în cadrul instrucțiunii PROC
FORMAT, formatele se for salva în biblioteca Work.Formats și vor exista:
a) Doar în procedura curentă
b) Doar in secțiunea de date curentă
c) Doar în sesiunea SAS curentă
d) Permanent

3. Identificați enunțul fals din cele de mai jos.


Declarația VALUES din procedura FORMAT poate specifica:
a) O singură valoare, cum ar fi 24 sau ‘R’
b) Un domeniu de valori, cum ar fi 0-1500
c) Un domeniu de valori caracter, cum ar fi ‘A’-’Z’
d) O listă de valori numerice și caracter, separate prin virgulă, cum ar fi:
90, ‘B’, 348, ‘D’, 134

55
4. Formatul pozitie a fost create cu procedura FORMAT. Identificați
varianta corectă de aplicare a formatului asupra variabilei pozitie:
a) format pozitie pozitie;
b) format pozitie pozitie.;
c) format pozitie=pozitie;
d) format pozitie=‘pozitie’;

5. Ce modalitate de citire a datelor trebuie folosită pentru setul de date


următor?

56
6. Formatele de afișare în SAS:
a) Se aplică pe fișiere de tip text
b) Afectează datele din tabele
c) Afectează modul de afișare a datelor
d) Se folosesc în secțiunile de date
e) Se folosesc în secțiunile de proceduri

7. În codul SAS se mai jos:


PROC PRINT DATA = date LABEL;
FORMAT tara $tara. venit venit.;
RUN;

a) Sunt definite două formate de afișare de tip caracter


b) Sunt definite un format de afișare de tip caracter și un format de
afișare de tip numeric
c) Sunt folosite două formate de afișare de tip caracter
d) Sunt folosite un format de afișare de tip caracter și un format de
afișare de tip numeric
e) Se vor afișa etichete corespunzătoare variabilelor
57
Programarea în
limbajul SAS

PA R T E A A I I - A
CUPRINS Curs

➢ Crearea și gestiunea variabilelor


➢ Subseturi de date
➢ Procesarea condițională și iterativă a datelor
➢ Transformarea datelor prin funcții SAS
Crearea seturilor de date SAS din seturi de
date existente -1

Sintaxa generală:

DATA set-de-date-SAS-de-iesire;
SET set-de-date-SAS-de-intrare;
WHERE expresie-conditionala;
DROP listă-variabile;
KEEP listă-variabile;
LABEL var1=‘eticheta1’ var2=‘eticheta2’;
FORMAT variabila(le) format.;
RUN;

3
Crearea seturilor de date SAS din
seturi de date existente -2
◼ Implicit toate întregistrările dintr-un set de date de intrare
sunt scrise în setul de date rezultat.
◼ Declaraţia WHERE are rolul de a extrage observaţiile dintr-
un set de date.
◼ O secţiune de date poate include o singură declaraţie
WHERE.

Exemple:
where gen eq ‘M’;
where salariu ne .;
where pozitie contain ‘Vanzari’;
where nume like ‘T_M%’;
where cod is missing;
4
Crearea seturilor de date SAS din
seturi de date existente -3
◼ Extragerea (selectarea) variabilelor din setul rezultat se
realizează cu ajutorul declaraţiilor DROP şi KEEP:
◼ DROP listă-variabile; {cu spaţiu între ele} arată care
sunt variabilele care se exclud din setul rezultat.
◼ KEEP listă-variabile; {cu spaţiu între ele} arată care
sunt variabilele care se păstrează în setul rezultat.
◼ Declaraţia LABEL are rolul de a adăuga o etichetă la zona
de descriere a unui set de date. Eticheta schimbă modul în
care apare numele variabilei în diverse proceduri. Spre
exemplu, PROC PRINT poate afişa numele etichetei în loc
de numele variabilei:
PROC PRINT DATA = set-de-date-SAS LABEL;
◼ FORMAT este un format de afişare care schimbă modul de
afişare a variabilelor: <$>format <w>.<d> 5
Procesare condiţională în programele SAS

• Procesarea condiţională reprezintă capacitatea programelor


SAS de a lua decizii în funcţie de valorile datelor.
• Principala construcţie pentru procesarea condiţională este
declaraţia IF, împreună cu versiunea ei ELSE IF.
• Forma generală a acestei declarații este:
IF expresie THEN declarație;
ELSE declarație;
• Versiunea ELSE IF:
IF expresie1 THEN declarație1;
ELSE IF expresie2 THEN declarație2;
ELSE IF expresie3 THEN declarație3;
......
6
Operatorii logici și de comparaţie din SAS
Operator Mnemonic echivalent Operație
& AND ȘI
| OR SAU
^ NOT Negație
= EQ Equal to
^= NE Not equal to
> GT Greater than
< LT Less then
>= GE Greater than or equal to
<= LE Less than or equal to
IN IN Equal to one in a list

Atenție!!! La evaluarea expresiilor folosind operatori logici trebuie să


aveți în vedere că în SAS orice valoare numerică alta decât 0 sau
valoarea lipsă este adevărată, iar valorile 0 și lipsă sunt false. 7
Exemplu
Considerăm pentru exemplificare setul de date creat prin următorul cod
SAS:
DATA produse;
LENGTH Categorie $9;
INFILE'/home/nume.prenume/produse.txt';
INPUT Cod Pret_achizitie Pret_vanzare Categorie $;
RUN;
PROC PRINT DATA=produse;
VAR Cod Pret_achizitie Pret_vanzare Categorie;
Rezultatul rulării codului

8
Exemplu - creare de noi variabile
Pornind de la setul de date din exemplu, se definesc două noi variabile:
◼ Variabila Profit_unitar prin calcule

◼ Variabila Grup prin procesare condițională

LIBNAME exemple '/home/nume.prenume/';


DATA exemple.produse;
SET produse;
Profit_unitar=Pret_vanzare-Pret_achizitie;
if missing(Pret_vanzare) or Pret_vanzare lt 10
then Grup=1;
else if Pret_vanzare le 20 then Grup=2;
else Grup=3;
DROP Pret_achizitie;
RUN;

9
Exemplu - creare de noi variabile

10
Subseturi de date
• Într-o secțiune de date, observațiile pot fi regrupate într-un subset de date
SAS folosind declarațiile WHERE, DELETE sau instrucțiunea IF.
• Declarația DELETE oprește procesarea observației curente.
• Pentru a procesa condițional declarația DELETE, se folosește următoare
sintaxă:
IF expresie THEN DELETE;
• Exemplu de crearea a unui subset de date pentru categoria de produse
“perisabile”:
data perisabile;
set exemple.produse;
where Categorie IN ("legume", "fructe", “brutarie");
• Daca am dori un subset de date pentru grupul 1, condiția ar fi: where Grup
eq 1;
• În secțiunile de proceduri se folosește numai instrucțiunea WHERE, nu și
IF, iar expresiile condiționale ale lui WHERE în secțiunea de date trebuie
să refere numai variabile din setul de date de intrare.
• WHERE nu se poate folosi în expresii condiționale bazate pe variabile
11
create în secțiunea de date prin declarații de atribuire.
Subseturi de date - exemplu
Declarația DELETE este folosită pentru a controla care observații să nu fie
incluse în subsetul de date.
Se dorește crearea unui subset de date care să conțină toate produsele
neperisabile:
Varianta 1: IF cu DELETE
data neperisabile;
set exemple.produse;
if Categorie NOT IN ("cosmetice", "curatenie") then
delete;
run;
Varianta 2: WHERE
data neperisabile;
set exemple.produse;
WHERE Categorie IN ("cosmetice", "curatenie");
run;
Varianta 3: IF fără THEN
data neperisabile;
set exemple.produse;
if Categorie IN ("cosmetice", "curatenie"); 12
run;
Acumularea de totaluri-1
▪ De multe ori este utilă crearea unei variabile care acumulează
valorile altor variabile.
▪ Pentru a adăuga rezultatul unei expresii la o variabilă acumulator se
poate folosi declarația de adunare în secțiunea de date, cu sintaxa:
variabila + expresie;
▪ variabilă = numele variabilei acumulator, care trebuie să fie
numerică. Variabila este inițializată automat cu 0 înainte de
citirea primei observații. Valoarea variabilei este păstrată între
două execuții ale secțiunii de date.
▪ expresie = orice expresie SAS validă.
▪ Declarația de adunare adaugă rezultatul expresiei din drepta
semnului plus (+) la variabila numerică din stânga semnului plus.

13
Acumularea de totaluri-2
Pornim de la datele care memorează informațiile referitoare la un test
medical de efort efectuat de pacienți pe o bandă de alergare.

data efort;
input Cod $ 1-4 Nume $ 6-19 RCRep 23-24 RCMax 29-31
RCRec 35-37 TimpMin 43-44 TimpSec 51-52
Toleranta $ 58;
datalines;
2458 Murray, W 72 185 128 12 38 D
2462 Almers, C 68 171 133 10 5 I
……
run;
Lista parțială a rezultatelor

14
Acumularea de totaluri-3
▪ Dorim să aflăm care este timpul total, măsurat în secunde, în care s-
a folosit banda de alergare după efectuarea exercițiilor de către
fiecare pacient.

data efort1;
set efort;
TimpTotal = (TimpMin*60)+TimpSec;
SumSec + TimpTotal;

run;
Atenție!!! Dacă expresia de evaluat produce o valoare lipsă, declarația
de adunare o ignoră. Prin comparație, declarația de atribuire atribuie o
valoare lipsă dacă expresia produce o valoare lipsă.
Operație Expresie Rezultat
variabila+expresie; NULL Valoarea variabilei
variabila=variabila+expresie; NULL NULL
SUM(variabila, expresie); NULL Valoarea variabilei 15
Acumularea de totaluri-4
data efort1;
set efort;
TimpTotal = (TimpMin*60)+TimpSec;
SumSec + TimpTotal;

run;

16
KEEP și DROP – opțiuni vs. declarații
▪ Atât KEEP cât și DROP pot apărea sub forma unor opțiuni ale setului
de date sau ca declarații în secțiunea de date.
DATA set_date (DROP = variabil(e) | KEEP = variabil(e));
……
DROP variabil(e);
KEEP variabil(e);
RUN;
▪ În principiu, ambele variante au același scop (păstrarea sau
eliminarea variabilelor), diferențele dintre cele două fiind:
✓ Nu se pot folosi declarațiile KEEP și DROP în secțiunile de
proceduri;
✓ Declarațiile KEEP și DROP se aplică tuturor seturilor de date
care sunt denumite în declarația DATA. Pentru a exclude
variabile dintr-un set, dar nu și din altele, se folosesc opțiunile
DROP= și KEEP=.
17
KEEP și DROP cu două seturi de date

DATA perisabile (DROP = Pret_achizitie) neperisabile;


SET produse;
Profit_unitar=Pret_vanzare-Pret_achizitie;
if Categorie NOT IN ("cosmetice", "curatenie") then
output perisabile;
else output neperisabile;
RUN;

18
De lucru - Analizați exemplul!
▪ Exemplu utilizare opțiunea DROP cu un set de date
data efort2 (drop = TimpMin TimpSec);
set efort;
if Toleranta ="D";
TimpTotal = (TimpMin*60)+TimpSec;
SumSec + TimpTotal;
length DurataTest $ 6.;
if TimpTotal >800 then DurataTest = "Lung";
else if 750<=TimpTotal<=800 then DurataTest =
"Normal";
else if TimpTotal<750 then DurataTest = "Scurt";
run;

19
Stabilirea lățimii unei variabile noi
▪ În timpul compilării, atunci când se creează o nouă variabilă de tip
caracter în urma unei declarații de atribuire, SAS alocă atâția octeți
ca spațiu de stocare câte caractere are prima valoare pe care o
întâlnește pentru acea variabilă.

Întrebare
Câți octeți credeți că rezervă programul anterior pentru variabila
DurataTest în absența declarației LENGTH?
▪ În cadrul programului, s-a inclus declarația LENGTH pentru a
asigna variabilei o lățime suficientă pentru a stoca cea mai lungă
valoare pentru variabila DurataTest, și anume șase caractere.
Aplicăm!
Rulăm programul anterior comentând declarația LENGTH.

20
Procesarea condițională cu SELECT
▪ O altă modalitate de a realiza procesare condițională în SAS o
reprezintă folosirea declarației SELECT, cu sintaxa:
SELECT <(expresie-select)>;
WHEN (expresie-conditionala-1 <…, expresie-conditionala-n>) declaratie;
WHEN (expresie-conditionala-1 <…, expresie-conditionala-n>) declaratie;
<OTHERWISE declaratie;>
END;
unde
▪ SELECT specifică începutul unui grup de selecție.
▪ expresie-select este opțională și reprezintă orice expresie a cărei
evaluare produce o singură valoare.
▪ WHEN identifică o declarație care se execută atunci când o anumită
condiție este adevărată.
▪ expresie-condițională specifică orice expresie SAS, inclusiv o
expresie compusă.
▪ Opțiunea OTHERWISE arată ce declarație se execută dacă nu este
îndeplinită niciuna dintre condițiile specificate cu WHEN.
▪ END semnifică sfârșitul grupului de selecție. 21
SELECT cu expresie de selectare
▪ SELECT fără crearea unui set de date:
DATA _NULL_; *nu se creaza un set de date;
a=7; x=2;
SELECT (a);
WHEN (2,4,6,8) x=x*10;
WHEN (1,3,5,7) x=x*100;
OTHERWISE;
END;
put x= ; RUN;
▪ SELECT cu crerea unui set de date:
DATA salariati;
SET exemple.salarii; length grup $ 20;
SELECT(Pozitie);
WHEN ("FA1") grup ="Flight Attendant I";
WHEN ("FA2") grup ="Flight Attendant II";
WHEN ("FA3") grup ="Flight Attendant III";
WHEN ("ME1", "ME2", "ME3") grup ="Mechanic";
WHEN ("NA1", "NA2", "NA3") grup ="Navigator";
WHEN ("PT1") grup ="Pilot I";
WHEN ("PT2") grup ="Pilot II";
WHEN ("PT3") grup ="Pilot III";
WHEN ("TA1", "TA2", "TA3") grup ="Ticket Agents";
OTHERWISE grup="Other";
END; 22
SELECT fără expresie de selectare
DATA produse_procent_profit;
SET produse;luna=MONTH(TODAY());
SELECT;
WHEN (Categorie="fructe" and luna in (10,11,12))
Procent_profit=0.4;
WHEN (Categorie="fructe" and luna in (1,2,3,4))
Procent_profit=0.6;
WHEN (Categorie="fructe") Procent_profit=0.3;
OTHERWISE;
END;
IF Categorie="fructe" THEN
Pret_vanzare=Pret_achizitie*(1+Procent_profit);
RUN;

Numai prima declarație


WHEN care are expresia
adevărată va fi folosită,
celelalte nu sunt
evaluate.

23
Gruparea declarațiilor – grupurile DO
▪ Exemplele de până acum au folosit procesarea condițională în care
se execută o singură declarație SAS atunci când o condiție este
evaluată ca fiind adevărată. Se pot executa însă și grupuri de
declarații folosind construcția DO cu sintaxa:
DO;
declaratii SAS
END;
▪ Este permisă imbricarea declarațiilor DO în cadrul grupurilor DO, sub
forma:
DO;
declaratii;
DO;
declaratii;
DO;
declaratii;
END;
END;
24
END;
Grupurile DO - exemplu
DATA produse_reduceri;
SET produse;
SELECT(Categorie);
WHEN ("legume", "fructe", "brutarie")
DO;
Reducere=0.25;
IF Pret_vanzare le 10 THEN reducere=0.2;
END;
WHEN ("cosmetice") Reducere=0.3;
OTHERWISE;
END;
IF not missing (Reducere) THEN Pret_nou=Pret_vanzare
*(1-Reducere);
ELSE Pret_nou=Pret_vanzare;
RUN;

Atenție!! Valorile datelor de tip caracter care apar în expresii


sunt case sensitive.

25
Grupurile DO - exemplu

26
Procesarea iterativă în programele SAS-1
Procesarea iterativă permite procesarea unui grup de declarații în mod
repetat, reducând semificativ codul necesar efectuării de calcule
repetitive. Pentru buclele repetitive se poate cunoaște sau nu numărul
de iterații
1. Bucla cu număr cunoscut de iterații
DO contor= inceput TO sfarsit BY incrementare;
declaratii SAS;
END;
unde valorile inceput, sfarsit și incrementare:
• sunt setate la începutul intrării în buclă
• nu pot fi schimbate pe parcursul procesării buclei
• pot fi numere, variabile sau expresii SAS
▪ Dacă valoarea de incrementare este omisă, atunci aceasta implicit
este 1.
▪ Atunci când valoarea de incrementare este un număr negativ,
contorul va realiza o actualizare descrescătoare.
▪ Valorea variabilei contor poate fi schimbată în interiorul buclei.
27
Procesarea iterativă în programele SAS-2
2. Bucla condițională, cu număr necunoscut de iterații
▪ Există două variante prin declarațiile DO UNTIL și DO WHILE.
DO UNTIL (expresie); DO WHILE (expresie);
declaratii SAS; declaratii SAS;
END; END;
▪ DO UNTIL execută bucla până când expresie devine adevărată.
Expresia nu se evaluează până la finalul buclei, ceea ce însemnă că
aceasta întotdeuna se execută cel puțin o dată.
▪ DO WHILE evaluează expresie înainte de intrarea în buclă, cu
posibilitatea ca aceasta să nu se execute niciodată.
▪ Exemplu de combinare a celor două variante de procesare iterativă:
DATA investitie;
DO an=1 to 10 UNTIL (Capital>=50000);
Capital +4000;
Capital+Capital*.10;
END;
RUN;
28
Funcții SAS
▪ Funcțiile SAS sunt rutine predefinite care permit efectuarea unei
multitudini de operații de manipulare a datelor rapid și cu ușurință.
▪ Există multe categorii de funcții SAS, cu ar fi: aritmetice, financiare,
de tip caracter, pentru calculul probabilităților, de tip dată și timp etc.
▪ Argumentele unei funcții pot fi variabile, constante sau expresii.
▪ Există funcții care pot folosi ca argumente și liste de variabile sau
masive (pe lângă numele argumentelor separate prin virgulă), caz în
care argumentele sunt precedate de cuvântul OF:
▪ mean (x1,x2,x3) este echivalentă cu mean(of x1-x3)

Care va fi rezultatul afișat de codul de mai jos

DATA _NULL_;
x1=1; x2=4; x3=10;
medie= mean(x1-x3);
put medie= ;
RUN;
29
PUT și INPUT -1
▪ Există situații în care datele de care dispunem nu sunt în formatul
necesar efectuării transformărilor sau calculelor de care avem
nevoie. Spre exemplu, avem de efectuat o operație matematică între
o variabilă de tip caracter și una de tip numeric.
▪ Chiar dacă SAS va detecta nepotrivirea dintre tipurile variabilelor și
va realiza o conversie automată caracter-numeric sau numeric-
caracter, este întotdeuna o bună practică să se realizeze o conversie
explicită folosind funcțiile INPUT sau PUT.
▪ Funcția INPUT convertește valorile de tip caracter la valori numerice:
INPUT (sursa, informat);
unde
▪ sursa reprezintă orice variabilă de tip caracter, constantă sau
expresie care va fi convertită la o valoare numerică.
▪ informat este un format de citire potrivit pentru formatul datelor
respective.
30
PUT și INPUT -2
▪ Funcția PUT convertește valorile de tip numeric la valori de tip
caracter:
PUT (sursa, format);
unde
▪ sursa reprezintă orice variabilă de tip numeric, constantă sau
expresie care va fi convertită la o valoare de tip caracter.
▪ format este un format de afișare potrivit pentru datele care se citesc,
deci în acest caz un format numeric.
▪ Funcția returnează întotdeauna un șir de caractere.
▪ Exemplu utilizare funcția INPUT:
DATA _NULL_;
c_data= "2/24/2019";
c_num= "1234";
Data_SAS= INPUT(c_data,mmddyy10.);
Numar = INPUT(c_num,10.);
PUT Data_SAS= Numar=;
RUN;
31
Exemple funcția PUT
DATA _NULL_;
Data_SAS= 1;
Numar = 1234;
SS_numar= 123456789;*/Social Security number;
Data_car= PUT(Data_SAS,mmddyy10.);
Moneda = PUT(Numar,dollar8.2);
SS_car= PUT(SS_numar,ssn.);
PUT Data_car= Moneda= SS_car=;
RUN;
------------------------------------------------------

PROC FORMAT;
VALUE grup 0-10='0 la 10'
11-20='11 la 20'
21-40='21 la 40'
41-high='41+';
RUN;
DATA Exemplu_PUT;
INPUT Varsta @@;
GrupVarsta= PUT(Varsta,grup.);
DATALINES;
9 15 25 60 32
; RUN;
LENGTH, LENGTHN, LENGTHC
▪ Funcțiile LENGTH și LENGTHN returnează lățimea unui șir de
caractere, fără a lua în considerare eventualele spații de la sfârșitul
șirului:
LENGHTN (valoare_caracter);
▪ Dacă valoare_caracter este o valoare lipsă, atunci funcția LENGTHN
returnează 0, iar versiunea acesteia mai veche, LENGTH, va returna
1 în acest caz.

DATA _NULL_;
String = ' ';
Latime1=LENGTH(String);
Latime2=LENGTHN(String);
put "Latime cu LENGHT: " Latime1 = ;
put "Latime cu LENGHTN: " Latime2 = ;
Cuvant1 = "abc ";
Latime=LENGTHN(Cuvant1);
Put Cuvant1= Latime = ;
Cuvant2 = "a b c";
Latime=LENGTHN(Cuvant2);
Put Cuvant2= Latime = ;RUN;
33
LENGTHN, LENGTHC - exemple
Funcția LENGTC returnează numărul de octeți pe care este stocat intern
un șir de caractere.

DATA caractere1;
LENGTH String $ 7;
String = 'curs';
Stocare= LENGTHC(String);
Latime = LENGTHN(String);
Afisare = ":" || String || ":";
PUT Stocare= /
Latime= /
Afisare=;
RUN;

34
MISSING și CALL MISSING
▪ Funcția MISSING preia o valoare numerică sau de tip caracter și
returnează “adevărat” dacă valoarea este lipsă și “fals” în caz contrar.
▪ CALL MISSING reprezintă o rutină care setează toate argumentele
sale (numerice sau de tip caracter) cu valoarea nulă.
▪ Verificare valoare lipsă:
*Fără MISSING;
IF Numar = . then . . .
IF Sir = '' then . . .
*Cu MISSING;
IF missing(Numar) then . . .
IF missing(Sir) then . . .
-------------------------------------------------------
DATA _NULL_;
array a[10]a1-a10;
array car[3] x y z;
do i= 1 to 10;
a[i] = .;
end;
do i= 1 to 3; call missing(of a1-a10,x,y,z);
car[i] = ' ';
end;
drop i; 35
RUN;
SUBSTR
▪ Funcția SUBSTR returnează un subșir de caractere din sir, pornind
de la poziția specificată în start și cu o lățime menționată în ultimul
argument al funcției. Atunci când latime nu este specificată, subșirul
se termină la ultimul caracter nenul din sir.
SUBSTR (sir , start, latime);
▪ În situația în care nu se stabilește anterior, lățimea variabilei
rezultate va fi aceeași cu lățimea șirului parametru.
data parti_cod;
input Cod $9.;
length Judet $ 2;
Judet = substr(Cod,3,2);
Numar= input(substr(Cod,5),4.);
datalines;
YXVL765
YXIF8765
;
-------------------------------------------------------
data ascundere_cont;
input ID Cont $9. @@;
Cont2 = Cont; substr(Cont2,1,5) = '*****';
datalines;
101 987037051 102 085701417 103 680865368 36
UPCASE LOWCASE și PROPCASE
▪ Cele trei funcții lucrează cu șiruri de caractere și sunt responsabile
de transformările în caractere mari, mici și respectiv cele specifice
unui titlu.
DATA litere;
INPUT Nume $15.;
Mari = UPCASE(Nume);
Mici = LOWCASE(Nume);
Potrivit = PROPCASE(Nume," '");
DATALINES;
poPEscU IOANA
D'Angelo
;
TRIM și STRIP
▪ Funcția TRIM returnează un șir de caractere din care s-au îndepărtat
spațiile de la sfârșitul șirului.
▪ Funcția STRIP returnează un șir de caractere din care s-au
îndepărtat spațiile de la începutul și sfârșitul șirului.
▪ Pentru ambele funcții, dacă argumentul conține valoarea lipsă,
atunci lățimea rezultatului este egală cu 0.
37
▪ Se folosesc frecvent împreună cu operatorul de concatenare.
CATS, TRIM și STRIP - exemplu
▪ Funcția CATS preia mai multe argumente de tip șir de caractere,
îndepărtează spațiile de la începutul și sfârșitul șirulor și
concatenează rezultatele.

DATA _NULL_;
length Concatenare$ 8;
Unu = ' ABC ';
Doi = 'XYZ';
Unu_doi= ':' || Unu || Doi || ':';
Trim = ':' || trimn(Unu) || Doi || ':';
Strip = ':' || strip(Unu) || strip(Doi) ||
':';
Concatenare= cats(':',Unu,Doi,':');
put Unu_Doi= / Trim= / Strip= /
Concatenare=;
RUN;

38
N, NMISS, SUM și MEAN
▪ N(lista_valori) returnează numărul de valori nenule din listă.
▪ NMISS(lista_valori) returnează numărul de valori nule din listă.
▪ SUM(lista_valori) returnează suma valorilor, ignorând valorile lipsă.
▪ MEAN(lista_valori) returnează media valorilor, ignorând valorile
lipsă.

DATA descriptive;
INPUT a1-a10;
Suma = sum(of a1-a10);
if n(of a1-a10) ge 3 then
Media1 = mean(of a1-a5);
if nmiss(of a1-a10) le 5 then
Media2 = mean(of a1-a10);
DATALINES;
1 2 . . 3 4 5 . 6 7
. . . 8 . . 9 . . 10
;

39
Funcții de tip dată
▪ MDY(Luna, Zi, An) – returnează o dată SAS.
▪ Weekday(Data) – returneaza ziua din saptămână (1-duminică, 2-luni
etc.)
▪ Day(Data) – returnează ziua din lună (1-31)
▪ Year(Data) – returnează anul
▪ Yrdif(Data1,Data2) – retunează numărul de ani dintre Data1 și
Data2
DATA Functii_Data;
INPUT (Data1 Data2)(:mmddyy10.) M D Y;
Data_SAS= MDY(M,D,Y);
ZiSaptamana= weekday(Data1);
ZiLuna= day(Data1);
An = year(Data1);
Varsta = yrdif(Data1,Data2);
FORMAT Data_SAS mmddyy10.;
datalines;
02/24/1992 02/24/2019 7 28 2018
;

40
Sintaxă recapitulativă
LIBNAME libref ‘Biblioteca-SAS‘;
DATA set_date (DROP = variabil(e) | KEEP = variabil(e));
SET Set_date;/ INFILE ...; INPUT ...;
DROP variabil(e);
KEEP variabil(e);
LENGTH variabil_1 ... variabila_n <$> latime;
IF expresie THEN declarație;
ELSE declarație;
IF expresie THEN DELETE;
LABEL variabila1 = “Eticheta1”….. ;
FORMAT variabila <$> nume_format. ;
SELECT <(expresie-select)>;
WHEN (expresie-conditionala-1 <…, expresie-conditionala-n>) declaratie;
WHEN (expresie-conditionala-1 <…, expresie-conditionala-n>) declaratie;
<OTHERWISE declaratie;>
END;
RUN; 41
Să recapitulăm!
1. Câte declarații WHERE poate include o secțiune de
date SAS?
2. Ce valori sunt considerate false la evaluarea
operatorilor logici?
3. Procesarea condițională cu IF se poate folosi în
secțiunile de proceduri?
4. Ce efect are declarația variabila+expresie; ?
5. În declarația PUT(Numar,dollar8.2); ce tip de format
se aplică parametrului numar și de ce?
6. Explicați declarația SELECT fără expresie de selectare!
7. De ce este recomandată folosirea declarației LENGTH
în cazul variabilelor noi definite prin atribuire? 42
Programarea în
limbajul SAS

PA RT EA A I I I - A
CUPRINS Curs

Combinarea seturilor de date


➢ Proceduri SAS
➢ Proceduri SQL
➢ Comparație între cele două abordări
Combinarea seturilor de date
Abordarea SAS
▪ În programarea SAS, una dintre prelucrările comune constă în
combinarea observațiilor din două sau mai multe seturi de date într-
un set de date nou.
▪ SAS oferă următoarele metode de combinare a seturilor de date:

Metodă Modalitate de realizare


Concatenare instrucțiunea SET
Adăugare procedura APPEND
Interclasare instrucțiunea SET
Fuziune pe baza unei corespondențe procedura MERGE

3
Concatenare -1
▪ O modalitate de a combina seturi de date SAS folosind instrucțiunea
SET o reprezintă concatenarea, prin care se adaugă obsevații dintr-
un set de date în altul.
▪ Pentru aceasta, într-o singură instrucțiune SET, se va specifica o
listă de seturi de date de intrare.
▪ Sintaxa generală este:
DATA set-date-iesire;
SET set-date-1 set-date-2;
RUN;
▪ Atunci când se concatenează seturi de date, vor fi citite toate
observațiile din fiecare set de date listat în instrucțiunea SET.
▪ Noul set de date va conține toate variabilele și observațiile din toate
seturile de date de intrare.

4
Concatenare -2
Set de date A Set de date B
NR VarA NR VarB

1 A1 1 B1

2 A2 2 B2

3 A3 4 B3

Concatenare

Setul de date combinat


NR VarA VarB

1 A1

2 A2

3 A3

1 B1

2 B2

4 B3
Concatenare: exemplu -1
DATA pret1;
INPUT COD pret; • Observăm că seturile de date au o
DATALINES; variabilă comună numită COD.
124 23.5 Ambele variabile COD trebuie să fie
178 35.0 de acelasi tip, altfel SAS intrerupe
197 44.6
procesarea secțiunii de date și va
;RUN;
DATA pret2; afișa un mesaj de eroare: variabila
INPUT COD $ pret; COD are două tipuri de date.
DATALINES;
234 53.7
356 75.5
367 84.0
;RUN;
DATA concatenare;
SET pret1 pret2;
RUN;

6
Concatenare: exemplu -2
DATA nume1;
INPUT ID$ nume$;
DATALINES;
0123 Mihai • Dacă lățimea variabilelor diferă,
0134 Delia SAS preia lățimea primului set de
0162 Ionela date din listă. Același lucru este
; RUN;
valabil și pentru atributele
DATA nume2;
LENGTH nume $ 10.; etichetă, format și informat.
INPUT ID$ nume$;
DATALINES;
0124 Alexandra
0138 Georgiana
0189 Sebastian
; RUN;
DATA concatenare;
SET nume1 nume2;
RUN;

7
Adăugare -1
▪ Adăugarea este similară concatenării, în cazul aceasta folosindu-se
procedura APPEND.
▪ Există câteva diferențe importante între concatenare și adăugare:
✓ În timp ce secțiunea de date definește un set de date nou la
concatenare, procedura APPEND doar adaugă observațiile unui
set de date la sfârșitul unui set de date de bază (master data
set).
✓ SAS nu citește datele din setul de date de bază atunci când
execută procedura APPEND.
▪ Sintaxa generală este:
PROC APPEND BASE= set-date
DATA= set-date;
RUN;
▪ Numai două seturi de date pot fi folosite în cadrul procedurii
APPEND.

8
Adăugare -2
▪ Pentru a folosi procedura APPEND cu seturi de date care au
structuri diferite, se utilizează opțiunea FORCE a procedurii, cu
sintaxa:
PROC APPEND BASE= set-date
DATA= set-date FORCE;
RUN;
▪ Această opțiune este necesară atunci când setul de date care
trebuie adăugat conține variabile care:
✓ nu sunt în setul de date de bază;
✓ au alt tip decât cele din setul de date de bază;
✓ sunt mai late decât cele din setul de date de bază.
▪ SAS raportează diferitele caracteristici ale variabilelor la setul de
date de bază, nu la cel adăugat, astfel încât valorile și variabilele din
setul de date din instrucțiunea DATA sunt cele care vor suferi
modificări.

9
Adăugare -exemplu

DATA persoane1;
*LENGTH GEN $1;
INPUT cod Gen $;
DATALINES;
1 M
2 F
3 M
;
RUN;
DATA persoane2;
INPUT cod Gen $ Judet $;
DATALINES;
4 Masculin IL
5 Feminin DB
6 Masculin VL
7 Feminin CJ
;
RUN;
PROC APPEND BASE=persoane1
DATA= persoane2; *FORCE;
RUN;
PROC PRINT DATA =persoane1 NOOBS; 10
VAR Cod Gen; cu FORCE și cu LENGTH
RUN;
Interclasare -1
▪ Dacă se folosește instrucțiunea BY la concatenarea seturilor de
date, rezultatul îl reprezintă interclasarea acestora.
▪ Sintaxa generală este:
DATA set-date-iesire;
SET set-date-1 set-date-2;
BY variabil(e);
RUN;
▪ Fiecare set de date de intrare trebuie să fie sortat sau indexat în
ordine crescătoare după variabilele din BY.
▪ Când SAS interclasează seturi de date, observațiile sunt citite în
mod secvențial, în ordinea în care sunt specificate seturile de date și
variabilele BY, până când toate observațiile au fost procesate.
▪ Setul de date rezultat include toate variabilele și toate observațiile
din seturile de date de intrare.
11
Interclasare -2
Set de date C Set de date D
NR Var NR Var

1 C1 2 D1

2 C2 3 D2

2 C3 3 D3

3 C4
Interclasare

Setul de date
combinat
NR Var
1 C1
2 C2
2 C3
2 D1
3 C4
3 D2 12
3 D3
Interclasare -3
DATA persoane1;
INPUT cod Gen $;
DATALINES;
1 M
3 F
5 M
;
RUN;
DATA persoane2;
INPUT cod Gen $ Judet $;
DATALINES;
2 Masculin IL
4 Feminin DB
6 Masculin VL
7 Feminin CJ
;
RUN;
data interclasare;
set persoane1 persoane2;
by Cod;
RUN;
PROC PRINT DATA = interclasare;
Fuziune pe baza unei corespondențe -1
▪ Metodele de combinare anterioare au fost bazate pe ordinea
observațiilor din seturile de date de intrare.
▪ Există și situații când este necesară combinarea observațiilor din
două sau mai multe seturi de date într-o singură observație dintr-un
set de date nou în funcție de valorile unei variabile comune.
▪ Sintaxa generală este:
DATA set-date-iesire;
MERGE set-date-1 set-date-2;
BY <DESCENDING> variabil(e);
RUN;
▪ Opțiunea DESCENDING indică faptul că seturile de date de intrare
sunt sortate în ordine descrescătoare și se aplică doar variabilei care
urmează imediat instrucțiunii.
▪ Fiecare set de date de intrare trebuie sortat sau indexat după
variabila(e) din clauza BY. DESCENDING nu se poate folosi pentru
date indexate, deoarece acestea sunt stocate ascendent.

14
Fuziune pe baza unei corespondențe -2
Set de date A Set de date B
NR VarA NR VarB

1 A1 1 B1

2 A2 2 B2

3 A3 4 B3

Fuziune

Setul de date combinat


NR VarA VarB

1 A1 B1

2 A2 B2

3 A3

4 B3
DATA persoane1;
INPUT cod Gen $;
DATALINES;
1 M
2 F
3 M
4 F
;
RUN;
DATA persoane2;
INPUT cod Gen $ Judet $;
DATALINES;
2 Masculin IL
3 Feminin DB
6 Masculin VL
7 Feminin CJ
;
RUN;
data jonctiune;
merge persoane1 persoane2;
by /* descending*/ Cod;
RUN;
PROC PRINT DATA = jonctiune;
Fuziune pe baza unei corespondențe -3
▪ La modul general, SAS verifică în mod secvențial dacă fiecare
observație a fiecărui set de date se potrivește cu valoarea din clauza
BY și apoi scrie observația combinată în noul set de date.
▪ Fără alte instrucțiuni suplimentare sau opțiuni, setul de date de ieșire
va conține valori din toate observațiile tuturor seturilor de date de
intrare.
▪ Totuși, în multe situații dorim să selectăm doar observațiile care au
corespondent în două sau mai multe seturi de date.
▪ Pentru a exclude observațiile care nu au corespondent din setul de
date de ieșire, se poate folosi opțiunea IN= a secțiunii de date
împreună cu instrucțiunea condițională IF pentru a genera un subset
de date.
▪ Opţiunea IN= asociată unui set de date poate fi folosită pentru a
urmări care din seturile de date de intrare a contribuit la fiecare
observaţie din setul de date nou creat.

17
Fuziune pe baza unei corespondențe -4
DATA persoane;
INPUT ID Gen$ Varsta;
DATALINES;
1492 F 45
1584 M 38
1943 F 52
2031 M 19
3140 M 60
3514 F 28
5403 F 35
7219 F 42
;
RUN;

DATA masuratori;
INPUT ID Inaltime
Greutate;
DATALINES;
1492 158 60
1584 193 95
2031 178 75
3515 172 58
5403 163 54
18
;
Fuziune pe baza unei corespondențe -5
▪Opţiunea IN= se specifică
după numele fiecărui set de
date şi este urmată de un nume
DATA fuziune_variabile_in; de variabilă temporară ales de
MERGE persoane (IN=inpers) utilizator, sintaxa fiind:
masuratori
(IN=variabila). Variabila nu va fi
(IN=inmasura);
BY ID;
inclusă în setul de date rezultat.
file print; ▪Variabilele temporare definite
PUT ID= inpers= gen= prin IN= iau valoarea 1
varsta= inmasura= inaltime= ;
(adevărat) dacă setul de date la
RUN;
care se referă contribuie la
observaţia curentă din setul de
date nou şi 0 (fals) în caz
contrar.

19
Fuziune pe baza unei corespondențe -6
▪ Realizăm o fuziune între observațiile care au corespondent.
DATA fuziune_corespondenta;
MERGE persoane (IN=inpers)
masuratori (IN=inmasura);
BY ID;
IF inpers=1 and inmasura=1;
* cod echivalent;
* IF inpers and inmasura;
RUN;

Cu IF

Fara IF 20
Fuziune pe baza unei corespondențe -7
B. Selectăm persoanele care nu au efectuat măsurători.
DATA persoane_fara_masuratori;
MERGE persoane (IN=inpers)
masuratori (IN=inmasura);
BY ID;
IF inpers=1 and inmasura=0;
* cod echivalent;
* IF inpers and NOT inmasura;
RUN;
▪ La fel ca la definirea seturilor de date SAS din fișiere externe sau alte
seturi de date, se pot specifica variabilele pe care dorim să le păstrăm
sau să le excludem folosind opțiunile DROP= și KEEP=.
DATA fuziune_inaltime (DROP=ID);
MERGE persoane (IN=inpers) masuratori (DROP=Greutate
IN=inmasura);
BY ID;
IF inpers=1 and inmasura=1;
RUN;

21
Unde specificăm DROP= și KEEP= ?
▪ În cazul fuziunii, opțiunile DPOP= și KEEP= se pot specifica fie în
instrucțiunea DATA, fie în MERGE, în funcție de modul în care dorim
să referim variabilele în setul de date:
➢ Dacă nu dorim să referim anumite variabile și ca acestea să
apară în noul set de date, atunci acestea vor fi specificate în
opțiunea DROP = a instrucțiunii MERGE.
masuratori (DROP=Greutate IN=inmasura);
➢ Dacă avem nevoie să referim o variabilă din seturile de date de
intrare (spre exemplu, într-o instrucțiune IF), atunci variabila va fi
specificată în opțiunea DROP a instrucțiunii DATA. În sens
contrar, este posibil să obținem rezultate nedorite și ca variabila
să fie neinițializată.
DATA fuziune_inaltime (DROP=ID);
Atenție!!! Atunci când este folosită în instrucțiunea DATA, opțiunea
DROP= doar elimină variabilele din noul set de date, acestea sunt în
continuare citite și disponibile pentru procesare în secțiunea de date.22
Redenumirea variabilelor
▪ Dacă există mai multe variabile care au același nume în seturile de
date de intrare, atunci fuziunea seturilor de date în secțiunea de date
va duce la suprascrierea valorilor variabilelor din primul set de date cu
valorile variabilelor cu același nume din seturile de date care îl succed.
▪ Pentru a preveni suprascrierea, se pot redenumi variabilele folosind
opțiunea RENAME= în instrucțiunea MERGE.
▪ Sintaxa generală este:
(RENAME=(nume_variabila_vechi=nume_variabila_nou));
▪ Se pot redenumi oricâte variabile într-o singură instrucțiune
RENAME.
▪ De asemenea, putem folosi RENAME= și pentru a redenumi variabile
în instrucțiunea SET sau în setul de date de ieșire din instrucțiunea
DATA.

23
Redenumirea variabilelor: exemplu -1
▪ Cazul 1 – evitarea suprascrierii datelor
▪ Se consideră seturile de date listate mai jos referitoare la persoanele
care s-au înscris pentru susținerea unui test de certificare. Se dorește
realizarea unei joncțiuni între aceste două seturi de date.

DATA examene_certificare;
MERGE inscrisi (RENAME=(data=data_inscriere))
sustineri (RENAME=(data=data_sustinere));
BY Cod;
FORMAT data_inscriere data_sustinere DDMMYY10.;
RUN;

Ce credeți că genera programul în absența instrucțiunilor RENAME 24


25
Redenumirea variabilelor: exemplu -2
▪ Cazul 2 – facilitarea combinării datelor
DATA produse1;
INPUT COD Pret Disponibil;
DATALINES;
124 23.5 50
178 35.0 43
197 44.6 12
;
RUN;
DATA produse2;
INPUT COD Cost Stoc;
DATALINES;
234 53.7 10
356 75.5 12
367 84.0 34
;
RUN;
DATA concatenare;
SET produse1 (RENAME=(Disponibil=Stoc))
produse2 (RENAME=(Cost=Pret));
RUN;
Ce credeți că va genera programul în absența instrucțiunilor RENAME
26
27
Fuziunea datelor detaliate cu date agregate
▪ Studiu de caz: Crearea unui set de date cu duplicatele înregistrărilor
1) Determinarea numărului de apariții ale variabilei de identificare
(procedura FREQ) și crearea unui set de date cu frecvențele.
2) Sortarea setului de date.
3) Fuziunea dintre setul de date inițial și cel care conține frecvențele dacă
numărul de apariții este mai mare decât 1.
PROC FREQ DATA=exemple.salarii1;
TABLES Cod/nocum out=frecvente;
RUN;
PROC PRINT DATA= frecvente;
WHERE count >= 2;
RUN;
PROC SORT DATA=exemple.salarii out=salarii_sort;
by Cod;
RUN;
DATA duplicate;
MERGE frecvente (in=InFrecvente WHERE = (count>1) KEEP
= Cod count)
salarii_sort (in=InSalarii);
BY Cod;
IF InFrecvente and InSalarii;
DROP count; 28
RUN;
29
Proceduri specifice SQL -1
▪ Procedura SQL reprezintă implementarea în SAS a limbajului
Structured Query Language (SQL), un standard utilizat pe scară
largă pentru regăsirea și utilizarea datelor din tabele.
▪ Procedura SQL este folosită, în mod frecvent, ca o alternativă la alte
proceduri SAS sau la secțiunea de date.
▪ Se poate folosi procedura SQL pentru a:
✓ Regăsi și manipula date din tabele SAS
✓ Adăuga și modifica valori într-o tabelă
✓ Adăuga, modifica și șterge coloane într-o tabelă
✓ Crea tabele și view-uri
✓ Crea joncțiuni între mai multe tabele
✓ Genera rapoarte

30
Proceduri specifice SQL -2
▪ Asemenea altor proceduri SAS, procedura SQL permite combinarea
datelor din două sau mai multe surse diferite și prezentarea acestora
ca o singură tabelă. Spre exemplu, se pot combina date din două
tipuri de baze de date externe sau din baze de date externe și seturi
de date SAS.
▪ Procedura SQL diferă de multe alte proceduri prin aceea că
majoritatea din instrucțiunile sale includ clauze.
PROC SQL;
SELECT Cod,Pozitie,Salariu,
Salariu*.06 as Bonus
FROM biblioteca.salarii
WHERE Salariu<32000
ORDER BY Cod;
QUIT;
▪ În exemplul de mai sus apar două instrucțiuni: PROC SQL și
SELECT. Instrucțiunea SELECT include clauzele: SELECT, FROM,
WHERE și ORDER BY.

31
Proceduri specifice SQL -3
▪ Procedura SQL nu necesită o instrucțiune RUN, iar fiecare
interogare este executată imediat. Dacă se folosește instrucțiunea
RUN la sfârșitul unei proceduri SQL, SAS o ignoră, execută toate
instrucțiunile în mod obișnuit și generează în fișierul de log SAS nota
de mai jos:
NOTE: PROC SQL statements are executed immediately; The
RUN statement has no effect
▪ Pentru a termina procedura, se trimite spre rulare altă secțiune de
date sau de proceduri sau se folosește instrucțiunea QUIT.

▪ Spre exemplu, ca măsură de precauție, SAS Enterprise Guide


adaugă automat o instrucțiune QUIT la codul trimis către SAS.
Pentru procedura SQL aceasta este o bună practică de programare.

32
Combinarea datelor cu PROC SQL -1
▪ O joncțiune în procedura SQL reprezintă o interogare în care se
specifică mai multe tabele care trebuie combinate și care, de cele
mai multe ori, arată ce condiții trebuie să îndeplinească rândurile
care vor fi combinate și returnate către setul de date rezultat.
▪ Se pot utiliza cele patru tipuri de joncțiuni din limbajul SQL: inner
join, left join, right join si full outer join.
▪ Sintaxa generală pentru joncțiunea internă este:
SELECT coloana-1<,...coloana-n>
FROM tabela-1 | view-1, tabela-2 | view-2<,...tabela-n | view-n>
WHERE conditie(i)-jonctiune
<AND alte conditii suplimentare)>
<alte clauze>;
▪ Joncțiunea internă vs. produsul cartezian.

33
Combinarea datelor cu PROC SQL -2
▪ O joncțiune externă combină și afișează toate rândurile care au
corespondent între tabele, plecând de la criteriul de corespondență
specificat (numit și condiție de joncțiune), plus o parte sau toate
rândurile care nu au corespondent. Aceasta poate fi privită ca o
augmentare a joncțiunii interne.
▪ Sintaxa generală pentru joncțiunile externe este:
SELECT coloana-1<,...coloana-n>
FROM tabela-1 | view-1
LEFT JOIN | RIGHT JOIN | FULL JOIN
tabela-2 | view-2
ON conditie(i)-jonctiune
<alte clauze>;
▪ Dacă se dorește folosirea unei sintaxe asemănătoare pentru toate
tipurile de joncțiune, atunci și pentru joncțiunea internă se poate
folosi aceeași sintaxă ca și la joncțiunile externe specificând INNER
JOIN ca tip de joncțiune.
▪ Diferența dintre cele două modalități de descriere a unei joncțiuni
interne este aceea că în prima variantă se pot combina până la 256
de tabele sau view-uri, iar în cea de-a doua doar două. 34
Comparație SAS-SQL: exemplu
▪ Considerăm pentru exemplificare cele două seturi de date de mai
jos. Rândurile evidențiate sunt cele care nu au corespondent în
celălalt set de date.

▪ Vom exemplifica cele patru tipuri de joncțiuni, comparativ, folosind


abordarea specifică SAS și abordarea SQL.

35
Exemple INNER JOIN
PROC SQL; PROC SORT DATA =
CREATE TABLE inner_SQL as exemple.Vanzari;
SELECT b.Tranzactie BY Cod_vanzare;
, b.Cod_produs RUN;
, b.Cantitate PROC SORT DATA = exemple.Agenti;
, b.DATA_vanzare BY Cod_vanzare;
, a.Cod_vanzare RUN;
, a.Nume DATA inner_MERGE;
FROM exemple.Vanzari b, MERGE exemple.Vanzari ( in = s )
Exemple.Agenti a exemple.Agenti ( in = p );
WHERE a.Cod_vanzare = BY Cod_vanzare;
b.Cod_vanzare IF s and p;
ORDER BY Cod_vanzare; RUN;
QUIT;

Ambele abordări furnizează rezultate identice.

36
37
Exemple LEFT JOIN
PROC SQL; PROC SORT DATA =
CREATE TABLE left_SQL as exemple.Vanzari;
SELECT s.Tranzactie BY Cod_vanzare;
, s.Cod_produs RUN;
, s.Cantitate PROC SORT DATA = exemple.Agenti;
, s.DATA_vanzare BY Cod_vanzare;
, p.Cod_vanzare RUN;
, p.Nume DATA left_MERGE;
FROM exemple.Vanzari s MERGE exemple.Vanzari ( in = s )
left join Exemple.Agenti ( in = p );
exemple.Agenti p BY Cod_vanzare;
ON s.Cod_vanzare = IF s;
p.Cod_vanzare RUN;
ORDER BY Cod_vanzare;
QUIT;

38
39
Exemple RIGHT JOIN
PROC SQL; PROC SORT DATA =
CREATE TABLE right_SQL as exemple.Vanzari;
SELECT p.Cod_vanzare BY Cod_vanzare;
, p.Nume RUN;
, s.Tranzactie PROC SORT DATA = exemple.Agenti;
, s.Cod_produs BY Cod_vanzare;
, s.Cantitate RUN;
, s.DATA_vanzare DATA right_MERGE;
FROM exemple.Vanzari s MERGE exemple.Vanzari ( in = s )
right join exemple.Agenti ( in = p );
exemple.Agenti p BY Cod_vanzare;
ON s.Cod_vanzare = IF p;
p.Cod_vanzare RUN;
ORDER BY Cod_vanzare;
QUIT;

40
41
Exemple FULL OUTER JOIN
PROC SQL; PROC SORT DATA =
CREATE TABLE full_SQL as exemple.Vanzari;
SELECT p.Cod_vanzare BY Cod_vanzare;
, p.Nume RUN;
, s.Tranzactie PROC SORT DATA = exemple.Agenti;
, s.Cod_produs BY Cod_vanzare;
, s.Cantitate RUN;
, s.DATA_vanzare DATA full_MERGE;
FROM exemple.Vanzari s MERGE exemple.Vanzari ( in = s )
full outer join exemple.Agenti ( in = p );
exemple.Agenti p BY Cod_vanzare;
ON s.Cod_vanzare = RUN;
p.Cod_vanzare
ORDER BY Cod_vanzare;
QUIT;

42
Comparație SAS-SQL -2
▪ Pentru a rezolva această problemă se folosește funcția COALESCE.
PROC SQL;
CREATE TABLE full_SQL as
SELECT COALESCE(p.Cod_vanzare, s.Cod_vanzare) as Cod_vanzare
, p.Nume
, s.Tranzactie
, s.Cod_produs
, s.Cantitate
, s.DATA_vanzare
FROM exemple.Vanzari s
full outer join
exemple.Agenti p
ON s.Cod_vanzare = p.Cod_vanzare
ORDER BY Cod_vanzare;
QUIT;

43
Avantaje comparative ale abordărilor
SQL
✓ Seturile de date nu trebuie sortate în mod explicit, doarece SQL
sortează datele în mod implicit.
✓ Se poate realiza, în aceeași interogare, o joncțiune între mai
multe tabele după mai multe chei (chiar dacă tipurile de variabile
diferă).
✓ Interogările care realizează joncțiuni pot, de asemenea, să
realizeze agregări ale datelor.
SAS
✓ Permite folosirea sintaxei flexibile a secțiunii de date, cu folosirea
de masive, variabilele temporare IN=, FIRST., LAST., etc.
✓ Construcțiile limbajului sunt mai ușor de înțeles și aplicat.
Concluzie: SQL a fost construit special pentru a realiza interogări la
diferite niveluri de compexitate, de avantajele sale putând beneficia
și în SAS prin procedura PROC SQL.

44
Să recapitulăm!
1. Care dintre metodele de combinare a seturilor de
date folosesc instrucțiunea SET?
2. Ce diferențe sunt între concatenare și adăugare?
3. Ce fel de variabilă este cea definită prin IN=variabila?
4. De ce este uneori necesară redenumirea variabilelor
la combinarea seturilor de date?
5. În declarația MERGE date1(DROP=Nume) variabila Nume
va putea fi folosită în continuare în secțiunea de date?
6. Câte seturi de date pot participa, în procedura SQL,
la o joncțiune internă ?
7. Care este rolul funcției COALESCE și împreună cu ce
tipuri de joncțiuni se folosește?
Programarea în
limbajul SAS

PARTEA A IV-A
CUPRINS Curs
➢ Proceduri SAS
Motode de automatizare a prelucrării datelor
➢ Procesarea variabilelor cu ajutorul masivelor
➢ Utilizarea facilității SAS macro
Proceduri SAS -1
▪ Majoritatea prelucrărilor asupra datelor sunt realizate în SAS prin
intermediul procedurilor sale predefinite. Acestea reprezintă
secțiunile de proceduri în cadrul programelor SAS.
▪ Prin intermediul procedurilor SAS se pot realiza, spre exemplu,
rapoarte de detaliu și agregate, reprezentări grafice, analize
statistice elementare sau complexe, rezolvarea unor probleme de
optimizare și analiză decizională etc.
▪ Există o mare varietate de proceduri SAS incluse în toate pachetele
oferite de limbaj.
Proceduri pentru prezentarea datelor
Scop: Rapoarte Pachetul: BASE SAS
PRINT Realizează rapoarte detaliate și este principala modalitate de afișare de
datelor.
TABULATE Crează rapoarte în formă tabelară care afișează frecvențe, procente și
statistici descriptive.
REPORT Oferă o modalitate de realizare a rapoartelor care combină
caracteristice oferite de procedurile PRINT, MEANS și TABULATE. 3
Proceduri SAS -2
Proceduri pentru agregarea datelor:
Scop: Agregare Pachetul: BASE SAS
MEANS Realizează agregarea datelor prin generarea de indicatori statistici
pentru datele numerice. Generează seturi de date agregate.
FREQ Generează tabele care arată distribuția valorilor datelor categorice.
UNIVARIATE Calculează distribuția unidimensională a datelor, realizează evaluarea
normalității datelor și identifică valorile extreme.
SUMMARY Exte similară procedurii MEANS, având câteva opțiuni diferite.

Proceduri pentru analize statistice elementare:


Scop: Statistici Pachetul: BASE SAS
CORR Calculează coeficienții de corelație Pearson, măsoară statistici
nonparametrice de asociere și probabilitățile asociate acestora.
RANK Calculează rangurile pentru una sau mai multe variabile numerice în
cadrul observațiilor unui set de date și creează un set de date de ieșire.
STANDARD Creează un set de date de ieșire ce conține variabile care sunt
standardizate la o anumită medie și deviație standard.
4
Proceduri SAS -3
Proceduri pentru analize statistice avansate:
Scop: Statistici Pachetul: SAS/STAT
ANOVA Realizează analize dispersionale pe date echilibrate.
REG Este folosită pentru mai multe modele de regresie și aplică metoda celor
mai mici pătrate.
LOGISTIC Se folosește pentru modelele cu variabile dependente binare, ordinale sau
nominale.
CLUSTER Realizează grupări ierarhice ale observațiilor dintr-un set de date.

Proceduri pentru realizarea de grafice:


Scop: Grafice Pachetul: SAS/GRAPH
GCHART Produce șase tipuri de grafice care reprezintă grafic valoarea unei statistici
calculate pentru una sau mai multe variabile.
GPLOT Construiește o diagramă de corelație pentru două variabile.

Proceduri pentru probleme de optimizare:


Scop: Optimizare Pachetul: SAS/OR
Proceduri Sunt specifice pentru arbori decizionali, grafice GANTT, probleme de
transport, alocare, planificare etc.
Solvere Aplică diferiți algoritmi pentru rezolvarea problemelor de tip 5
programare liniară liniară, non-liniară, teoria grafurilor etc.
Sintaxa procedurilor SAS -1
▪ Sintaxa generală a procedurilor SAS poate fi destul de complexă.
Spre exemplu, procedura MEANS are următoarea sintaxă completă:
PROC MEANS <option(s)> <statistic-keyword(s)>;
BY <DESCENDING> variable-1 <... <DESCENDING> variable-
n><NOTSORTED>;
CLASS variable(s) </ option(s)>;
FREQ variable;
ID variable(s);
OUTPUT <OUT=SAS-data-set> <output-statistic-specification(s)>
<id-group-specification(s)> <maximum-id-specification(s)>
<minimum-id-specification(s)> </ option(s)> ;
TYPES request(s);
VAR variable(s) < / WEIGHT=weight-variable>;
WAYS list;
6
WEIGHT variable
Sintaxa procedurilor SAS –2
▪ În practică, rareori se folosește varianta completă a procedurii.
▪ Vom exemplifica câteva modalități de utilizare a sintaxei procedurilor.
1. Folosirea unei proceduri fără opțiuni
În mod implicit, SAS folosește ultimul set de date creat și calculează
medii pentru toate variabilele numerice din acel set de date.
PROC MEANS;
RUN;
2. Folosirea de opțiuni
Opțiunea data= specifică setul de date pe care se va aplica procedura.
Este recomandat să se folosească întotdeauna. Opțiunile
n, mean și std stabilesc indicatorii statistici care se vor calcula.
PROC MEANS DATA=auto N MEAN STD ;
RUN;
3. Folosirea de declarații adiționle
Declarația var arată ce variabile se vor folosi pentru calculul
indicatorilor, iar class determină defalcarea statisticilor în funcție de
valorile variabilei specificate.
PROC MEANS DATA=auto;
CLASS provenienta;
VAR pret; 7
RUN;
Procesarea variabilelor cu ajutorul masivelor -1
▪ În secțiunea de date, de multe ori, este necesar să se repete acceași
secvență de cod pentru mai mult de o singură variabilă.
▪ Chiar dacă variabilele pot fi procesate individual, este mai eficient să
le gestionăm grupate.
▪ Acest lucru poate fi realizat în SAS cu ajutorul masivelor.
❑ Exemplu: Dorim să transformăm din grade Fahrenheit în grade
Censius temperaturile înregistrate în fiecare zi din luna martie
pentru o perioadă de timp.

DATA temperaturi;
SET temp_martie;
ARRAY temp {31} ziua1-ziua31;
DO i=1 to 31;
temp{i}=5*(temp{i}-32)/9;
END;
RUN;

8
Procesarea variabilelor cu ajutorul masivelor -2
▪ Masivele se pot folosi pentru a simplifica codul necesar
pentru:
✓ Executarea de calcule repetitive
✓ Crearea de variabile care au atribute asemănătoare
✓ Citirea datelor
✓ Rotirea seturile de date prin schimbarea variabilelor cu
observațiile sau a observațiilor cu variabilele
✓ Compararea variabilelor
✓ Realizarea de tabele de căutare (table lookup)

9
Crearea masivelor unidimensionale -1
▪ Definire
ARRAY nume_masiv {<dimensiune>} <elemente>;
unde:
• nume_masiv specifică numele masivului
• dimensiune descrie numărul de elemente ale masivului
• elemente listează variabilele care sunt incluse în masiv.
Elementele trebuie să fie ori de tip numeric, ori de tip caracter.
Dacă nu se speficică elementele, atunci se crează variabile noi
având nume implicite.
Observații
❖ Un masiv nu trebuie să aibă același nume cu o variabilă din
secțiunea de date sau cu numele unei funcții.
❖ Nu se pot folosi pentru denumire cuvinte rezervate pentru
instrucțiuni.
❖ Un masiv există doar pe durata secțiunii de date.

10
Crearea masivelor unidimensionale -2
▪ Specificarea dimensiunii
Considerăm setul de date Vanzari2018, în care este necesar să
procesăm variabilele Trim1, Trim2, Trim3 și Trim4 în acelși fel.
Există mai multe modalități de specificare a dimensiunii:
➢ specificarea directă a numărului de elemente
ARRAY vanzari{4} trim1 trim2 trim3 trim4;
➢ Specificarea unui interval de valori
ARRAY vanzari{96:99} totalv96 totalv97 totalv98 totalv99;
➢ Folosirea semnului asterisc (*), iar SAS va determina dimensiunea
prin numărarea elementelor
ARRAY vanzari{*} trim1 trim2 trim3 trim4;
• Dimensiunea poate fi inclusă între paranteze rotunde, pătrate sau
acolade.
▪ Specificarea elementelor
Elementele masivului se pot specifica individual, separate prin spațiu,
sau ca listă de variabile care grupează mai multe variabile.
ARRAY vanzari{4} trim1-trim4; 11
Crearea masivelor unidimensionale -3
▪ Liste de variabile ca elemente ale masivului
Se pot specifica listele de variabile în formatele următoare:
➢ O serie numerotată de variabile: Var1-Varn;
▪ variabilele trebuie să aibă același nume, cu excepția ultimului
sau ultimelor caractere
▪ ultimul caracter al variabilelor trebuie să fie numeric
▪ variabilele trebuie numerotate consecutiv
➢ Listele cu domeniu denumit: a--d;
▪ depind de ordinea internă sau de poziţia variabilelor în setul de
date.
▪ lista abreviată a--d referă variabilele numerice care au fost
definite prin declaraţia INPUT a b c d; .
➢ Listele cu valori speciale: _NUMERIC_ _CHARACTER_ _ALL_
▪ Au semnificația de a specifica, în grup, toate variabilele de tip numeric,
caracter și respectiv, de orice tip, care au fost deja definite în secțiunea
de date curentă.
ARRAY vanzari {*}_all_;
12
Crearea masivelor unidimensionale -4
▪ Referirea elementelor
nume_masiv (subscript)
Unde subscript:
• este inclus în paranteze rotunde, pătrate sau acolade
• specifică o variabilă, o expresie SAS sau un întreg
• este inclus între limitele dimensiunii masivului

Exemplu: crearea unui set de date care conține vânzările exprimate în USD.

DATA vanzari18_usd (drop=i);


SET vanzari18;
ARRAY vanzari(4) trim1-trim4;
DO i=1 to 4;
vanzari(i)= round(vanzari(i)/4.75,1);
END;
RUN;

13
Crearea masivelor unidimensionale -5
LIBNAME ad_data '/home/nume.prenume/';
*exemple masive;
DATA vanzari18;
INPUT RepVanzari $ Trim1 Trim2 Trim3 Trim4;
DATALINES;
Ionescu 346890 456876 231677 298700
Popescu 150000 345000 678900 345789
Irimia 455000 245000 588900 195781
Dimian 670000 565000 458900 235789
Cristea 346890 456876 231677 298700
Avram 455566 566245 654900 295781
;
DATA vanzari18_usd (drop=i);
SET vanzari18;
ARRAY vanzari(4) trim1-trim4;
DO i=1 to 4;
vanzari(i)= round(vanzari(i)/4.75, 1);
END;
RUN;
Title "Vanzari in LEI";
proc print data=vanzari18;
run;
Title "Vanzari in USD";
proc print data=vanzari18_usd;
run;
14
Crearea masivelor unidimensionale -5

15
Liste de variabile - exemplu
DATA chestionar;
INPUT q1 $ q2 $ q3 $ q14 $ q5 $ q6 $ q7 $ q8 $ q9 $ q10 $;
DATALINES;
0 1 DA nu Da 2 6 NS 0 1
2 da nu 3 2 1 0 ns 0 NU
2 1 2 0 Ns DA 0 1 4 NU
;
DATA chestionar_cor;
SET chestionar;
ARRAY intrebari(*) _CHARACTER_;
DO i=1 TO DIM (intrebari);
SELECT(upcase (intrebari(i)));
WHEN ('0', 'NU') intrebari(i)='0';
WHEN ('1', 'DA') intrebari(i)='1';
WHEN ('2', 'NS') intrebari(i)='2';
OTHERWISE call missing (intrebari(i));
END;
END;
DROP i;
RUN;

16
Liste de variabile - exemplu

17
Crearea de variabile în masive
▪ În instrucțiunea ARRAY se pot crea variabile prin omiterea
specificării elementelor masivului din declarație.
▪ Dacă nu se referă variabile deja existente, SAS crează variabile noi
în mod automat cărora le asignează și nume implicite.
▪ Aceste nume sunt formate prin concatenarea numelui masivului cu
numerele de la 1 la numărul de elemente.

Exemplu: calculăm pierderea sau creșterea în greutate, de la o săptămână la


alta, a membrilor unei clase de fitness.

DATA diferente;
SET greutate;
ARRAY gr{6} greutate1-greutate6;
ARRAY difGr {5};
DO i=1 to 5;
difGr{i}=gr{i+1}-gr{i};
END;
RUN;
18
Crearea de variabile în masive
DATA greutate;
INPUT nume$ greutate1 greutate2 greutate3
greutate4 greutate5 greutate6;
DATALINES;
Mihaela 67.5 67.2 66.3 66.0 65.8 66.1
Doina 72.3 71.6 71.3 70.5 70.0 69.2
Cristi 93.3 92.4 91.5 92.3 91.8 91.5
;
DATA diferente;
SET greutate;
ARRAY gr{6} greutate1-greutate6;
ARRAY difGr {5};
DO i=1 to 5;
difGr{i}=gr{i+1}-gr{i};
END;
RUN;
PROC PRINT DATA=diferente;
RUN;

19
Alocarea de valori inițiale

▪ Se realizează prin declarații de genul:


ARRAY obiectiv{4} o1 o2 o3 o4 {300 340 350 390};
ARRAY var{4} {1 2 3 4};
Exemplu: calculam nivelul de realizare a unui indicator financiar.

DATA Vanzari_anuale;INPUT RepVanzari $ Vanz1 Vanz2 Vanz3 Vanz4;


DATALINES;
Dinca 8400 8800 9300 9800
Irimia 9500 9300 9800 8900
Mihai 9150 9200 9650 11000
; RUN;
DATA raport(DROP=i);
SET Vanzari_anuale;
ARRAY vanzari{4} vanz1-vanz4;
ARRAY tinta {4} (9000 9300 9600 9900);
ARRAY realizat {4};
DO i=1 TO 4;
realizat {i} =100* vanzari{i}/tinta{i};
END;RUN;
20
Alocarea de valori inițiale

▪ Acesta este un exemplu simplu de tabelă de căutare.

▪ Pentru a nu stoca variabilele tinta1-tinta4, definim masivul ca


temporar:
ARRAY tinta {4} _temporary_ (9000 9300 9600 9900);

21
Crearea masivelor bidimensionale
▪ Masivele bidimensionale simulează o structură de tip tabelă.
▪ Sintaxa generală este:
ARRAY nume_masiv {randuri, coloane} <elemente>;
ARRAY an {3,4} x1-x12;
X1 X2 X3 X4

X5 X6 X7 X8

X9 X10 X11 X12

Spre exemplu, X7 se referă ca an {2,3}


▪ Se folosesc, de obicei, împreună cu bucle DO imbricate.
▪ Aplicații frecvente în SAS:
➢ Restructurarea variabilelor unui set de date (similară agregării)
➢ Transpunerea unui set de date
22
Aplicații cu masive bidimensionale
▪ Restructurarea unui grup de variabile - Exemplu: Vânzările anuale ale unei
companii au fos stocate lunar. Se dorește gerearea unui nou set de date
care conține vânzările trimestriale.
DATA lunare;
INPUT An Luna1 Luna2 Luna3 Luna4 Luna5 Luna6 Luna7 Luna8 Luna9 Luna10
Luna11 Luna12;
DATALINES;
2016 23000 21000 25200 26700 34500 23400 67000 23700 45000 34200 37000 45800
2017 68000 21700 35000 44200 35000 25800 43000 31000 28900 34700 56500 67400
2018 33000 31000 35200 46700 44500 33400 56000 44700 67000 45200 23000 56800
;
DATA trimestriale (DROP= i j ) trimestriale2 ;
SET lunare;
ARRAY l {4,3} luna1-luna12;
ARRAY trim {4};
DO i=1 to 4;
trim {i}=0;
DO j=1 to 3;
trim{i}+l{i,j};
END;
END;
DROP Luna1-Luna12;
RUN;

PROC PRINT DATA=trimestriale;


RUN; 23
Exemplu transpunere
▪ Transpunerea (rotirea) unui set de date prin schimbarea variabilelor cu
observațiile sau viceversa. - Exemplu: Transpunerea setului Vanzari_anuale.
DATA Vanzari_anuale_timestru (DROP=vanz1-vanz4);
SET Vanzari_anuale;
ARRAY finante{4} vanz1-vanz4;
DO trim=1 to 4;
Vanzari=finante{trim};
output;
END;
RUN;

24
Facilitatea SAS macro
▪ Folosind limbajul SAS macro, facilitatea SAS macro are rolul de a
ușura dezvoltarea și mentenanța programelor prin mai multe
metode:
✓ Efectuarea unei mici modificări în program, pe care SAS o
propagă ulterior în întreg programul.
✓ Posibilitatea de a scrie o bucată de cod sursă, pe care să o
reutilizăm în același program sau în altele.
✓ Programele pot fi orientate pe date, lasând SAS să decidă
acțiunile potrivite în funcție de valorile efective ale datelor.

Macro procesorul
▪ Odată cu trimiterea spre execuție, codul SAS standard este compilat
și executat imediat.
▪ Atunci când se execută cod macro, există un pas adițional.
▪ Înainte de compilare și execuție, SAS trimite macro declarațiile către
macro procesor, care le transformă generând cod SAS standard.
▪ Deoarece presupune scrierea unui program care scrie un alt
program, utilizarea macro declarațiior mai poartă denumirea de meta-
programare. 25
Limbajul SAS macro
▪ Limbajul SAS macro propune două concepte:
➢ macro variabilele
➢ macro procedurile
Macro variabile
▪ Macro variabilele în SAS permit substituirea de text în programele
SAS. Acestea pot substitui o varietate de informații, cum ar fi:
✓ informații furnizate de sistemul de operare
✓ informații referitoare la sesiunea SAS
✓ șiruri de caractere
▪ Atunci când se referă o macro variabilă într-un program SAS, SAS
înlocuiește referința cu valoare textuală care a fost asignată macro
variabilei. Prin această substituire, crește dinamica și gradul de
reutilizare în programele SAS.
▪ O macro variabilă se comportă ca o variabilă standard cu
următoarele restricții:
✓ ia o singură valoare
✓ nu aparține unui set de date
✓ este numai de tip caracter
▪ Variabilele macro pot fi:
a. definite de utilizator 26
b. automate
Macro variabile -1
▪ Variabilele definite de utilizator pot fi create cu declarația %LET:
%LET nume-macro-variabila =valoare;
▪ La alocarea valorii nu sunt necesare ghilimelele.
%LET iteratii = 10;
%LET oras = Ramnicu Valcea;
▪ Atunci când este referit în cod, numele unei macro variabile este
prefixat de caracterul ampersant (&).
DO i=1 to &iteratii;
TITLE "Scoli din &oras";
Exemplu: Crearea unor rapoarte în funcție de valoarea unei macro variabile.
%LET an=2017;
PROC PRINT DATA=ad_data.orar_cursuri;
WHERE year(Data_incepere)=&an;
TITLE "Cursurile programate pentru anul &an";
RUN;
proc means data=cursuri mean;
where year(Data_incepere)=&an;
class Locatie;
var Taxa;
title1 "Taxe medii pentru cursurile anului &an";
title2 "per centru de instruire"; 27
Macro variabile -2

28
Macro variabile -3
▪ De fiecare dată când este trimis cod SAS către execuție, macro
procesorul crează în mod automat anumite macro variabile. Mai
departe, aceste variabile automate pot fi folosite în programe.
▪ Exemple de macro variabile automate: SYSTIME (ora curentă),
SYSDAY (ziua din săptămână), SYSSCP (sistemul de oprerare pe care
rulează), SYSVER (versiunea SAS cu care se lucrează).

Exemplu: Crearea unui subset de date în funcție de valoarea unei macro


variabile și folosirea de macro variabile automate.
footnote1 "Creat la &systime &sysday, &sysdate9";
footnote2 "pe sistemul &sysscp folosind versiunea
&sysver";
%let an=2018;
title "Cursurile din anul &an";
data ad_data.cursuri&an;
set cursuri;
if year(Data_incepere)=&an;
run;
proc print data=ad_data.cursuri&an;
run;
29
Macro variabile -4

30
Crearea de cod modular cu macro proceduri
▪ Macro procedurile permit încapsularea unei scevențe de cod și
reutilizarea ei repetată. Sintaxa generală este:
%MACRO macro-nume;
text-macro;
%MEND <macro-nume>;
▪ Apelarea unei macro proceduri se face cu: %macro-nume
%MACRO exemplu;
PROC SORT DATA = VanzariFlori;
BY DESCENDING Cantitate;
PROC PRINT DATA = VanzariFlori (OBS = 5);
FORMAT DataVanzare WORDDATE18.;
TITLE 'Cele mai mari vanzari';
%MEND exemplu;
* Citirea setului de date de intrare;
DATA VanzariFlori;
INFILE "/home/nume.prenume/FloriTropicale.dat";
INPUT IDClient $ @6 DataVanzare MMDDYY10. @17
Varietate $9. Cantitate;
RUN;
* Apelarea macro procedurii;
%exemplu 31
Crearea de cod modular cu macro proceduri

32
Adăugarea de parametri la macro proceduri
▪ Parametrii permit o reutilizare sporită a codului prin posibilitatea de a
alege, la momentul rulării, setul de date și variabilele cu care se
lucrează. Sintaxa generală este:
%MACRO macro-nume (par-1= , par-2= , .... par-n= );
text-macro;
%MEND <macro-nume>;

* Macro procedura cu parametri;


%MACRO select(client=, varsort=);
PROC SORT DATA = VanzariFlori OUT = vanzari;
BY &varsort;
WHERE IDClient = "&client";
PROC PRINT DATA = vanzari;
FORMAT DataVanzare WORDDATE18.;
TITLE1 Comenzile pentru clientul cu codul &client ;
TITLE2 Sortate dupa &varsort ;
%MEND select;
*Apelarea macro procedurii;
%select(client = 356W, varsort = Cantitate)
%select(client = 240W, varsort = Varietate)
33
RUN;
Adăugarea de parametri la macro proceduri

34
Macro proceduri cu logică condițională -1
▪ Forme generale de declarații folosite pentru logică condițională în
interiorul macro procedurilor:
%IF conditie%THEN actiune;
%ELSE %IF conditie %THEN actiune;
%ELSE actiune;
%IF conditie %THEN %DO;
declaratii SAS
%END;
▪ Acestea pot fi folosite doar în interiorul unei macro proceduri.
De ce este nevoie de aceste declarații și nu de instrucțiunile
standard IF-THEN?
Instrucțiunile %IF pot conține acțiuni care nu sunt posibile în
instrucțiunile standard, cum ar fi utilizarea de secțiuni de date sau
de proceduri complete sau chiar alte macro proceduri.
Local vs. global
▪ Macro variabilele pot avea vizibilitate locală sau globală.
➢ Vizibilitatea este locală dacă au fost definite în cadrul unei macro
proceduri și se pot folosi doar la acest nivel.
➢ Vizibilitatea este globală dacă sunt definite în afara unei macro
35
proceduri și pot fi utilizate oriunde.
Macro proceduri cu logică condițională – 2
Exemplu: Combinare a logicii condiționale cu macro variabile automate.
%MACRO rapoartezilnice;
%IF &SYSDAY = Monday %THEN %DO;
PROC PRINT DATA = VanzariFlori;
FORMAT DataVanzarii WORDDATE18.;
TITLE 'Raport pentru ziua de luni: Vanzarile de flori';
%END;
%ELSE %IF &SYSDAY = Saturday %THEN %DO;
PROC MEANS DATA = VanzariFlori MEAN MIN MAX MAXDEC=2;
CLASS Varietate;
VAR Cantitate;
TITLE 'Raport pentru ziua de sambata: Rezumat vanzari
flori';
%END;
%MEND rapoartezilnice;
DATA VanzariFlori;
INFILE "/home/nume.prenume/FloriTropicale.dat";
INPUT IDClient $ @6 DataVanzare MMDDYY10. @17
Varietate $9. Cantitate;
RUN;
%rapoartezilnice
36
RUN;
Macro proceduri cu logică condițională

37
Programe orientate pe date cu CALL SYMPUT
▪ CALL SYMPUT este o rutină care preia o valoare dintr-o secțiune de
date și o alocă unei macro variabile.
▪ Sintaxa generală este:
CALL SYMPUT(”nume-macro-variabla”,valoare);
unde nume-macro-variabila, inclus între ghilimele, este numele unei
macro variabile, noi sau deja definite, iar valoare este numele unei
variabile SAS sau o valoare constantă inclusă între ghilimele.
▪ CALL SYMPUT este, de obicei, folosită cu instrucțiuni IF-THEN:
IF Varsta >= 18 THEN CALL SYMPUT(”status”, ”Adult”);
ELSE CALL SYMPUT(”status”, ”Minor”);

Atenție!!!
▪ O macro variabilă creată cu CALL SYMPUT nu va putea fi folosită în
aceeași secțiune de date, deoarece SAS nu va asigna acesteia o
valoare decât la momentul execuției.
▪ Reamintim că secțiunea de date se execută atunci când SAS
întâlnește o limită a unei alte secțiuni (DATA sau PROC) sau
instrucțiunea RUN. 38
CALL SYMPUT - exemplu
DATA VanzariFlori;
INFILE "/home/nume.prenume/FloriTropicale.dat";
INPUT IDClient $ @6 DataVanzare MMDDYY10. @17
Varietate $9. Cantitate;
RUN;
PROC SORT DATA = VanzariFlori;
BY DESCENDING Cantitate;
RUN;
* Identificarea celei mai mari comenzi și transmiterea
codului clientului catre o macro variabila;
DATA _NULL_;
SET VanzariFlori;
IF _N_ = 1 THEN CALL SYMPUT( "clientselectat", IDClient);
ELSE STOP;
RUN;
PROC PRINT DATA = VanzariFlori;
WHERE IDClient = "&clientselectat";
FORMAT DataVanzare WORDDATE18.;
TITLE "Clientul &clientselectat cu cea mai mare comanda";
RUN;
39
CALL SYMPUT - exemplu

40
Întrebări recapitulative -1
1. Plecând de la instrucțiunea ARRAY de mai jos, identificați referința
elementului q50 al masivului:
ARRAY elemente{3,25} q1-q75;
a. elemente {q50}
b. elemente {1,50}
c. elemente {2,25}
d. elemente {3,0}

2. Care dintre următoarele referințe la o bibliotecă este corectă?


a. 2010Date
b. date/2010
c. Date_2012
d. 1_sau_a

41
Întrebări recapitulative -2
3. Următorul program SAS este trimis spre execuție:
PROC FORMAT;
VALUE PUNCTAJ 1 - 50 = “ADMIS”;
51 - 100 = “RESPINS”;
RUN;
Care dintre următoarele proceduri PRINT aplică în mod corect
formatul?
a. PROC PRINT DATA = exemplu;
VAR test; FORMAT test PUNCTAJ; RUN;
b. PROC PRINT DATA = exemplu;
VAR TEST; FORMAT test PUNCTAJ.; RUN;
c. PROC PRINT DATA = exemplu FORMAT = PUNCTAJ;
VAR test; RUN;
d. PROC PRINT DATA = exemplu FORMAT = PUNCTAJ.;
VAR test; RUN;

42
Întrebări recapitulative -3
4. Plecăm de la următoarea eroare apărută în SAS log:
44 data WORK.OUTPUT;
45 set SASHELP.CLASS;
46 BMI=(Greutate*703)/Inaltime**2;
47 where bmi ge 20;
ERROR: Variable bmi is not on file SASHELP.CLASS.
48 run;
Ce schimbare în program va corecta eroarea?
a. Adăugarea opțiunii (Keep=BMI) în instrucțiunea SET
b. Schimbarea ** in formula BMI cu un singur character *
c. Schimbarea bmi cu BMI în instrucțiunea WHERE
d. Înlocuirea instrucțiunii WHERE cu o instrucțiune IF

5. Identificați procedura prin care pot fi vizualizate etichetele și


formatele permanente asociate unui set de date:
a. PROC PRINT
b. PROC FORMAT
c. PROC CONTENTS
d. PROC UNIVARIATE 43
Întrebări recapitulative -4
6. Care dintre următoarele secvețe de cod crează în mod corect o
variabilă macro numită regiune și îi atribuie o valoare bazată pe
valorarea variabilei setului de date locatie?
a. data new; c. data new;
set sasuser.all; set sasuser.all;
if locatie='Boston' then do; if locatie='Boston' then do;
call symput('regiune', 'East'); call symput(regiune, "East");
end; end;
else do; else
call symput('regiune', 'West'); call symput(regiune, "West");
end; end;
run; run;

b. data new; d. data new;


set sasuser.all; set sasuser.all;
if locatie='Boston' then do; if locatie='Boston' then do;
%let regiune=East; symput(regiune, East);
end; end;
else else
%let regiune=West; symput(regiune, West);
end; end; 44
run;
Întrebări recapitulative -5
7. Avem ca intrare două seturi de date referitoare la manageri și la angajații aflați
în subordinea acestora. Ce raport se poate realiza pe baza setului de date
rezultat din următoarea fuziune?
DATA rezultat;
MERGE manageri (in=M)angajati (in=A);
BY IDAngajat;
IF M=0 and A=1;
RUN;

45

S-ar putea să vă placă și