Você está na página 1de 29

INTRODUÇÃO À MINERAÇÃO DE DADOS COM O SOFTWARE R

Jonas Liebl
jonasliebl@outlook.com
(41) 99974-0533

O que é o Software R

O R é um software livre para computação estatística e gráficos. Além de ser amplamente utilizado no meio acadêmico para cálculos estatísticos, vem ganhando
notoriedade em mineração de dados, tornando-se uma das ferramentas mais usadas por profissionais conhecidos como “cientistas de dados”. A principal
página na Internet através da qual se pode baixar o software e iniciar o seu aprendizado é a https://www.r-project.org.

O R se destaca como uma ferramenta estatística e esse estigma já é suficiente para desestimular o seu uso por profissionais de outras áreas. Ocorre que os
seus comandos e a elevada capacidade de processamento podem facilitar a execução de atividades completamente distintas do segmento estatístico, sendo
úteis inclusive para uso no ambiente doméstico de uma família. Este trabalho se propõe a apresentar um ensaio de introdução à mineração de dados fazendo
uso das suas funções mais básicas descritas no “Short R Reference Card” (https://cran.r-project.org/doc/contrib/Short-refcard.pdf). Embora o guia de referência
completo tenha mais de 3.500 páginas e exija um longo percurso de aprendizado, nada impede que o usuário iniciante utilize essa ferramenta a partir de
algumas funções mais simples e atinja excelentes resultados.

Contextualização do problema

Como motivador para esta introdução à mineração de dados, vamos trazer um problema hipotético da área bancária relativo a uma suspeita de que há gerentes
favorecendo parentes e amigos com financiamentos subsidiados, mal formalizados e sem avaliação de risco de crédito. Ocorrências dessa natureza podem
prejudicar o retorno dos financiamentos pela possibilidade de inadimplência e pela fragilidade ou ausência de garantias. Subsídios concedidos a quem não faz
jus podem afetar a imagem da instituição quando o assunto vem à tona na mídia. Esse é um tema particularmente interessante para auditores, contadores,
administradores e profissionais da área de controle.

O primeiro teste que podemos fazer é o confronto do sobrenome dos gerentes concessores com o sobrenome dos devedores dos respectivos contratos,
através do qual obteremos uma amostra de concessões de financiamentos que deverão ser examinadas de forma aprofundada. Para isso, precisamos de duas
bases de dados, a primeira oriunda da área de recursos humanos e a segunda, do gestor da área de crédito. Obviamente, vamos trabalhar com bases fictícias,
criadas apenas para os fins didáticos a que se propõe.

A base “gerentes.txt” contém o nome dos gerentes da instituição e o código pelo qual são identificados nas bases dos sistemas corporativos. Esse código
normalmente é a matrícula funcional ou o número do registro do empregado na empresa. Os nomes foram compostos aleatoriamente.

A “baseinad.txt” contém dados dos contratos inadimplentes. É uma base totalmente fictícia com nomes também compostos aleatoriamente e número do
contrato gerado através de função de números aleatórios.
Ambas as bases estão disponíveis para download nos seguintes endereços:
http://www.angelfire.com/un/cde/gerentes.txt
http://www.angelfire.com/un/cde/baseinad.txt

Iniciando o R

Uma vez instalado no computador, o ícone do R fica disponível na área de trabalho para ser acionado sempre que necessário. No notebook que faço uso,
esse ícone está identificado como “R x64 3.2.1”, mas pode variar dependendo da versão do software.

Duplo-clique sobre ele:

Uma questão importante que merece a nossa atenção é a informação que aparece no console assim que ele é aberto: o “R é um software livre e vem sem
GARANTIA ALGUMA”. Obviamente, essa garantia não existe porque o R é fruto de um ambiente colaborativo e é totalmente gratuito para o usuário. A hipótese
de eventual bug não pode ser descartada, entretanto, dependendo do que estamos processando, é possível estabelecer um controle de qualidade que assegura
a total confiabilidade. Vamos discorrer sobre isso ao longo deste ensaio.
Outra coisa que precisamos ver logo ao início é para qual pasta do nosso computador o R está direcionando o salvamento dos arquivos:

getwd()
[1] "C:/Users/Jonas/Documents"

Neste momento, ele está apontando para os “Documentos” do meu usuário. Como gostaríamos de direcionar os arquivos deste ensaio para uma pasta
específica, vamos criá-la no gerenciador do Windows: C:\ENSAIO_R. Feito isso, voltamos ao console do R e, em Arquivo / Mudar dir, selecionamos a pasta
de interesse:

Extração de sobrenomes

Vamos armazenar o nome “Rubens Nakazato Yoshida Neto” na variável de memória “nome”. Há várias maneiras de armazenar informações ou atribuir valores
a uma variável, mas nós vamos utilizar a forma mais usual que consiste em alinhar as variáveis de memória à esquerda usando uma seta como operador:

nome<-"Rubens Nakazato Yoshida Neto"

Essa disposição das variáveis de memória é particularmente interessante quando desenvolvemos scripts. O fato de estarem sempre à esquerda facilita muito
a localização das variáveis criadas ao longo do conjunto de instruções.
O sinal de igual também funciona para o armazenamento de informações ou atribuição de valor, mas precisamos de alguma atenção ao usá-lo pois pode
assumir diferentes funções dependendo da sua posição em determinado contexto. Neste ensaio, vamos adotar a prática acadêmica reiteradamente observada
que dá preferência à seta.

Para ver o conteúdo de uma variável de memória, basta digitar o seu nome e dar “enter”:

nome
[1] "Rubens Nakazato Yoshida Neto"

O R diferencia os comandos e os resultados pelas cores vermelha e azul, respectivamente. Além disso, as linhas de resultado são numeradas sequencialmente.
Neste caso, a linha [1] mostra o conteúdo da variável de memória “nome”.

Como mencionamos na contextualização do problema, nós pretendemos buscar indícios de parentesco entre gerentes concessores e devedores de
financiamentos mediante tratamento de sobrenomes. Na maioria dos casos, o sobrenome corresponde ao último bloco de caracteres de um conjunto de blocos
que compõem um nome, os quais se encontram separados por espaços. No nome em questão, temos um conjunto de quatro blocos, porém o último não
corresponde a sobrenome. É um caso de exceção. Vamos descobrir, passo-a-passo, como isolar o sobrenome usando funções do R.

A “strsplit” é particularmente interessante para isso. Ela permite dividir os elementos do conjunto de caracteres armazenados em “nome” usando o espaço
como separador:

strsplit(nome," ")
[[1]]
[1] "Rubens" "Nakazato" "Yoshida" "Neto"

O nome da variável de memória e o espaço foram utilizados como argumentos da função. O resultado, apresentado na linha [1], mostra os quatro blocos que
compõem o nome devidamente separados e isolados por aspas. Desejando isolar o último bloco, precisamos acrescentar o respectivo índice [4] ao comando:

strsplit(nome," ")[4]
[[1]]
NULL

Ops!!! Algo não deu certo!!! Embora o strsplit(nome,” “) tenha mostrado os quatro blocos que compõem o nome devidamente separados, o índice [4], adicionado
ao comando, trouxe como resultado NULL. O esperado seria “Neto”. Para resolver a questão, precisamos adicionar uma outra função a esse conjunto de
instruções: “unlist”. Essa função é que de fato permite o reconhecimento dos quatro blocos que foram separados pela “strsplit”:

unlist(strsplit(nome," "))[4]
[1] "Neto"
O “Neto” não corresponde ao sobrenome. Trata-se de uma exceção, a exemplo de outras como “Filho”, “Júnior”, “Sobrinho”, etc. Para obter o sobrenome do
nome em questão, precisamos utilizar o [3] como índice:

unlist(strsplit(nome," "))[3]
[1] "Yoshida"

Nós definimos os índices [4] e [3] a partir da observação do conteúdo do nome, agregando-os manualmente ao conjunto de instruções. O R possui função que
permite contar a quantidade de blocos que compõem o nome: “length”:

length(unlist(strsplit(nome," ")))
[1] 4

Assim, se agregarmos esse conjunto de instruções ao anterior, colocando-o entre colchetes, teremos o índice para extrair o último bloco sem necessidade de
intervenção visual e manual de nossa parte:

unlist(strsplit(nome," "))[length(unlist(strsplit(nome," ")))]


[1] "Neto"

As exceções também podem ser tratadas e, quando for o caso, acrescenta-se um -1 à contagem de blocos que compõem o nome para que o sobrenome seja
extraído corretamente:

unlist(strsplit(nome," "))[length(unlist(strsplit(nome," ")))-1]


[1] "Yoshida"

Finalmente, podemos colocar a “cereja” no bolo... Que tal criar uma função personalizada para extrair o sobrenome, incluindo o tratamento de exceções? Que
tal gravá-la num script para que possamos utilizá-la sempre que precisarmos dela?

Vamos, então, abrir o editor de script (Arquivo / Novo script) e digitar a sequência de instruções a seguir (o copiar-e-colar também funciona):

sobrenome<-function(nome){
a<-c("BISNETO","NETO","NETA","JUNIOR","JÚNIOR","JR","FILHO","FILHA","SOBRINHO","NETTO")
y<-unlist(strsplit(as.character(nome)," "))[length(unlist(strsplit(as.character(nome)," ")))]
ifelse(which(toupper(y)==a)>0,y<-unlist(strsplit(as.character(nome),"
"))[length(unlist(strsplit(as.character(nome)," ")))-1],y)
toupper(y)}
Vamos salvar esse conjunto de instruções (Arquivo / Salvar como) com o nome de FUNÇÃO_SOBRENOME. Em seguida: Arquivo / Fechar script. Note que
incorporamos mais uma função ao conjunto de instruções: “as.character”. Embora pareça óbvio que o nome seja composto por um conjunto de caracteres, se
isso não estiver explícito nas instruções, essa função recém criada não funcionará quando estivermos aplicando a uma coluna de nomes de uma tabela.

Para ativar a função: Arquivo / Interpretar código fonte R, selecionando o script FUNÇÃO_SOBRENOME:

source("C:\\ENSAIO_R\\FUNÇÃO_SOBRENOME.R")

Embora tenhamos ativado a função a partir da barra de menus, o R descreveu o comando utilizado para tal. Essa instrução pode ser inserida em qualquer
outro script que necessite dessa função.

Sempre que ativada, o R armazena as instruções na variável de memória “sobrenome”. Essas instruções contemplam o tratamento das exceções: "BISNETO",
"NETO", "NETA", "JUNIOR", "JÚNIOR", "JR", "FILHO", "FILHA", "SOBRINHO" e "NETTO". Ao se tomar conhecimento de alguma outra exceção, basta editar
o script (Arquivo / Abrir script) e acrescentá-la à lista.

Ao executar a função sobrenome() tendo como argumento determinado nome, será extraído o último bloco e comparado com a lista de exceções. Isso será
determinante para definir o índice que extrairá o bloco que contém o sobrenome.

sobrenome(Rubens Nakazato Yoshida Neto)


Erro: unexpected symbol in "sobrenome(Rubens Nakazato"

Ops!!! Para que a função seja executada corretamente, lembre-se de colocar o nome entre aspas:

sobrenome("Rubens Nakazato Yoshida Neto")


[1] "YOSHIDA"

sobrenome("JONAS LIEBL")
[1] "LIEBL"

Para evitar qualquer conflito de grafia, as comparações foram precedidas de conversão do bloco de sobrenome para maiúsculas.

Tratamento da base de gerentes

A base “gerentes.txt” contém uma tabela de gerentes com o respectivo código. Antes de importa-la no R, precisamos verificar qual é o separador dos campos
e se estão identificados por cabeçalho. Essas informações, juntamente com o nome da base, são necessárias como argumentos a serem utilizados para a
função “read.table”.
gerentes<-read.table("http://www.angelfire.com/un/cde/gerentes.txt",head=T,sep=";")

O argumento head=T (true) sinaliza para o R que a base possui cabeçalho. O sep=”;” informa que os campos são separados por ponto-e-vírgula. A base de
gerentes, obtida na Internet através de um link, foi armazenada na variável de memória “gerentes”:

gerentes
Cód_Gerente Nome
1 1 Charles Chaplin
2 2 Roberto Carlos
3 3 Tony Galhos
4 4 Carquel Costa
5 5 Filomena Schwarzenegger
6 6 José da Silva
7 7 Frank Sinatra
8 8 Rubens Nakazato Yoshida Neto
9 9 Conegundo Rosenberg
10 10 Allan de Lounge

Visualizando o conteúdo da variável de memória, percebemos que se trata de uma tabela com 10 linhas e 2 colunas, a qual se encontra plenamente compatível
com as informações da fonte original. Cabe uma dica: sempre que importamos uma base, precisamos ter alguma maneira de testar a integridade dessa
importação. Pode ser mediante batimento de totalizadores ou de contagem de linhas e de colunas. Somente podemos dar prosseguimento após termos uma
garantia mínima de que o conteúdo armazenado na variável de memória corresponde ao conteúdo da base original.

Nesta base em questão, temos duas observações a fazer. Os números que precedem a coluna Cód_Gerente, que aparecem sem nome de coluna,
correspondem ao nome da linha atribuído automaticamente pelo R. Neste exemplo, coincidem com o próprio código dos gerentes, mas é mera coincidência.

A outra observação é que os códigos de gerente, na base original, são compostos pelas sequências “001” a “010”. O R os importou no formato numérico,
desprezando os zeros à esquerda. Isso não trará qualquer problema, como demonstraremos quando fizermos o relacionamento de tabelas.

Agora vamos mostrar como buscamos o conteúdo de determinada célula: por exemplo, queremos o nome do gerente que se encontra na oitava linha. Podemos
mencionar explicitamente o nome da coluna que contém os nomes e usar o número da linha como índice:

gerentes$Nome[8]
[1] Rubens Nakazato Yoshida Neto
Levels: Allan de Lounge Carquel Costa Charles Chaplin Conegundo Rosenberg...

A linha “Levels” informa a sequência de nomes da coluna, mas o resultado da consulta propriamente dito aparece na linha [1] Rubens Nakazato Yoshida Neto.
A outra maneira de fazer a consulta consiste em informar o número da linha e o número da coluna:

gerentes[8,2]
[1] Rubens Nakazato Yoshida Neto
Levels: Allan de Lounge Carquel Costa Charles Chaplin Conegundo Rosenberg...

Desejando o sobrenome desse gerente, podemos utilizar essas consultas como argumentos da função sobrenome() criada anteriormente:

sobrenome(gerentes$Nome[8])
[1] "YOSHIDA"

sobrenome(gerentes[8,2])
[1] "YOSHIDA"

Também podemos usar essa função sobrenome() para extrair o sobrenome de cada gerente e adicioná-lo a uma terceira coluna da tabela:

gerentes<-cbind(gerentes,sobrenome=apply(gerentes[2],1,sobrenome))

A função “cbind” cria uma nova coluna chamada “sobrenome” na tabela armazenada na variável de memória “gerentes”. Essa coluna é resultado da função
“apply” com os seguintes argumentos:
- gerentes[2]: corresponde a todos os nomes da coluna 2 da tabela;
- 1: esse argumento 1 significa que a função será aplicada linha por linha;
- sobrenome: é o nome da função que nós criamos para extrair o sobrenome.

Uma dica importante: o R possui “ajuda” para nos orientar acerca da utilização das suas funções e respectivos argumentos. Por exemplo, na dúvida com
relação à função “apply”, basta solicitar essa ajuda usando a função help().

help(apply)

O resultado do comando para criação da coluna “sobrenome” foi rearmazenado na variável de memória “gerentes”:

gerentes
Cód_Gerente Nome sobrenome
1 1 Charles Chaplin CHAPLIN
2 2 Roberto Carlos CARLOS
3 3 Tony Galhos GALHOS
4 4 Carquel Costa COSTA
5 5 Filomena Schwarzenegger SCHWARZENEGGER
6 6 José da Silva SILVA
7 7 Frank Sinatra SINATRA
8 8 Rubens Nakazato Yoshida Neto YOSHIDA
9 9 Conegundo Rosenberg ROSENBERG
10 10 Allan de Lounge LOUNGE

Vamos guardar essa tabela para os procedimentos subsequentes. A nossa intenção é de verificar se o sobrenome dos gerentes está contido no nome dos
tomadores de financiamentos inadimplentes concedidos por cada qual.

Tratamento da base de inadimplência

Agora vamos importar a “baseinad.txt”. Como fizemos com a base anterior, precisamos verificar qual é o separador dos campos e se estão identificados por
cabeçalho. Além disso, se tiver algum campo numérico, qual é o separador de decimais. O R adota o ponto como padrão, que é a convenção utilizada em
países de cultura inglesa. Se os valores da base estiverem com vírgula, precisamos incluir essa informação na lista de argumentos da função “read.table”:

baseinad<-read.table("http://www.angelfire.com/un/cde/baseinad.txt",head=T,sep=";",dec=",")

Agora vamos utilizar algumas funções para testar a integridade da base recém importada. Por exemplo, verificar qual é a quantidade de linhas e de colunas:

dim(baseinad)
[1] 336 7

A função dim() nos mostra que a “baseinad” possui 336 linhas e 7 colunas.

Vamos obter o totalizador de campos numéricos:

colSums(baseinad)
Error in colSums(baseinad) : 'x' deve ser numérico

Ops!!! Algo não deu certo!!! É que a função “colSums” tenta somar todas as colunas da base, mas somente algumas são numéricas. Podemos usar a função
“head” para visualizar as primeiras linhas da base (são mostradas 6, por padrão):

head(baseinad)
Contrato Devedor Filial Cód_Gerente Linha.de.Financiamento Prest_Atraso Dívida
1 10473-2 OLIMPIO BARBOSA JUNIOR Curitiba 1 Bens de consumo duráveis 1 261.01
2 10575-2 ELVIS JUNIOR NEMOTO São Paulo 8 Bens de consumo duráveis 4 617.40
3 10614-2 MONICA PASCINI BARBOSA Rio de Janeiro 5 Bens de consumo duráveis 4 632.90
4 10731-9 JEAN FERNANDO FERREIRA NAVES Rio de Janeiro 4 Bens de consumo duráveis 3 497.90
5 10732-6 MILENE GOMES FELLI São Paulo 6 Bens de consumo duráveis 4 522.80
6 10761-8 BARBARA BATAGELLO MOREIRA São Paulo 8 Bens de consumo duráveis 8 640.10

Note que somente a 6ª e a 7ª colunas possuem valores de interesse para totalização. Assim, devemos incluir os respectivos índices no argumento da função
"colSums":

colSums(baseinad[6:7])
Prest_Atraso Dívida
1559.0 213666.3

Também podemos totalizar colunas uma a uma, informando o seu nome:

sum(baseinad$Prest_Atraso);sum(baseinad$Dívida)
[1] 1559
[1] 213666.3

Se as quantidades de linhas e de colunas e os valores totalizáveis da base armazenada na variável de memória “baseinad” forem compatíveis com a fonte
original, podemos atestar a sua integridade e continuar com o trabalho proposto.

Temos uma série de funções que permitem realizar uma análise exploratória dessa base de inadimplência, mas o foco neste momento é obter indícios de
parentesco entre gerentes concessores e tomadores de financiamentos. A “baseinad” possui um campo denominado “Cód_Gerente” com a matrícula do
concessor. A tabela de gerentes possui o nome e o sobrenome do gerente de cada “Cód_Gerente”. Nós podemos fundir as duas tabelas para que o nome e
sobrenome do gerente seja vinculado ao financiamento concedido por cada qual e, assim, permitir a comparação com o nome do tomador.

A função “merge” serve para isso. A lista de argumentos inclui as bases que serão juntadas (“baseinad” e “gerentes”), a chave comum às duas (“Cód_Gerente”)
e o “all.x=T”, que significa que todos os registros da primeira base deverão estar contidos no resultado, mesmo que o código do gerente não seja encontrado
na base “gerentes”. Lembrete: a chave usada deve ser do mesmo tipo em ambas as bases (neste caso, é numérica do tipo “int”). Use a função ls.str() para
obter essa informação e conferir se ambas coincidem:

ls.str(baseinad[4])
Cód_Gerente : int [1:336] 1 8 5 4 6 8 4 8 8 5 ...

ls.str(gerentes[1])
Cód_Gerente : int [1:10] 1 2 3 4 5 6 7 8 9 10
Agora, sim, fundindo as bases:

juntado<-merge(baseinad,gerentes,by="Cód_Gerente",all.x=T)

Visualizando os primeiros registros do “juntado”, temos:

head(juntado)

Cód_Gerente Contrato Devedor Filial Linha.de.Financiamento Prest_Atraso Dívida Nome sobrenome


1 1 16954-1 AUESER DIAS BARBOSA Curitiba Bens de consumo duráveis 1 390.3 Charles Chaplin CHAPLIN
2 1 23300-8 ANDRE GUSTAVO JORGE VALENCIO Curitiba Bens de consumo duráveis 5 575.8 Charles Chaplin CHAPLIN
3 1 40228-7 LILIAN RENATA NAKASHIMA Curitiba Bens de consumo duráveis 1 385.7 Charles Chaplin CHAPLIN
4 1 21112-9 EDIANEZ REDOLFI Curitiba Bens de consumo duráveis 4 580.7 Charles Chaplin CHAPLIN
5 1 21914-7 GELBI REGIANE SCHUBERT Curitiba Bens de consumo duráveis 3 351.2 Charles Chaplin CHAPLIN
6 1 17703-6 PRISCILA FERREIRA DE SOUZA Curitiba Bens de consumo duráveis 1 341.9 Charles Chaplin CHAPLIN

Interessante notar que o campo utilizado como chave (“Cód_Gerente”) passa a figurar como a primeira coluna das bases juntadas. O nome do tomador se
encontra na terceira coluna (“Devedor”) e o sobrenome do gerente aparece na nona coluna.

A função “tail” pode ser usada para ver os últimos registros de uma tabela. Por padrão, são mostrados seis registros, a menos que se especifique a quantidade
desejada, como 10, por exemplo:

tail(juntado,10)
Cód_Gerente Contrato Devedor Filial Linha.de.Financiamento Prest_Atraso Dívida Nome sobrenome
327 8 21566-1 LESSYANE REZENDE DE SOUZA São Paulo Bens de consumo duráveis 6 750.9 Rubens Nakazato Yoshida Neto YOSHIDA
328 8 40327-5 BRUNO BUENO BAIONI São Paulo Microcomputadores 8 665.6 Rubens Nakazato Yoshida Neto YOSHIDA
329 8 12248-8 LUCIO HITOSHI MITSUI São Paulo Sem destinação específica 5 671.9 Rubens Nakazato Yoshida Neto YOSHIDA
330 8 14191-2 ANA CAROLINA DE ARAUJO VENTURA São Paulo Sem destinação específica 7 680.5 Rubens Nakazato Yoshida Neto YOSHIDA
331 999 13361-0 FRANCIELLE DAIANA MORETTO Curitiba Bens de consumo duráveis 12 718.6 <NA> <NA>
332 999 13365-9 RODRIGO BARBOSA DE ABREU Curitiba Bens de consumo duráveis 11 722.5 <NA> <NA>
333 999 11254-0 JEYMILING KELLY S.VON MUHLEN São Paulo Bens de consumo duráveis 12 699.2 <NA> <NA>
334 999 12932-6 MARIANNA BASSO JORGE Rio de Janeiro Bens de consumo duráveis 10 798.0 <NA> <NA>
335 999 11565-0 ANA FLAVIA GUILHERMETTI São Paulo Bens de consumo duráveis 11 635.4 <NA> <NA>
336 999 16493-2 PEDRO ROBERTO BRAVO FILHO São Paulo Microcomputadores 11 1876.5 <NA> <NA>

De fato, temos um código de gerente (“999”) que não existe na tabela de gerentes. Isso pode ser uma deficiência do sistema de processamento dos
financiamentos que acata códigos diferentes do código do gerente que está logado no sistema. Podemos obter um resumo de quantidades de financiamentos
por gerentes e por filial usando a função “table”:

table(juntado$Cód_Gerente,juntado$Filial)
Curitiba Rio de Janeiro São Paulo
1 20 0 0
2 8 0 0
3 0 16 0
4 0 36 0
5 0 76 0
6 0 0 51
7 0 0 13
8 0 0 110
999 2 1 3

Note que o gerente “999” não consta na tabela de gerentes e tem financiamentos concedidos nas três filiais. Este é um achado que merece aprofundamento,
mas... voltando aos indícios de parentesco, vamos criar uma rotina para verificar se o sobrenome do gerente está contido no nome do tomador.

Para isso, usaremos a função “match”. Ela vai identificar em quais dos blocos do nome do tomador se encontra o sobrenome do concessor, quando for o caso.
Essa função não é aplicável a toda uma tabela, de uma só vez. Precisa ser utilizada registro a registro, por isso que a sequência de instruções começa com
um looping controlado em “x”, percorrendo todas as linhas da tabela “juntado”. A cada rodada, armazena-se na variável “a” o sobrenome do gerente que está
na coluna 9. Em seguida, armazena-se na variável “b” todos os blocos que compõem o nome do tomador da coluna 3, já devidamente separados. Finalmente,
utiliza-se a variável “c” para armazenar o resultado do “match”, ou seja, o número correspondente à posição que o sobrenome do gerente ocupa no nome do
tomador. Quando inexistente, esse resultado é 0 (zero).

Ao final do processamento, a variável “c” terá uma lista numérica de comprimento igual ao número de linhas da tabela “juntado”. Aí, basta adicioná-la como
uma coluna de nome “batimento_sobrenome”, utilizando a função “cbind”.

{for(x in seq(nrow(juntado)))
{a<-juntado[x,9]
b<-unlist(strsplit(as.character(juntado[x,3])," "))
ifelse(x==1,c<-match(a,b,nomatch=0),c<-c(c,match(a,b,nomatch=0)))}}
juntado<-cbind(juntado,batimento_sobrenome=c)

Colocando-se um filtro para visualizar os registros cujo “batimento_sobrenome” for maior que zero, teremos os indícios de interesse. Para facilitar a visualização,
vamos restringir a exibição de colunas:

juntado[2:8][juntado$batimento_sobrenome>0,]
Contrato Devedor Filial Linha.de.Financiamento Prest_Atraso Dívida Nome
60 13715-9 FABIANE COSTA DA SILVA Rio de Janeiro Sem destinação específica 1 474.0 Carquel Costa
158 11521-6 FERNANDA LIZ DA SILVA MIRANDA São Paulo Bens de consumo duráveis 1 506.3 José da Silva
174 14991-6 PAULA BATISTA SILVA São Paulo Bens de consumo duráveis 5 522.4 José da Silva
198 16154-8 ANTONIO CARLOS SILVA JUNIOR São Paulo Sem destinação específica 5 501.9 José da Silva
320 16045-3 BIANCA KIMIE YOSHIDA São Paulo Sem destinação específica 12 3981.0 Rubens Nakazato Yoshida Neto

Assim temos, caso a caso:


• Carquel Costa concedeu financiamento para Fabiane Costa da Silva;
• José da Silva firmou os contratos de Fernanda Liz da Silva Miranda, Paula Batista Silva e Antonio Carlos Silva Junior, sendo que o indício mais forte recai
sobre o primeiro destes nomes (os demais não são “da Silva”);
• Rubens Nakazato Yoshida Neto concedeu para Bianca Kimie Yoshida.

Considerações finais

“Data Mining não é uma solução, é um processo de descoberta de padrões e modelos significativos em grandes massas de dados. Não existe Data Mining
automatizado, nem softwares que executam Data Mining. Existem ferramentas que auxiliam o analista de Data Mining a explorar os dados, propor e testar
hipóteses. É por isso que, em geral, analistas de Data Mining são estatísticos ou algum tipo de cientista.” (apostila “Business Intelligence com Pentaho” da
4LINUX, pág. 22)

O software R é uma dessas ferramentas, mas ele sozinho não faz nada. Precisamos nos aventurar à descoberta das suas potencialidades, avançando no
conhecimento das suas funções a partir das mais básicas. O “Short R Reference Card” é o começo, mas o guia de referência completo tem mais de 3.500
páginas de desafios à nossa criatividade. Isso só não basta. Precisamos conhecer as regras do negócio sob exame e respectivas bases de dados. A junção
de todos estes ingredientes com uma boa pitada de matemática, estatística e raciocínio lógico-abstrato poderá nos surpreender. É claro que tudo isso só será
válido se produzirmos algo útil e que agregue valor.

O R é fruto de um ambiente colaborativo, portanto, é justo que façamos a nossa parte. Devemos estimular a geração de conhecimento para todos
compartilhando as nossas próprias descobertas. Ainda que essas descobertas já tenham sido feitas e compartilhadas anteriormente, sempre terá os benefícios
de um novo olhar proporcionado pela visão única da experiência de cada um.
O USO DO SOFTWARE R PARA DETECÇÃO DE TRANSAÇÕES ATÍPICAS

Contextualização

Um dos sistemas mais sensíveis em qualquer empresa é o sistema de custos. É ele que fornece informações a respeito da viabilidade econômico-financeira
de qualquer negócio. O objetivo é que se tenha negócios rentáveis com resultados positivos sustentáveis, de preferência crescentes. O sistema de custos é
um grande concentrador de informações que recebe lançamentos das mais diversas origens, seja de registros efetuados nos caixas de lojas e agências ou
direcionados pelos demais sistemas da empresa. São milhões de transações mensais que vão culminar na apuração de resultados de produtos, operações e
unidades. Como em toda atividade humana, está sujeito ao efeito de erros, falhas, omissões e até eventuais fraudes, principalmente pela multiplicidade de
agentes envolvidos e pela complexidade de interações. Monitorar a consistência dos seus números é uma tarefa árdua. A ciência de dados pode ser uma
grande aliada!!!

Vamos fazer um ensaio com o software R sobre uma base de dados de determinada conta custo para avaliar a consistência da série histórica mensal. Trata-
se de uma base formatada apenas para fins didáticos, denominada BASE_SICRS.txt, contendo informações simuladas de uma carteira de cheque especial de
uma agência bancária. Antes de importá-la no R, precisamos verificar se tem cabeçalho, qual é o separador de campos e se as decimais são separadas por
vírgula ou ponto. Isso precisará ser especificado na lista de argumentos da função read.table(). Feito isso, mãos à obra!!!

A base está disponível em: http://www.angelfire.com/un/cde/BASE_SICRS.txt. É possível fazer a importação diretamente pelo link. É mais uma funcionalidade
interessante do software R.

base<-read.table("http://www.angelfire.com/un/cde/BASE_SICRS.txt",head=T,sep=";",dec=",")

Terminada a importação, podemos verificar o conteúdo dos primeiros registros:

head(base)
CENC PRODUTO OBJEC CONTA_CUSTO ANO_MÊS LINHA_DO_TEMPO SALDO_GERADOR TAXA_MÉDIA_REDE RECEITA_DA_UNIDADE
1 AG_FICTÍCIA 195 50 711052001 201401 1 1538731 8.038431 125556.35
2 AG_FICTÍCIA 195 50 711052001 201402 2 1570483 7.631439 115387.56
3 AG_FICTÍCIA 195 50 711052001 201403 3 1665922 7.679898 128127.10
4 AG_FICTÍCIA 195 50 711052001 201404 4 1662835 3.847419 66543.04
5 AG_FICTÍCIA 195 50 711052001 201405 5 1775825 3.837908 70273.31
6 AG_FICTÍCIA 195 50 711052001 201406 6 1898053 3.840972 74476.46

Vamos entender o conteúdo dessa base pela descrição resumida dos seus campos:

CENC: é o centro de custo no qual está sendo efetuada a apuração de determinado resultado, no caso, a AG_FICTÍCIA.
PRODUTO: contém o código do produto relativo às informações de cada registro. Esse produto 195 corresponde a CHEQUE ESPECIAL PESSOA FÍSICA –
UTILIZAÇÃO.

OBJEC: identifica o objeto de custeio das informações em questão. O OBJEC 50 corresponde ao saldo médio mensal da carteira da agência, apurado pela
quantidade de dias úteis de cada mês.

CONTA_CUSTO: são as contas contábeis utilizadas para compor a apuração dos resultados, podendo ser contas de receita, custo ou despesa. A conta custo
711052001 trata as Rendas de Empréstimos Pessoa Física, que, no caso de cheque especial, corresponde aos juros sobre os limites utilizados em cada mês.

ANO_MÊS: identificação do ano e mês de competência dos registros.

LINHA_DO_TEMPO: é a sequência numérica de meses da série histórica. Veremos, mais à frente, que precisamos tratar as informações devidamente
posicionadas no tempo para que as questões sazonais sejam consideradas. Não se consegue lidar adequadamente com uma linha do tempo caracterizada
por ANO_MÊS, pelas rupturas sequenciais nas mudanças de ano. No exemplo 201411 x 201412 x 201501, vemos que o segundo mês é decorrente do
acréscimo de 1 ao primeiro, enquanto que o terceiro teve um incremento de 89 em relação ao segundo. É por isso que precisamos de uma linha do tempo com
incremento unitário ao longo de toda a série.

SALDO_GERADOR: é o valor do objeto de custeio 50, correspondente ao saldo médio mensal da carteira desse produto na agência.

TAXA_MÉDIA_REDE: é a taxa média de juros sobre a utilização de cheque especial observada mensalmente em toda a rede. O uso da taxa média da rede,
em vez da taxa média da carteira da agência, tem o objetivo de possibilitar que o modelo detecte eventual descolamento de taxas.

RECEITA_DA_UNIDADE: é o valor da conta custo 711052001 contabilizado mensalmente nessa agência.

Plotando gráficos

Também podemos visualizar a série histórica da receita através de um gráfico:

plot(base$RECEITA_DA_UNIDADE~base$LINHA_DO_TEMPO,type="l",col="blue",lwd=3)

A função plot() aciona a janela de gráficos. O “til” vincula a variável dependente Y que se encontra à esquerda (RECEITA_DA_UNIDADE) com a variável
independente X que se encontra à direita (LINHA_DO_TEMPO), permitindo que visualizemos o comportamento da receita ao longo da linha do tempo. Os
demais argumentos da sintaxe significam que queremos um gráfico do tipo “linha”, na cor azul e com a espessura 3. Ei-lo:
Essa receita possui um comportamento crescente ao longo da linha do tempo, porém apresenta algumas depressões na curva. Até que ponto essas depressões
são justificáveis? Houve alguma situação atípica que interferiu na evolução normal da receita da agência?

Regressão linear múltipla

É fácil compreender que a receita da unidade depende do saldo médio da carteira e da taxa de juros praticada em cada mês da linha do tempo. Quando temos
uma variável dependente de outras variáveis, podemos utilizar um modelo estatístico de curvas de regressão. O modelo mais adequado varia de acordo com
o comportamento gráfico da série histórica e da quantidade de variáveis independentes. Neste ensaio, são três: linha do tempo, saldo gerador e taxa média
da rede. Faremos as simulações usando regressão linear múltipla. É um tratamento estatístico complexo, constituído por equações matriciais, mas facilmente
executável com o R. Vamos lá (não esqueça de alternar a janela do gráfico para a janela do console através da barra de menus):

summary(lm(RECEITA_DA_UNIDADE~LINHA_DO_TEMPO+SALDO_GERADOR+TAXA_MÉDIA_REDE, data=base))

Call:
lm(formula = RECEITA_DA_UNIDADE ~ LINHA_DO_TEMPO + SALDO_GERADOR +
TAXA_MÉDIA_REDE, data = base)
Residuals:
Min 1Q Median 3Q Max
-74207 -8762 -2015 11581 38462

Coefficients:
Estimate Std. Error t value Pr(>|t|)
(Intercept) -1.301e+05 2.854e+04 -4.560 2.70e-05 ***
LINHA_DO_TEMPO 9.184e+02 5.532e+02 1.660 0.102
SALDO_GERADOR 4.643e-02 1.066e-02 4.355 5.49e-05 ***
TAXA_MÉDIA_REDE 2.461e+04 2.444e+03 10.073 2.37e-14 ***
---
Signif. codes: 0 ‘***’ 0.001 ‘**’ 0.01 ‘*’ 0.05 ‘.’ 0.1 ‘ ’ 1

Residual standard error: 19140 on 58 degrees of freedom


Multiple R-squared: 0.9691, Adjusted R-squared: 0.9675
F-statistic: 606 on 3 and 58 DF, p-value: < 2.2e-16

Explicando a sintaxe passo-a-passo:

summary: é uma função genérica usada para produzir resumos de resultados de várias funções de ajuste de modelo.

lm: é uma função utilizada para ajustar modelos lineares, incluindo os de múltiplas variáveis independentes.

RECEITA_DA_UNIDADE~LINHA_DO_TEMPO+SALDO_GERADOR+TAXA_MÉDIA_REDE: o til serve para vincular a variável dependente Y que se


encontra à esquerda (RECEITA_DA_UNIDADE) com as variáveis independentes X que estão à direita (LINHA_DO_TEMPO, SALDO_GERADOR e
TAXA_MÉDIA_REDE). O “+” não significa que as variáveis serão somadas. Ele sinaliza para o R que temos três variáveis independentes que deverão ser
consideradas simultaneamente no modelo.

data=base: informa a base de origem das variáveis especificadas na sintaxe, que, neste ensaio, foram importadas na variável de memória “base”.

Num primeiro momento, a informação mais importante obtida nesse resumo é a “multiple R-squared”, ou coeficiente de determinação. O valor de 0,9691
significa que este modelo está bastante aderente para as variáveis utilizadas. Quanto mais próximo de 1, mais aderente é o modelo. O fato desse valor ser
positivo significa que é uma série histórica com tendência crescente. Uma outra interpretação que pode ser dada para o coeficiente de determinação é que
96,91% da receita é explicada pelas três variáveis independentes tomadas em conjunto, considerando esse modelo de regressão.

O resumo contém outras informações de interesse, incluindo os elementos da equação para calcular a curva ajustada (intercepto e coeficientes das variáveis
independentes), mas não vamos nos aprofundar em teorias estatísticas neste momento.
Incluindo a curva ajustada

A curva ajustada nada mais é do que uma média dos valores da receita sensibilizada por tendência. É um referencial muito útil para efeito de comparação com
a série histórica e detecção de situações atípicas. A função que permite calcular os valores mensais da curva ajustada é a predict(), tomada em conjunto com
a lm():

base<-cbind(base,CURVA_AJUSTADA=predict(lm(RECEITA_DA_UNIDADE~LINHA_DO_TEMPO+SALDO_GERADOR+TAXA_MÉDIA_REDE,
data=base)))

Visualizando o conteúdo dos primeiros registros:

head(base)
CENC PRODUTO OBJEC CONTA_CUSTO ANO_MÊS LINHA_DO_TEMPO SALDO_GERADOR TAXA_MÉDIA_REDE RECEITA_DA_UNIDADE CURVA_AJUSTADA
1 AG_FICTÍCIA 195 50 711052001 201401 1 1538731 8.038431 125556.35 140071.44
2 AG_FICTÍCIA 195 50 711052001 201402 2 1570483 7.631439 115387.56 132446.04
3 AG_FICTÍCIA 195 50 711052001 201403 3 1665922 7.679898 128127.10 138988.00
4 AG_FICTÍCIA 195 50 711052001 201404 4 1662835 3.847419 66543.04 45428.41
5 AG_FICTÍCIA 195 50 711052001 201405 5 1775825 3.837908 70273.31 51358.29
6 AG_FICTÍCIA 195 50 711052001 201406 6 1898053 3.840972 74476.46 58026.60

As regressões lineares, tanto as simples quanto as múltiplas, têm uma característica que lhes é bem peculiar: a curva ajustada constitui-se numa média
sensibilizada por tendência, cujos valores têm o efeito matemático de redistribuição dos valores originais. Assim, para nos assegurarmos que adotamos os
procedimentos corretos, basta testar se a soma de ambas as colunas, RECEITA_DA_UNIDADE e CURVA_AJUSTADA, são iguais:

sum(base$RECEITA_DA_UNIDADE);sum(base$CURVA_AJUSTADA)
[1] 12598850
[1] 12598850

Vamos enriquecer o gráfico plotado anteriormente acrescentando a curva ajustada. Neste momento, não cabe usar a função plot() porque ela “limpa” o conteúdo
da janela de gráficos antes de gerar o outro. A função adequada é a lines(). Ela dispensa o argumento “type” porque a própria função deixa claro que se trata
de linha. Vamos usar a cor vermelha com a mesma espessura da primeira plotagem:

lines(base$CURVA_AJUSTADA~base$LINHA_DO_TEMPO,col="red",lwd=3)

Para visualizar o gráfico, não esqueça de alternar a janela do console para a janela do gráfico através da barra de menus:
Esse gráfico já permite algumas observações interessantes. A primeira depressão na curva da receita da agência aconteceu logo no início, mais
especificamente no quarto mês. Note que a curva ajustada também sofreu uma depressão em intensidade semelhante. Isso significa que a perda de receita
nesse mês não foi provocada por algum evento atípico da unidade. De fato, no início da série histórica fizemos uma simulação da campanha Melhor Crédito
ocorrido há alguns anos. Evidentemente, o impacto da redução das taxas se estendeu a todas as unidades da rede e isso está refletido na curva ajustada,
que, sua vez, referenda o comportamento da curva da agência.

Ao longo dos primeiros 40 meses, ambas as curvas têm comportamentos semelhantes, com pequenos descolamentos. Isso revela períodos em que a taxa
média da carteira da unidade é superior à média geral, com a curva da receita sobreposta à ajustada, como também o inverso em outros períodos. Se esse
efeito for muito significativo, cabe averiguar se a unidade praticou as políticas vigentes de taxas nas contratações da época. As depressões de maior impacto,
observadas em pontos isolados como DEZ 2017 e FEV 2019, revelam alguma perda de receita não justificada por perda de carteira, já que a curva ajustada
manteve o ritmo da sua evolução. Por outro lado, o descolamento observado entre esses dois meses é decorrente da tensão que ambas as depressões
provocam sobre a curva ajustada e não pelo fato da taxa média da carteira da unidade ser maior do que a média geral.

É claro que o gráfico ajuda a observar o comportamento da receita da unidade em torno de uma “média com tendência”, mas não conseguimos perceber a
materialidade em termos de números. Para isso, convém criar mais uma coluna com a variação de valor de cada mês:

base<-cbind(base,VARIAÇÃO_VALOR=base$RECEITA_DA_UNIDADE-base$CURVA_AJUSTADA)
É interessante também criar um referencial que nos dê a dimensão percentual dessa materialidade:

base<-cbind(base,VARIAÇÃO_PERCENTUAL=base$VARIAÇÃO_VALOR/base$CURVA_AJUSTADA*100)

Baseado no pressuposto de que as depressões de maior impacto são relevantes para prospectar situações atípicas que ensejam perda de receita, a
classificação da coluna VARIAÇÃO_PERCENTUAL em ordem crescente dará a sinalização dos meses que deverão ser examinados prioritariamente. Vamos
visualizar os seis primeiros registros classificados dessa forma:

head(base[5:12][order(base$VARIAÇÃO_PERCENTUAL),])
ANO_MÊS LINHA_DO_TEMPO SALDO_GERADOR TAXA_MÉDIA_REDE RECEITA_DA_UNIDADE CURVA_AJUSTADA VARIAÇÃO_VALOR VARIAÇÃO_PERCENTUAL
48 201712 48 2591315 11.256782 237114.5 311321.0 -74206.55 -23.836024
62 201902 62 2552300 12.051558 273552.4 341930.3 -68377.84 -19.997597
2 201402 2 1570483 7.631439 115387.6 132446.0 -17058.48 -12.879567
1 201401 1 1538731 8.038431 125556.4 140071.4 -14515.09 -10.362634
45 201709 45 2953919 10.486931 281453.2 306450.4 -24997.16 -8.156999
22 201510 22 3276011 3.900796 127333.5 138165.9 -10832.42 -7.840156

A maior sinalização se encontra no mês de DEZ 2017, com a receita da unidade a 23,83% abaixo da curva ajustada. Esse mês ensejará uma análise
aprofundada dos lançamentos contábeis registrados no razonete da agência, para detectar a ocorrência de estornos de receita ou outros débitos atípicos. Esse
procedimento deve ser prioritário para o segundo classificado, o mês de FEV 2019, que é uma competência recente sobre a qual é possível agir caso a
atipicidade encontrada seja decorrente de erro, falha, omissão ou fraude. Com relação aos outros dois meses subsequentes, qualquer ação neste momento é
intempestiva visto já terem decorridos cinco anos. De qualquer forma, a análise pode ser interessante para produzir conhecimento acerca do comportamento
atípico da receita, com o objetivo de refinar o modelo.

Considerações finais

Com o R, fica fácil testar a aderência do modelo. Por exemplo, num primeiro momento poderíamos imaginar que o saldo gerador, por si só, já seria suficiente
para explicar a evolução da receita da unidade. Será que apenas essa variável independente seria razoável para isso?

summary(lm(RECEITA_DA_UNIDADE~SALDO_GERADOR, data=base))
Multiple R-squared: 0.2449, Adjusted R-squared: 0.2323

Reprocessando o “summary” com apenas o saldo gerador na posição da variável X, observamos que o “multiple R-squared” é de 0,2449. Fica evidente que o
modelo proporcionado pelo uso simultâneo das três variáveis, com coeficiente de determinação de 0,9691, é muito mais ajustado do que o mero uso de uma
única variável. Em suma, ao desenvolver um modelo baseado em curvas de regressão, devemos pensar e testar todas as variáveis independentes que podem
estar afetas à série histórica da variável Y. Um modelo bem ajustado reduzirá a ocorrência de falsos positivos.
Neste ensaio, nós usamos esse modelo de regressão linear múltipla para processar a série histórica de determinada conta custo de uma única agência, a
AG_FICTÍCIA. O R é uma ferramenta muito poderosa e podemos utilizá-lo com ganhos de escala, processando as séries históricas de todas as unidades da
instituição financeira numa única rodada. Para isso, basta desenvolver um script incluindo um controle de looping para percorrer a tabela de unidades e tratá-
las uma por vez, gravando os resultados num arquivo geral. Assim, ao final do processamento, teremos uma lista de prioridades apontando também as agências
que deverão ser analisadas.

Ao processar o conjunto de unidades da instituição financeira, teremos coeficientes de determinação distintos para cada qual. O modelo estará bem ajustado
se a maioria das unidades tiver um coeficiente próximo de 1. Eventuais unidades com “multiple R-squared” baixo não significa que o modelo está desajustado.
É possível que toda a série histórica dessas unidades se revista de aspectos atípicos merecedores de investigação.

Quanto mais ajustado um modelo baseado em curvas de regressão, maiores são os benefícios que se pode obter dele. Além da detecção de indícios de
transações atípicas através dos “picos” e “depressões” da curva, o modelo pode ser usado para previsão. Dizem os especialistas que é viável prever até um
quarto do tempo que se dispõe na série histórica. Por exemplo, a nossa “base”, que tem uma série de 62 meses, constitui-se em insumo para previsão de até
15 meses a partir de MAR 2019. Evidentemente, quanto mais distante no tempo for essa previsão, maior é a possibilidade de distorções. Além disso, a
consistência da previsão depende de quão criteriosa estão sendo as estimativas das variáveis independentes.

Finalmente, vai uma dica... Podemos fazer uso de modelos de curvas de regressão sempre que dispormos de séries históricas e for possível estabelecer
relações de causa e efeito através da identificação de variáveis independentes que possam explicar determinada variável. Isso serve para previsões
orçamentárias, atribuição de metas, análise de custos, entre tantas outras possibilidades. O R é uma das ferramentas mais importantes para potencializar o
uso dessa técnica.
IMPORTAÇÃO DE BASES ATÍPICAS NO SOFTWARE R

Somente é possível se aventurar no maravilhoso mundo da Ciência de Dados se dispusermos do combustível essencial para essa viagem: “os dados”. No
âmbito das empresas, eles podem ser obtidos nas mais diversas fontes, entre as quais se destacam:
• comando de queries nos sistemas corporativos;
• captura de bancos de dados diretamente nos sites;
• obtenção de spool files de relatórios em produção.

Uma vez conseguidas as bases adequadas para os nossos propósitos, deparamo-nos com dois grandes desafios: (1) efetuar a sua importação no software
escolhido para a empreitada e (2) descobrir quais são as funções adequadas para extrair as informações de que necessitamos.

Este artigo é um relato de uma experiência recente que foi um grande quebra-cabeça. Trata-se da base SA702 do Sistema de Custos, Receitas e Resultados
obtida através de querie. É uma base mensal muito simples que chega a ter cerca de 2,5 milhões de registros, contemplando todos os lançamentos em contas
custo discriminadas por centros de custo e produtos. Para este ensaio, elaboramos esta pequena base fictícia que permitirá simular as dificuldades encontradas
na prática:

EN CENC DATA TC CONTA PROD REALIZADO


9999 9999 201903 01 711052001 0195 +0000000073240,00
9999 9999 201903 01 711054001 0195 +0000000001430,39
9999 9999 201903 06 719201001 0195 +0000000003124,59
9999 9999 201903 17 781100130 0195 +0000000012292,58
9999 9999 201903 56 881100112 0195 +0000000003478,67
9999 9999 201903 61 881100130 0195 +0000000009628,94
9999 9999 201903 68 819999009 0195 +0000000000060,00
9999 9999 201903 81 819521402 0195 +0000000000633,38
***** TOTAL 0195 +0000000103888,55
8 GRAVADOS - INICIO 12.53.45.00 - FIM 12.53.54.59

À exceção das últimas duas linhas, podemos inferir que se trata de uma tabela composta por sete colunas, contendo informações do EN (escritório de negócio,
antiga denominação de superintendência regional), CENC (centro de custo), DATA (ano e mês), TC (tipo da conta custo), CONTA (conta custo), PROD
(produto) e REALIZADO (valor contabilizado). A penúltima linha tem o totalizador da coluna REALIZADO, enquanto que a última mostra o horário de início e
término da geração do arquivo, além da quantidade de linhas que apresentam as informações de interesse. Detalhe importante: ambas as linhas não
correspondem ao leiaute das anteriores e a última é mais comprida que as precedentes. Vamos copiar o conteúdo dessas 11 linhas e colar num bloco de
notas, salvando o arquivo como “SA702.txt”.
Em seguida, vamos abrir o software R. Já tivemos a oportunidade de conhecer um pouco das suas potencialidades através dos artigos anteriores. O desafio
de hoje é importar a base SA702. Vimos que se trata de uma tabela com sete colunas devidamente identificadas pelo nome dos campos e que as últimas duas
linhas não interessam para a importação, porém são muito úteis para garantir a integridade dos registros que serão importados. Identificamos visualmente que
temos 8 linhas de interesse, da segunda até a nona, que a primeira contém os nomes dos campos e que o valor do REALIZADO tem as decimais separadas
por vírgula. Antes de qualquer coisa, precisamos que o R detecte a quantidade de linhas do arquivo. O primeiro impulso é de utilizar a função “nrow”:

nrow("SA702.txt")
NULL

Obtivemos “NULL” como resultado, ou seja, essa função não funcionou. Podemos obter o resultado desejado por outro caminho. Vamos tentar a contagem de
campos: “count.fields”:

count.fields("SA702.txt")
[1] 7 7 7 7 7 7 7 7 7 4 8

O resultado apresentado em [1] mostra a quantidade de campos da base SA702 reconhecida pelo R, linha por linha. Note que temos nove resultados 7, que
correspondem ao cabeçalho e aos oito registros de interesse. As duas últimas linhas, cujos leiautes são diferentes das precedentes, tiveram um reconhecimento
de quantidade de campos diverso das demais. Para obter a contagem das linhas do arquivo, basta adicionar a função “length” a essa sintaxe:

length(count.fields("SA702.txt"))
[1] 11

Se diminuirmos as quantidades de linhas que não são registros de interesse para a importação (cabeçalho e as duas últimas linhas), teremos a contagem dos
registros que deverão ser importados:

length(count.fields("SA702.txt"))-3
[1] 8

Essa sintaxe será incorporada à lista de argumentos da função “read.table”, além da informação da existência de cabeçalho e da vírgula utilizada como
separador de decimais:

base<-read.table("SA702.txt",head=T,dec=",",nrows=length(count.fields("SA702.txt"))-3)

Visualizando a variável de memória “base”:


base
EN CENC DATA TC CONTA PROD REALIZADO
1 9999 9999 201903 1 711052001 195 73240.00
2 9999 9999 201903 1 711054001 195 1430.39
3 9999 9999 201903 6 719201001 195 3124.59
4 9999 9999 201903 17 781100130 195 12292.58
5 9999 9999 201903 56 881100112 195 3478.67
6 9999 9999 201903 61 881100130 195 9628.94
7 9999 9999 201903 68 819999009 195 60.00
8 9999 9999 201903 81 819521402 195 633.38

Note que não foi necessário informar o separador de campos na lista de argumentos. O próprio R detectou o espaço como separador de colunas e importou
as linhas corretamente. Como já percebemos visualmente, a penúltima linha da base SA702.txt contém o totalizador do REALIZADO e a última apresenta a
quantidade de linhas de interesse. Essas duas informações são muito importantes para testar a integridade dos registros importados na variável de memória
“base”. Para importar somente a penúltima linha, precisamos adicionar a função “skip” e informar que pretendemos importar uma única linha. Com “skip”, o R
vai “pular” os registros precedentes:

read.table("SA702.txt",dec=",",skip=length(count.fields("SA702.txt"))-2,nrows=1)
V1 V2 V3 V4
1 ***** TOTAL 195 103888.6

Neste caso, não devemos informar a existência de cabeçalho porque dará conflito entre as quantidades de campos detectadas pelo R para a linha 1 e para a
linha 10. O próprio R deu os nomes de campos de V1 a V4 para as informações que ele reconheceu. O que nos interessa mesmo está na V4, portanto, basta
incluir o índice [4] na sintaxe e obteremos somente o totalizador:

read.table("SA702.txt",dec=",",skip=length(count.fields("SA702.txt"))-2,nrows=1)[4]
V4
1 103888.6

Não estranhem o valor de 103888.6 apresentado para a V4. É apenas uma visualização arredondada para uma casa decimal, mas, internamente, o valor
original de 103888,55 está preservado. Para testar a integridade dos valores importados, basta totalizar a coluna REALIZADO da variável de memória “base”
e comparar com esse totalizador da linha 10:

sum(base$REALIZADO)==read.table("SA702.txt",dec=",",skip=length(count.fields("SA702.txt"))-2,nrows=1)[4]
V4
[1,] TRUE
O resultado “TRUE” confirma que ambos os totalizadores são iguais, portanto, a integridade dos valores do campo REALIZADO foi preservada na importação.
Atenção para a sintaxe de comparação: usa-se dois sinais de igual (“==”). Apenas um sinal de igual dará erro, pois não funciona para comparação e, sim, para
atribuição de valor para alguma variável. Podemos também testar a quantidade de registros com aquela informada na linha 11. A sequência abaixo nos dá a
dica de como fazê-lo:

dim(base)[1]==read.table("SA702.txt",dec=",",skip=length(count.fields("SA702.txt"))-1,nrows=1)[1]
V1
[1,] TRUE

Quando desenvolvemos scripts para importação de bases de forma automatizada, podemos sofisticar o teste de integridade para que a interação com o usuário
se dê através de mensagens. Por exemplo:

batimento1<-sum(base$REALIZADO)-read.table("SA702.txt",dec=",",skip=length(count.fields("SA702.txt"))-2,nrows=1)[4]
batimento2<-dim(base)[1]-read.table("SA702.txt",dec=",",skip=length(count.fields("SA702.txt"))-1,nrows=1)[1]
ifelse(batimento1==0,print("IMPORTAÇÃO DE VALORES REALIZADA COM SUCESSO"),print("DIVERGÊNCIA NA IMPORTAÇÃO DE VALORES.
VERIFIQUE!!!"))
ifelse(batimento2==0,print("IMPORTAÇÃO DE QUANTIDADE DE REGISTROS REALIZADA COM SUCESSO"),print("DIVERGÊNCIA NA
QUANTIDADE DE REGISTROS IMPORTADOS. VERIFIQUE!!!"))

Concluindo, cabe lembrar que em processamento de dados sempre há múltiplos caminhos que conduzem às soluções desejadas. Estes ensaios refletem a
visão de um leigo em TI que faz uso de ferramentas como o R para resolver questões de trabalho, dando prioridade às funções mais básicas descritas no
“Short R Reference Card” (https://cran.r-project.org/doc/contrib/Short-refcard.pdf). Mais importante do que a chegada, é entender as nuances da caminhada,
aprender com os tropeços e superar as dificuldades. O resto virá através de um processo de melhoria contínua.
IMPORTAÇÃO DE BASES ATÍPICAS NO SOFTWARE R – PARTE 2

Hoje vamos tratar uma outra base do Sistema de Custos, Receitas e Resultados que tem características bem peculiares: a SA719 – RESULTADO POR
PRODUTO. É uma base TXT gerada por querie que contém valores agrupados de contas custo por produto, incluindo o resultado do produto, também
conhecido como margem de contribuição. Além disso, apresenta saldos finais e saldos médios de alguns objetos de custeio e a rentabilidade dos produtos no
mês e/ou ano de referência. O arquivo de um mês contemplando todas as unidades tem cerca de 700 mil linhas, cada qual com o comprimento de 453
caracteres distribuídos em 33 campos.

Para este ensaio, elaboramos uma pequena base fictícia com alguns produtos de uma unidade hipotética identificada como 9999. Também encurtamos o
comprimento da linha para viabilizar a transcrição dos registros para este post:

CENC PROD DATA CUSTO OPORTUNI RECEITA FINANC RESULT. PROD. OBJ SALDO FINAL SALDO MEDIO RENTABILIDADE
9999 0102 201903+0000000000051,33+0000000000382,77+0000000000316,01 +0000000009976,09+0000000009611,57 +00002,534200
9999 0105 201903+0000000000337,37+0000000001524,19+0000000001131,64 +0000000063151,80+0000000063300,17 +00001,092900
9999 0107 201903+0000000002104,50+0000000017240,82+0000000016838,19 +0000000388298,71+0000000394813,99 +00002,721800
9999 0110 201903+0000000074587,54+0000000255971,05+0000000147205,51 +0000014171076,22+0000013992783,03 +00000,948000
9999 0144 201903+0000000000000,00+0000000000000,00+0000000000000,00 +0000000000000,00+0000000000000,00 00000,000000
9999 0203 201903+0000000003575,41+0000000036633,34+0000000031380,13 +0000000695858,05+0000000670754,76 +00002,696800
9999 4568 201903+0000000000069,00+0000000001805,84+0000000001656,07 +0000000027196,99+0000000012950,95 +00002,652900
9999 4569 201903+0000000003976,20+0000000013520,58+0000000038203,02 +0000000753483,25+0000000745936,46 +00005,068400
9999 9999 201903+0000000084701,35+0000000327078,59+0000000236730,57 +0000016109041,11+0000015890150,93 +00005,068400
9 GRAVADOS DATA: 2019/04/02 - INICIO 09.09.53.32 - FIM 09.10.05.79 DATA: 201903 NIVEL: 1 REFERENCIA: 1 CENC: 9999

Agora vamos conhecer alguns detalhes do seu conteúdo. A última linha contém informações da querie, como data da geração do arquivo, hora de início e
término da gravação, mês de competência e centro de custo (unidade). A primeira informação dessa linha tem a quantidade de registros gravados, que pode
ser usada para testar a integridade da importação.

As linhas anteriores permitem visualizar uma tabela com informações dispostas em 10 colunas: centro de custo, produto, ano/mês de competência, custo
oportunidade, receita financeira, resultado do produto, objeto de custeio, saldo final, saldo médio e rentabilidade. As colunas são separadas por espaços,
porém, quando se referem a valor, no lugar do espaço precedente temos o sinal do valor ( + ou - ), à exceção da coluna RENTABILIDADE. O campo OBJ se
encontra em branco. A penúltima linha contém os totalizadores de cada coluna de valor. Esses totalizadores poderão ser utilizados para testar a integridade
dos valores importados.

Vamos copiar o conteúdo da base e colar num bloco de notas, salvando como SA719.txt. Em seguida, contaremos a quantidade de campos que o R reconhece
em cada linha:

count.fields("SA719.txt")
[1] 15 5 5 5 5 5 5 5 5 5 18

Aqui temos o primeiro problema para importação da base. O R está utilizando o espaço como delimitador e percebemos que há conflito entre as quantidades
de campos detectadas para o cabeçalho e os demais registros de interesse. Uma outra questão é que, quando temos o sinal do valor no lugar do espaço, todo
o conjunto de valores existentes entre dois espaços é reconhecido como um único campo. Para contornar essas questões, deve-se pular o cabeçalho e definir
os campos desejados via script. As últimas duas linhas também não interessam para a importação, pois uma é de totais e a outra de informações da querie.
Assim, a contagem de linhas de interesse a serem importadas é dada pela sintaxe:

length(count.fields("SA719.txt"))-3
[1] 8

Essa sintaxe será incorporada à lista de argumentos da função “read.table”, além da informação para pular o cabeçalho e da vírgula utilizada como separador
de decimais:

base<-read.table("SA719.txt",skip=1,dec=",",nrows=length(count.fields("SA719.txt"))-3)

Visualizando a variável de memória “base”:

base
V1 V2 V3 V4 V5
1 9999 102 201903+0000000000051,33+0000000000382,77+0000000000316,01 +0000000009976,09+0000000009611,57 2.5342
2 9999 105 201903+0000000000337,37+0000000001524,19+0000000001131,64 +0000000063151,80+0000000063300,17 1.0929
3 9999 107 201903+0000000002104,50+0000000017240,82+0000000016838,19 +0000000388298,71+0000000394813,99 2.7218
4 9999 110 201903+0000000074587,54+0000000255971,05+0000000147205,51 +0000014171076,22+0000013992783,03 0.9480
5 9999 144 201903+0000000000000,00+0000000000000,00+0000000000000,00 +0000000000000,00+0000000000000,00 0.0000
6 9999 203 201903+0000000003575,41+0000000036633,34+0000000031380,13 +0000000695858,05+0000000670754,76 2.6968
7 9999 4568 201903+0000000000069,00+0000000001805,84+0000000001656,07 +0000000027196,99+0000000012950,95 2.6529
8 9999 4569 201903+0000000003976,20+0000000013520,58+0000000038203,02 +0000000753483,25+0000000745936,46 5.0684

O R reconheceu 5 campos que foram denominados como V1 a V5. O único campo de valor importado como tal foi o de RENTABILIDADE, identificado como
V5. Isso se deve ao fato de que havia espaço antes do sinal do valor. Os demais campos de valor foram importados em blocos de texto. Vamos imaginar que
as colunas de interesse para o nosso trabalho sejam o CENC, PROD, DATA, RESULT. PROD e RENTABILIDADE. Os campos V1, V2 e V5 contêm três
dessas informações desejadas, mas a DATA e o RESULT. PROD precisarão ser extraídos do V3. Vamos fazê-lo agora criando os respectivos campos:

base<-cbind(base,DATA=substr(base$V3,1,6))
base<-cbind(base,RESULT_PROD=as.numeric(paste(substr(base$V3,41,54),substr(base$V3,56,57),sep=""))/100)
A composição do valor do resultado do produto precisou ser feita a partir da colagem das sequências de texto entre vírgulas, com a sua transformação para
numérico e divisão por 100 para reposicionar as casas decimais. Como não precisamos mais dos campos V3 e V4, podemos excluí-los da base utilizando os
respectivos índices:

base<-base[-3:-4]

Visualizando a variável de memória “base”:

base
V1 V2 V5 DATA RESULT_PROD
1 9999 102 2.5342 201903 316.01
2 9999 105 1.0929 201903 1131.64
3 9999 107 2.7218 201903 16838.19
4 9999 110 0.9480 201903 147205.51
5 9999 144 0.0000 201903 0.00
6 9999 203 2.6968 201903 31380.13
7 9999 4568 2.6529 201903 1656.07
8 9999 4569 5.0684 201903 38203.02

Vamos renomear as colunas para deixá-las mais intuitivas:

colnames(base)<-c("CENC","PROD","RENTABILIDADE","DATA","RESULT_PROD")

base
CENC PROD RENTABILIDADE DATA RESULT_PROD
1 9999 102 2.5342 201903 316.01
2 9999 105 1.0929 201903 1131.64
3 9999 107 2.7218 201903 16838.19
4 9999 110 0.9480 201903 147205.51
5 9999 144 0.0000 201903 0.00
6 9999 203 2.6968 201903 31380.13
7 9999 4568 2.6529 201903 1656.07
8 9999 4569 5.0684 201903 38203.02

Agora só falta testar a integridade da base recém importada. Esse procedimento é imprescindível porque, havendo erros na importação de uma base, todo o
trabalho subsequente será equivocado. Vimos que a última linha contém a quantidade de registros gerados. Percebemos também que o registro precedente é
de totalizadores, portanto, não interessa para a importação, porém faz parte dessa quantidade. A sintaxe para extrair essa informação e comparar com a
quantidade importada é a seguinte:

dim(base)[1]==read.table("SA719.txt",skip=length(count.fields("SA719.txt"))-1,nrows=1)[1]-1
V1
[1,] TRUE

Ao ler a última linha, a existência de espaços entre as diversas informações faz o R reconhecer 18 campos. O que nos interessa corresponde ao primeiro,
razão pela qual incorporamos o índice [1] à sintaxe. A subtração de 1 é para não computar a linha de totalizadores na quantidade de registros que deve ser
considerada para comparar com a quantidade importada. A função “dim” aplicada à variável de memória “base” retorna a quantidade de linhas e de colunas
que ela possui. Ao agregar o índice [1], obtém-se unicamente a quantidade de linhas.

Finalmente, vamos extrair o totalizador do campo RESULT. PROD. Precisaremos ler o terceiro bloco da penúltima linha e tratar o valor da mesma maneira
como fizemos para definir o respectivo campo. Faremos por etapas utilizando a variável de memória “totalizador”:

(totalizador<-read.table("SA719.txt",skip=length(count.fields("SA719.txt"))-2,nrows=1)[3])
V3
1 201903+0000000084701,35+0000000327078,59+0000000236730,57

Note que sintaxe interessante... Foi criada a variável de memória “totalizador” para armazenar o conteúdo do terceiro bloco da penúltima linha. Como
colocamos entre parênteses, o R simultaneamente criou a variável de memória e mostrou o conteúdo armazenado. Agora vamos extrair o valor:

(totalizador<-as.numeric(paste(substr(totalizador$V3,41,54),substr(totalizador$V3,56,57),sep=""))/100)
[1] 236730.6

Não estranhem o valor de 236730.6. É apenas uma visualização arredondada para uma casa decimal, mas, internamente, o valor original de 236730,57 está
preservado. Para testar a integridade dos valores importados, basta totalizar a coluna RESULT_PROD da variável de memória “base” e comparar com a
variável de memória “totalizador”:

sum(base$RESULT_PROD)==totalizador
[1] TRUE

Ambos os resultados TRUE confirmam que a quantidade de registros importados e os valores do campo RESULT_PROD conferem com a base original, dando-
nos um atestado de integridade. A nossa variável de memória “base” está pronta para os trabalhos subsequentes que ensejaram a importação.