O SQLite é uma biblioteca embutida em um processo único que é autônomo, não necessita de servidor e exige zero de configuração. O código é de domínio público e seu uso é gratuito em qualquer tipo de utilização. Trata-se de um sistema SQL completo, capaz de utilizar múltiplas tabelas, índices, gatilhos e visões. Ele funciona, virtualmente, em qualquer plataforme (incluindo móveis) e pesa cerca de 600KB.
##Objetivos
Ao fim deste laboratório, você deverá ser capaz de:
Conectar-se a um banco de dados do tipo SQLite utilizando o R como interface; Explorar quais são as tabelas disponíveis no referido banco de dados; Identificar quais são as colunas de uma dada tabela existente no banco de dados; Realizar pesquisas simples; Extrair registros do banco de dados e armazená-las em objetos do R; Realizar algumas pesquisas complexas, utilizando WHERE, INNER JOIN. Criar novas tabelas no banco de dados. Fonte do problema: Estes dados são de uma iniciativa de publicidade de desempenho de alunos e professores nas Universidades Americanas. A UW-Madison disponibilizou os seus dados online (no Office of the Registrar: https://registrar.wisc.edu/), e alguém trouxe os dados para uma competição no Kaggle (https://www.kaggle.com/Madgrades/uw-madison-courses). Nesta atividades, examinaremos disciplinas oferecidas no assunto de Estatística pela referida Universidade. O esquema do banco de dados é apresentado na figura abaixo.
##Observações
Esta tarefa não deve ser realizada no site jupyter.ime.unicamp.br ; Você deve realizar o download dos dados para o computador que estiver utilizando e, então, iniciar a atividade; Recomenda-se a utilização dos seguintes pacotes: RSQLite Toda a atividade deve ser realizada utilizando-se apenas de SQLite (i.e., não utilize dbplyr);
##Atividade
Baixe o arquivo database.sqlite3. Conecte-se a ele usando o pacote RSQLite, armazenando a conexão em uma variável conn.
# Instalar pacote se necessário# install.packages("RSQLite")# Carregar o pacotelibrary(RSQLite)# Conectar ao banco de dadosconn <-dbConnect(RSQLite::SQLite(), "database.sqlite3")# Verificar se a conexão foi bem sucedidadbListTables(conn)
Quem são e quantos são os professores que lecionaram disciplinas cujo tópico era estatística (subjects.abbreviation=‘STAT’);
# Query corrigida baseada na estrutura realquery_professores <-"SELECT DISTINCT i.name, COUNT(DISTINCT co.uuid) as num_disciplinasFROM instructors iINNER JOIN teachings t ON i.id = t.instructor_idINNER JOIN sections s ON t.section_uuid = s.uuidINNER JOIN course_offerings co ON s.course_offering_uuid = co.uuidINNER JOIN subject_memberships sm ON co.uuid = sm.course_offering_uuidINNER JOIN subjects sub ON sm.subject_code = sub.codeWHERE sub.abbreviation = 'STAT'GROUP BY i.nameORDER BY num_disciplinas DESC;"professores_stat <-dbGetQuery(conn, query_professores)
O GPA americano é definido numa escala de 0 a 4, em que A = 4, AB = 3.5, B = 3, BC = 2.5, C = 2, D = 1 e F = 0. Determinando a nota média de cada oferecimento pela ponderação da quantidade de alunos em cada extrato com os valores numéricos de cada conceito, indique (no que se referente a disciplinas no assunto de estatística):
3.1. Quem é o professor mais difícil? 3.2. Quem é o professor mais fácil?
# Query para dados dos professoresquery_gpa_professores <-"SELECT i.name as professor, co.name as disciplina, -- Converter contagens de texto para números CAST(gd.a_count AS INTEGER) as a_count, CAST(gd.ab_count AS INTEGER) as ab_count, CAST(gd.b_count AS INTEGER) as b_count, CAST(gd.bc_count AS INTEGER) as bc_count, CAST(gd.c_count AS INTEGER) as c_count, CAST(gd.d_count AS INTEGER) as d_count, CAST(gd.f_count AS INTEGER) as f_countFROM grade_distributions gdINNER JOIN course_offerings co ON gd.course_offering_uuid = co.uuidINNER JOIN sections s ON co.uuid = s.course_offering_uuidINNER JOIN teachings t ON s.uuid = t.section_uuidINNER JOIN instructors i ON t.instructor_id = i.idINNER JOIN subject_memberships sm ON co.uuid = sm.course_offering_uuidINNER JOIN subjects sub ON sm.subject_code = sub.codeWHERE sub.abbreviation = 'STAT';"dados_gpa <-dbGetQuery(conn, query_gpa_professores)# Função para calcular GPA a partir da estrutura de colunas separadascalcular_gpa_from_columns <-function(a, ab, b, bc, c, d, f) {# Valores do GPA para cada conceito valores_gpa <-c(A =4.0, AB =3.5, B =3.0, BC =2.5, C =2.0, D =1.0, F =0.0)# Calcular totais total_a <-sum(a, na.rm =TRUE) total_ab <-sum(ab, na.rm =TRUE) total_b <-sum(b, na.rm =TRUE) total_bc <-sum(bc, na.rm =TRUE) total_c <-sum(c, na.rm =TRUE) total_d <-sum(d, na.rm =TRUE) total_f <-sum(f, na.rm =TRUE) total_alunos <- total_a + total_ab + total_b + total_bc + total_c + total_d + total_fif (total_alunos ==0) return(NA)# Calcular GPA ponderado gpa_ponderado <- (total_a *4.0+ total_ab *3.5+ total_b *3.0+ total_bc *2.5+ total_c *2.0+ total_d *1.0+ total_f *0.0) / total_alunosreturn(gpa_ponderado)}# Calcular GPA por professorgpa_por_professor <-aggregate(cbind(a_count, ab_count, b_count, bc_count, c_count, d_count, f_count) ~ professor, dados_gpa, FUN =function(x) sum(as.numeric(x), na.rm =TRUE))# Aplicar função de cálculo de GPAgpa_por_professor$gpa_medio <-mapply(calcular_gpa_from_columns, gpa_por_professor$a_count, gpa_por_professor$ab_count, gpa_por_professor$b_count, gpa_por_professor$bc_count, gpa_por_professor$c_count, gpa_por_professor$d_count, gpa_por_professor$f_count)# Remover NAs e ordenarresultado_professores <- gpa_por_professor[!is.na(gpa_por_professor$gpa_medio), c("professor", "gpa_medio")]resultado_professores <- resultado_professores[order(resultado_professores$gpa_medio), ]cat("Professor mais difícil (menor GPA):", resultado_professores$professor[1], "- GPA:", round(resultado_professores$gpa_medio[1], 3), "\n")
Professor mais difícil (menor GPA): JAMES D KUELBS - GPA: 2.608
Professor mais fácil (maior GPA): YAJUAN SI - GPA: 4
3.3. Qual é a disciplina mais difícil? 3.4. Qual é a disciplina mais fácil?
# Query para dados das disciplinasquery_gpa_disciplinas <-"SELECT co.name as disciplina, CAST(gd.a_count AS INTEGER) as a_count, CAST(gd.ab_count AS INTEGER) as ab_count, CAST(gd.b_count AS INTEGER) as b_count, CAST(gd.bc_count AS INTEGER) as bc_count, CAST(gd.c_count AS INTEGER) as c_count, CAST(gd.d_count AS INTEGER) as d_count, CAST(gd.f_count AS INTEGER) as f_countFROM grade_distributions gdINNER JOIN course_offerings co ON gd.course_offering_uuid = co.uuidINNER JOIN subject_memberships sm ON co.uuid = sm.course_offering_uuidINNER JOIN subjects sub ON sm.subject_code = sub.codeWHERE sub.abbreviation = 'STAT';"dados_disciplinas <-dbGetQuery(conn, query_gpa_disciplinas)# Calcular GPA por disciplinagpa_por_disciplina <-aggregate(cbind(a_count, ab_count, b_count, bc_count, c_count, d_count, f_count) ~ disciplina, dados_disciplinas, FUN =function(x) sum(as.numeric(x), na.rm =TRUE))# Aplicar função de cálculo de GPAgpa_por_disciplina$gpa_medio <-mapply(calcular_gpa_from_columns, gpa_por_disciplina$a_count, gpa_por_disciplina$ab_count, gpa_por_disciplina$b_count, gpa_por_disciplina$bc_count, gpa_por_disciplina$c_count, gpa_por_disciplina$d_count, gpa_por_disciplina$f_count)# Remover NAs e ordenarresultado_disciplinas <- gpa_por_disciplina[!is.na(gpa_por_disciplina$gpa_medio), c("disciplina", "gpa_medio")]resultado_disciplinas <- resultado_disciplinas[order(resultado_disciplinas$gpa_medio), ]cat("Disciplina mais difícil (menor GPA):", resultado_disciplinas$disciplina[1], "- GPA:", round(resultado_disciplinas$gpa_medio[1], 3), "\n")
Disciplina mais difícil (menor GPA): Intro-Theory of Probability - GPA: 2.886