Post on 08-Jul-2020
ICE-BICE-BICE-BICE-BICE-BICE-BICE-BICE-BICE-B
15 - Organizar Dados15 - Organizar Dados15 - Organizar Dados15 - Organizar Dados15 - Organizar Dados15 - Organizar Dados15 - Organizar Dados15 - Organizar Dados15 - Organizar Dados
Ludwig Krippahl
1
Organizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar Dados
Resumo■ Organização de dados:• Ficheiros, listas, matrizes e dicionários
■ Ler e representar dados (gráficos)■ Dicionário como relação de atributos■ Vector de dicionários como uma tabela■ Selecção de campos e cruzamento de tabelas
2
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
3
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
Exemplo: temperaturas por país■ PRT.csv ■ DEU.csvyear,data
1901,14.236396789550781
1902,14.387377738952637
1903,14.560417175292969
1904,14.721814155578613
1905,14.297182083129883
...
year,data
1901,7.781550407409668
1902,7.262444972991943
1903,8.382242202758789
1904,8.436717987060547
1905,8.02903938293457
...
■ Podemos obter estes valores do World Bank neste URL:http://climatedataapi.worldbank.org/climateweb/rest/v1/country/cru/tas/year/[COD].csv
■ Ou então podemos tê-los já em ficheiros no disco.■ Vamos considerar ambas as possibilidades:• Carregar um lote de países para um dicionário de tabelas• De ficheiro ou do servidor
4
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
Exemplo: temperaturas por país■ Decompor o problema:• Um país, uma tabela, de ficheiro ou servidor• Vários países, um dicionário, de ficheiro ou servidor
def load_temperatures(file_name, online=False): """Return numpy array with years and temperatures for given name (code.csv) If online load from server""" def load_countries(codes, online=False): """Return dictionary with one table per country code Loads tables from file, or server if online is True"""
5
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
import numpy as np from requests import get BASE_URL = 'http://climatedataapi.worldbank.org/'+\ 'climateweb/rest/v1/country/cru/tas/year/' def load_temperatures(file_name, online=False): """Return numpy array with years and temperatures for given name (code.csv) If online load from server""" if online: response = get(BASE_URL+file_name) lines = response.text.strip().split('\n') else: lines = open(file_name).readlines() table = [] for line in lines[1:]: year, temp = line.split(',') table.append( (int(year),float(temp))) return np.array(table)
6
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
def load_temperatures(file_name, online=False): """Return numpy array with years and temperatures for given name (code.csv) If online load from server""" ...
In : load_temperatures('PRT.csv',True) Out: array([[1901. , 14.23639679], [1902. , 14.38737774], [1903. , 14.56041718], [1904. , 14.72181416],
■ Se temos o ficheiro PRT.csv
In : load_temperatures('PRT.csv') Out: array([[1901. , 14.23639679], [1902. , 14.38737774], [1903. , 14.56041718], [1904. , 14.72181416],
7
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
def load_countries(codes, online=False): """Return dictionary with one table per country code Loads tables from file, or server if online is True""" countries = {} for code in codes: countries[code] = load_temperatures(code+'.csv', online) return countries
In : countries = load_countries(['PRT','ESP','FRA'],True) Out: {'PRT': array([[1901. , 14.23639679],...]), 'ESP': array([[1901. , 12.61713982],...]), 'FRA': array([[1901. , 9.74886513],...])}
■ Ou omitindo (ou False) o segundo argumento se tivermos osficheiros na pasta.
8
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
■ Já temos os dados organizados, vamos fazer o gráfico■ Generalizar:• Podemos escolher o intervalo de anos• Podemos escolher os países (daqueles que há no dicionário)
def plot_years(first,last,codes,countries): """from countries dictionary, plot countries given in codes in specified interval""" plt.figure(figsize=(10,5)) for code in codes: table = countries[code] years = np.logical_and(table[:,0]>=first, table[:,0]<=last) data = table[years,:] plt.plot(data[:,0],data[:,1],label=code) plt.legend() plt.show()
In : plot_years(1960,2000,['PRT','ESP','FRA'],countries)
9
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
■ Já temos os dados organizados, vamos fazer o gráfico
In : plot_years(1960,2000,['PRT','ESP','FRA'],countries)
10
Tabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas NuméricasTabelas Numéricas
Exemplo: temperaturas por país■ Funções para ler os dados e organizá-los• Dicionário com código do país e matriz
■ Depois processamos os dados organizados• Exemplo: função para fazer gráfico a partir do dicionário
Esquema genérico:■ Guardar os dados num formato prático para processamento■ Processar os dados nesse formato
11
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
12
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
Exemplo (antiquado): Clube de vídeofilmes.tsv: id_filme, tipo, titulo, classificacao
101 Sexto Sentido suspense drama maiores de 12
102 Regresso ao Futuro comedia aventura maiores de 6
103 Monstros e Cia. animacao maiores de 4
...
clientes.tsv:id_cliente, nome, morada, c_credito
101 Artur Meireles Rua da Paz, 20 123412341234123401
102 Joana Fonseca Rua da Guerra, 123 4123412341234123402
103 Artur Lopes da Silva Av.Liberdade, 202 123412341234123403
...
alugueres.tsv:id_aluguer, id_filme, id_cliente, data_aluguer, data_entrega
1001 109 102 05/10/14 05/11/14
1002 106 101 05/12/14 NULL
1003 102 107 05/13/14 NULL
1004 104 102 05/11/14 05/12/14
13
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
Exemplo (antiquado): Clube de vídeo■ Cada tabela tem campos diferentes• Filmes: id_filme, tipo, titulo, classificacao• Clientes: id_cliente, nome, morada, c_credito
• Alugueres: id_aluguer, id_filme, id_cliente, data_aluguer, data_entrega
■ Relações 1 para 1:• Não é prático guardar relações de um para vários na mesma tabela
• nome, morada e cartão de crédito funciona• nome de cada cliente e filmes alugados já não é prático
■ Para fazer "perguntas" temos de cruzar tabelas• Nome dos filmes alugados e data de entrega• Nome da pessoa e filme que alugou• ...
14
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
Exemplo (antiquado): Clube de vídeo■ Ler as tabelas para um dicionário• Cada tabela é uma lista de dicionários com os campos e valores• A nossa "base de dados" será um dicionário com todas as tabelas• Vamos fazer uma funçao genérica, que sirva para qualquer tabela
■ Processar os dados• Juntar duas tabelas por um campo (e.g. identificador)• Seleccionar colunas da tabela (os campos dos registos)• Mostrar uma tabela (print)
15
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Ler uma tabela para uma lista de dicionários
def load_table(file_name,fields): "Read file into list of dictionaries with given fields" lines = open(file_name).readlines() table = [] for line in lines: cells = line.strip().split('\t') record = {} for ix in range(len(fields)): record[fields[ix]]=cells[ix] table.append( record ) return table
In : load_table('filmes.tsv',['id_filme','titulo','tipo','classificacao']) Out: [{'classificacao': 'maiores de 12','id_filme': '101', 'tipo': 'suspense drama', 'titulo': 'Sexto Sentido'}, {'classificacao': 'maiores de 6','id_filme': '102', 'tipo': 'comedia aventura', 'titulo': 'Regresso ao Futuro'}, ...]
16
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Ler uma tabela para uma lista de dicionários
def load_table(file_name,fields): "Read file into list of dictionaries with given fields" lines = open(file_name).readlines() table = [] for line in lines: cells = line.strip().split('\t') record = {} for ix in range(len(fields)): record[fields[ix]]=cells[ix] table.append( record ) return table
In : load_table('clientes.tsv',['id_cliente','nome','morada','c_credito']) Out: [{'c_credito': '123412341234123401', 'id_cliente': '101', 'morada': 'Rua da Paz, 20', 'nome': 'Artur Meireles'}, {'c_credito': '123412341234123402', 'id_cliente': '102', 'morada': 'Rua da Guerra, 1234', 'nome': 'Joana Fonseca '}, ...]
17
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Ler uma tabela para uma lista de dicionários
def load_table(file_name,fields): "Read file into list of dictionaries with given fields" lines = open(file_name).readlines() table = [] for line in lines: cells = line.strip().split('\t') record = {} for ix in range(len(fields)): record[fields[ix]]=cells[ix] table.append( record ) return table
In : load_table('alugueres.tsv',['id_aluguer', 'id_filme', 'id_cliente', 'data_aluguer', 'data_entrega']) Out: [{'id_aluguer': '1001', 'id_filme': '109', 'id_cliente': '102', 'data_aluguer': '05/10/14','data_entrega': '05/11/14'}, {'id_aluguer': '1002', 'id_filme': '106', 'id_cliente': '101', 'data_aluguer': '05/12/14', 'data_entrega': 'NULL'},... ]
18
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Ler as tabelas para um dicionário de tabelas ("base de dados")• A partir de um dicionário com o esquema das tabelas
def load_db(table_defs): """Reads all tables into a dictionary Argument table_defs is dictionary with table name and dictionary with file name and fields """ db = {} for table_name in table_defs: table = table_defs[table_name] db[table_name] = load_table(table['file'],table['fields']) return db table_defs = {'filmes':{'file':'filmes.tsv', 'fields':['id_filme','titulo','tipo','classificacao']}, 'clientes':{'file':'clientes.tsv', 'fields':['id_cliente','nome','morada','c_credito']}, 'alugueres':{'file':'alugueres.tsv', 'fields':['id_aluguer','id_filme','id_cliente', 'data_aluguer','data_entrega']}, }
19
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Ler as tabelas para um dicionário de tabelas ("base de dados")• A partir de um dicionário com o esquema das tabelas
def load_db(tables): """Reads all tables into a dictionary Argument is dictionary describing tables""" db = {} for table_name in tables: table = tables[table_name] db[table_name] = load_table(table['file'],table['fields']) return db
In : db = load_db(table_defs) In : db['filmes'] Out: [{'classificacao': 'maiores de 12', 'id_filme': '101', 'tipo': 'Sexto Sentido', 'titulo': 'suspense drama'}, {'classificacao': 'maiores de 6', 'id_filme': '102', 'tipo': 'Regresso ao Futuro', 'titulo': 'comedia aventura'}, ...]
20
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Consultas cruzando informação• E.g. Quais os títulos dos filmes alugados e quando foram alugados?
■ Precisamos de cruzar os alugueres com os filmesfilmes: id_filme, tipo, titulo, classificacao
101 Sexto Sentido suspense drama maiores de 12
102 Regresso ao Futuro comedia aventura maiores de 6
...
alugueres:id_aluguer, id_filme, id_cliente, data_aluguer, data_entrega
1001 109 102 05/10/14 05/11/14
1002 106 101 05/12/14 NULL
...
21
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Consultas cruzando informação• E.g. Quais os títulos dos filmes alugados e quando foram alugados?
■ Caso geral:• Dadas duas tabelas e um campo em ambas, seleccionar pares que partilham o
mesmo valor nesse campo
• E.g. pares aluguer, filme com o mesmo id_filme
• (todos os pares porque um filme pode ter sido alugado várias vezes)
Filme:
106 Elizabeth drama historico maiores de 12
Aluguer:
1002 106 101 05/12/14 NULL
Junção:
106 Elizabeth drama historico maiores de 12 1002 101 05/12/14 NULL
22
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Decompor o problema:• Dado um registo, uma tabela e um campo, emparelhar com todos os registos com
o mesmo valor nesse campo
• Fazer isto para cada registo de uma tabela com todos da outra que tenham omesmo valor no campo
Filme:
106 Elizabeth drama historico maiores de 12
Aluguer:
1002 106 101 05/12/14 NULL
Junção:
106 Elizabeth drama historico maiores de 12 1002 101 05/12/14 NULL
23
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Juntar um registo com todos os que partilhem esse campo
def join_rec(rec,table,field): "join record to all in table sharing same value in field" new_table=[] for other_rec in table: if rec[field] == other_rec[field]: new_rec={} for f in rec: new_rec[f] = rec[f] for f in other_rec: new_rec[f] = other_rec[f] new_table.append(new_rec) return new_table
In : filme = db['filmes'][5] In : filme Out: {'classificacao': 'maiores de 12', 'id_filme': '106', 'tipo': 'Elizabeth', 'titulo': 'drama historico'} In : join_rec(filme,db['alugueres'],'id_filme') Out: [{'classificacao': 'maiores de 12', 'data_aluguer': '05/12/14', 'data_entrega': 'NULL', 'id_aluguer': '1002', 'id_cliente': '101', 'id_filme': '106', 'tipo': 'Elizabeth', 'titulo': 'drama historico'}]
24
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Alugueres da Joana Fonseca
1001 109 102 05/10/14 05/11/14
1002 106 101 05/12/14 NULL
1003 102 107 05/13/14 NULL
1004 104 102 05/11/14 05/12/14
In : cliente = db['clientes'][1] In : cliente Out: {'c_credito': '123412341234123402', 'id_cliente': '102', 'morada': 'Rua da Guerra, 1234', 'nome': 'Joana Fonseca '} In : join_rec(cliente,db['alugueres'],'id_cliente') Out: [{'c_credito': '123412341234123402', 'data_aluguer': '05/10/14', 'data_entrega': '05/11/14', 'id_aluguer': '1001', 'id_cliente': '102', 'id_filme': '109', 'morada': 'Rua da Guerra, 1234', 'nome': 'Joana Fonseca '}, {'c_credito': '123412341234123402', 'data_aluguer': '05/11/14', 'data_entrega': '05/12/14', 'id_aluguer': '1004', 'id_cliente': '102', 'id_filme': '104', 'morada': 'Rua da Guerra, 1234', 'nome': 'Joana Fonseca '}]
25
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Juntar duas tabelas por um campo partilhado
def join(table1, table2, field): "Return all pairs of records with shared field" new_table = [] for rec in table1: new_table.extend(join_rec(rec,table2,field)) return new_table
In : filmes_alug = join(db['filmes'],db['alugueres'],'id_filme') In : filmes_alug [{'classificacao': 'maiores de 6', 'data_aluguer': '05/13/14', 'data_entrega': 'NULL', 'id_aluguer': '1003', 'id_cliente': '107', 'id_filme': '102','tipo': 'comedia aventura','titulo': 'Regresso ao Futuro'}, {'classificacao': 'maiores de 16','data_aluguer': '05/11/14', 'data_entrega': '05/12/14', 'id_aluguer': '1004', 'id_cliente': '102', 'id_filme': '104','tipo': 'ficcao-cientifica terror','titulo': 'Alien'}, {'classificacao': 'maiores de 12', 'data_aluguer': '05/12/14', 'data_entrega': 'NULL', 'id_aluguer': '1002', 'id_cliente': '101', 'id_filme': '106', 'tipo': 'drama historico', 'titulo': 'Elizabeth'}, {'classificacao': 'maiores de 4', 'data_aluguer': '05/10/14', 'data_entrega': '05/11/14','id_aluguer': '1001', 'id_cliente': '102', 'id_filme': '109', 'tipo': 'animacao', 'titulo': 'Idade do Gelo'}]
26
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Juntar mais tabelas
In : film_client_alug = join(filmes_alug,db['clientes'],'id_cliente') In : film_client_alug Out[27]: [{'c_credito': '123412341234123407', 'classificacao': 'maiores de 6', 'data_aluguer': '05/13/14', 'data_entrega': 'NULL', 'id_aluguer': '1003', 'id_cliente': '107', 'id_filme': '102', 'morada': 'Boliqueime', 'nome': 'Cavaco Silva', 'tipo': 'comedia aventura', 'titulo': 'Regresso ao Futuro'}, {'c_credito': '123412341234123402', 'classificacao': 'maiores de 16', 'data_aluguer': '05/11/14', 'data_entrega': '05/12/14', 'id_aluguer': '1004', 'id_cliente': '102', 'id_filme': '104', 'morada': 'Rua da Guerra, 1234', 'nome': 'Joana Fonseca ', 'tipo': 'ficcao-cientifica terror', 'titulo': 'Alien'}, {'c_credito': '123412341234123401', 'classificacao': 'maiores de 12', 'data_aluguer': '05/12/14', 'data_entrega': 'NULL', 'id_aluguer': '1002', 'id_cliente': '101', 'id_filme': '106', 'morada': 'Rua da Paz, 20', 'nome': 'Artur Meireles', 'tipo': 'drama historico', 'titulo': 'Elizabeth'}, ...]
27
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Confuso, com informação a mais. Vamos seleccionar campos
def select(table, fields): "Return table with selected fields" new_table = [] for rec in table: new_rec = {} for f in fields: new_rec[f] = rec[f] new_table.append(new_rec) return new_table
In : filmes_alug = join(db['filmes'],db['alugueres'],'id_filme') In : film_client_alug = join(filmes_alug,db['clientes'],'id_cliente') In : film_client = select(film_client_alug,['nome','titulo']) In : film_client Out: [{'nome': 'Cavaco Silva', 'titulo': 'Regresso ao Futuro'}, {'nome': 'Joana Fonseca ', 'titulo': 'Alien'}, {'nome': 'Artur Meireles', 'titulo': 'Elizabeth'}, {'nome': 'Joana Fonseca ', 'titulo': 'Idade do Gelo'}]
28
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Imprimir mais bonito
def print_table(table, separator = '\t'): "Prints a table using separator" fields = table[0].keys() print(separator.join(fields)) for rec in table: vals = [str(rec[f]) for f in fields] print(separator.join(vals))
In : print_table(film_client) nome titulo Cavaco Silva Regresso ao Futuro Joana Fonseca Alien Artur Meireles Elizabeth Joana Fonseca Idade do Gelo
29
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Nota: list comprehension
In : some_list = [] for x in range(10): some_list.append(x) In : some_list Out: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] In : some_list = [x for x in range(10)] In : some_list Out: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
30
Tabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas MistasTabelas Mistas
■ Imprimir mais bonito
def print_table(table, separator = '\t'): "Prints a table using separator" fields = table[0].keys() print(separator.join(fields)) for rec in table: vals = [str(rec[f]) for f in fields] print(separator.join(vals))
In : print_table(film_client,';') nome;titulo Cavaco Silva;Regresso ao Futuro Joana Fonseca ;Alien Artur Meireles;Elizabeth Joana Fonseca ;Idade do Gelo
31
Organizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar DadosOrganizar Dados
ResumoResumoResumoResumoResumoResumoResumoResumoResumo
32
ResumoResumoResumoResumoResumoResumoResumoResumoResumo
Organizar Dados■ Revisões• Listas e dicionários• Leitura de ficheiros e recursos remotos• Gráficos, matrizes Numpy
■ Ideia de base de dados:• Conjunto de tabelas com registos, relacionando diferentes campos
■ Cruzar informação em tabelas diferentes• (Vamos ver isto melhor na próxima semana)
Leitura adicional:■ Capítulo 15, quando tiver pronto (sem promessas)