Introdução

Ao contrário da maioria dos exemplos encontrados em livros didáticos, é comum encontrar dados em uma forma crua na natureza. Portanto, a limpeza de dados torna-se um elemento essencial para a qualidade da análise exploratória.

A má qualidade dos dados é a principal razão para problemas na análise exploratória de dados e de inteligência de negócios.

A limpeza de dados é o processo de transformação de dados brutos em dados utilizáveis. Limpeza de dados, verificação da qualidade e padronização dos tipos de dados são os responsáveis pela maioria do tempo gasto no cronograma analítico do projeto.

Os analistas de negócios gastam muito tempo na limpeza de dados antes de passar para a fase de análise (que é o que interessa).

Esse material complementar fornecerá um processo estruturado para resumir, corrigir, converter e adaptar os dados brutos em conjuntos de dados para a sua análise exploratória de dados. Trata-se de um guia, que, porém, não substituirá pesquisas futuras na web.

Limpeza e preparação dos dados

Os dados foram disponibilizados por uma empresa internacional que atua no segmento de aluguel de bicicletas na cidade de São Francisco – EUA. Os dados também podem ser encontrados aqui.

Antes de começar a fase de análise, devemos, sempre, verificar a qualidade dos dados. Neste caso, resumiremos os dados e limparemos deficiências comuns, como corrigir dados ausentes, converter datas e incompatibilidades de tipo de dados.

Ler os dados

Utilizaremos, entre outros, o pacote dplyr, um subconjunto do package tidyverse. O dplyr possui uma completa e coerente gramática para manipulação de dados.

library(tidyverse)

bike <- read_csv("Dados/raw_bike_data.csv")
class(bike)
## [1] "spec_tbl_df" "tbl_df"      "tbl"         "data.frame"

Como foi utilizada a função readr::read_csv() para ler os dados no sistema, bike foi criada como um tibble (um objeto da classe tbl_df).

tibbles são data.frames “preguiçosos” e “mal-humorados”: eles fazem menos (ou seja, eles não mudam nomes ou tipos de variáveis, e não fazem correspondência parcial) e reclamam muito (por exemplo, quando uma variável não existe). Isso nos força a perceber os problemas mais cedo, normalmente levando a um código mais limpo. Os tibbles também têm um método de impressão print() aprimorado, o que os torna mais fáceis de se usar com grandes conjuntos de dados contendo objetos complexos.

As primeiras quinze linhas da variável bike:

Resumindo a estrutura de dados do data frame

str(bike)
## tibble [17,379 x 13] (S3: spec_tbl_df/tbl_df/tbl/data.frame)
##  $ datetime  : chr [1:17379] "1/1/2011 0:00" "1/1/2011 1:00" "1/1/2011 2:00" "1/1/2011 3:00" ...
##  $ season    : num [1:17379] 1 1 1 1 1 1 1 1 1 1 ...
##  $ holiday   : num [1:17379] 0 0 0 0 0 0 0 0 0 0 ...
##  $ workingday: num [1:17379] 0 0 0 0 0 0 0 0 0 0 ...
##  $ weather   : num [1:17379] 1 1 1 1 1 2 1 1 1 1 ...
##  $ temp      : num [1:17379] 9.84 9.02 9.02 9.84 9.84 ...
##  $ atemp     : num [1:17379] 14.4 13.6 13.6 14.4 14.4 ...
##  $ humidity  : num [1:17379] 81 80 80 75 75 75 80 86 75 76 ...
##  $ windspeed : num [1:17379] 0 0 0 0 0 ...
##  $ casual    : num [1:17379] 3 8 5 3 0 0 2 1 1 8 ...
##  $ registered: num [1:17379] 13 32 27 10 1 1 0 2 7 6 ...
##  $ count     : num [1:17379] 16 40 32 13 1 1 2 3 8 14 ...
##  $ sources   : chr [1:17379] "ad campaign" "www.yahoo.com" "www.google.fi" "AD campaign" ...
##  - attr(*, "problems")= tibble [1 x 5] (S3: tbl_df/tbl/data.frame)
##   ..$ row     : int 14177
##   ..$ col     : chr "humidity"
##   ..$ expected: chr "a double"
##   ..$ actual  : chr "x61"
##   ..$ file    : chr "'Dados/raw_bike_data.csv'"
##  - attr(*, "spec")=
##   .. cols(
##   ..   datetime = col_character(),
##   ..   season = col_double(),
##   ..   holiday = col_double(),
##   ..   workingday = col_double(),
##   ..   weather = col_double(),
##   ..   temp = col_double(),
##   ..   atemp = col_double(),
##   ..   humidity = col_double(),
##   ..   windspeed = col_double(),
##   ..   casual = col_double(),
##   ..   registered = col_double(),
##   ..   count = col_double(),
##   ..   sources = col_character()
##   .. )
dim(bike) # fornece as dimensões de linha e coluna de um data frame
## [1] 17379    13
head(bike) # seis primeiras observações
## # A tibble: 6 x 13
##   datetime season holiday workingday weather  temp atemp humidity windspeed
##   <chr>     <dbl>   <dbl>      <dbl>   <dbl> <dbl> <dbl>    <dbl>     <dbl>
## 1 1/1/201~      1       0          0       1  9.84  14.4       81      0   
## 2 1/1/201~      1       0          0       1  9.02  13.6       80      0   
## 3 1/1/201~      1       0          0       1  9.02  13.6       80      0   
## 4 1/1/201~      1       0          0       1  9.84  14.4       75      0   
## 5 1/1/201~      1       0          0       1  9.84  14.4       75      0   
## 6 1/1/201~      1       0          0       2  9.84  12.9       75      6.00
## # ... with 4 more variables: casual <dbl>, registered <dbl>, count <dbl>,
## #   sources <chr>
tail(bike) # seis últimas observações
## # A tibble: 6 x 13
##   datetime season holiday workingday weather  temp atemp humidity windspeed
##   <chr>     <dbl>   <dbl>      <dbl>   <dbl> <dbl> <dbl>    <dbl>     <dbl>
## 1 12/31/2~      1       0          1       2  10.7  13.6       48      9.00
## 2 12/31/2~      1       0          1       2  10.7  12.9       60     11.0 
## 3 12/31/2~      1       0          1       2  10.7  12.9       60     11.0 
## 4 12/31/2~      1       0          1       1  10.7  12.9       60     11.0 
## 5 12/31/2~      1       0          1       1  10.7  13.6       56      9.00
## 6 12/31/2~      1       0          1       1  10.7  13.6       65      9.00
## # ... with 4 more variables: casual <dbl>, registered <dbl>, count <dbl>,
## #   sources <chr>

Alternativamente, pode-se utilizar a função dplyr::glimpse(), que apresenta um visão mais “enxuta”.

glimpse(bike)  # uma outra forma de verificar as variaveis
## Rows: 17,379
## Columns: 13
## $ datetime   <chr> "1/1/2011 0:00", "1/1/2011 1:00", "1/1/2011 2:00", "1/1/...
## $ season     <dbl> 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,...
## $ holiday    <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ workingday <dbl> 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,...
## $ weather    <dbl> 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 2, 2, 2, 2, 3,...
## $ temp       <dbl> 9.84, 9.02, 9.02, 9.84, 9.84, 9.84, 9.02, 8.20, 9.84, 13...
## $ atemp      <dbl> 14.395, 13.635, 13.635, 14.395, 14.395, 12.880, 13.635, ...
## $ humidity   <dbl> 81, 80, 80, 75, 75, 75, 80, 86, 75, 76, 76, 81, 77, 72, ...
## $ windspeed  <dbl> 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 6.0032, 0.0000, ...
## $ casual     <dbl> 3, 8, 5, 3, 0, 0, 2, 1, 1, 8, 12, 26, 29, 47, 35, 40, 41...
## $ registered <dbl> 13, 32, 27, 10, 1, 1, 0, 2, 7, 6, 24, 30, 55, 47, 71, 70...
## $ count      <dbl> 16, 40, 32, 13, 1, 1, 2, 3, 8, 14, 36, 56, 84, 94, 106, ...
## $ sources    <chr> "ad campaign", "www.yahoo.com", "www.google.fi", "AD cam...

Podemos interpretar imediatamente algumas das principais características dos dados: há 17379 observações e 13 variáveis, com dois tipos de dados:

  • onze numéricos <dbl> e

  • dois caracteres <chr>.

Podemos ver alguns problemas com o dados:

  • datetime foi lida como um string, ao invés do formato Date e

  • Algumas variáveis foram lidas como <dbl>, mas são, na realidade, categóricas (factor) descritas por números inteiros (por exemplo, season). Saiba que estes dados estão em muito melhor condição do que a maioria dos que encontramos para análise de negócios.

Uma sugestão: mantenha a mente aberta e se esforce para aprender sempre ao longo da vida. Os métodos mudam e se adaptam continuamente. Os melhores analistas de negócios desenvolvem o seu próprio conjunto de ferramentas. Há uma quantidade enorme de pacotes no R. Como dizem, para quase todos os problemas de análise de dados, há um pacote do R.

A questão dos NAs

Dados ausentes - NAs ou valores não-disponíveis - representam muitas dificuldades para os métodos de análise. Encontrar dados ausentes é tão importante que existem no R funções projetadas especificamente para encontrá-los. A função is.na() é otimizada para pesquisar grandes conjuntos de dados e encontra rapidamente valores ausentes. Afunção table() pode ser utilizada inicialmente para verificar a quantidade total de NAs em seus dados. is.na(), quando aplicada com a função apply(), permite verificar todo o data frame de modo vetorizado. Uma maneira alternativa de se obter o mesmo resultado é utilizar a função colSums().

table(is.na(bike))
## 
##  FALSE   TRUE 
## 225372    555
prop.table(table(is.na(bike))) * 100  # calcula proporções
## 
##      FALSE       TRUE 
## 99.7543454  0.2456546
apply(is.na(bike), 2, sum)
##   datetime     season    holiday workingday    weather       temp      atemp 
##          0          0          0          0          0          0          0 
##   humidity  windspeed     casual registered      count    sources 
##          1          0          0          0          0        554
colSums(is.na(bike))  # uma alternativa
##   datetime     season    holiday workingday    weather       temp      atemp 
##          0          0          0          0          0          0          0 
##   humidity  windspeed     casual registered      count    sources 
##          1          0          0          0          0        554

Apenas 0,25% dos valores são NAs. Note que 554 NAs estão localizados na coluna sources (fontes) e apenas um na variável “humidity”. Embora poucos neste caso, podemos encontrar dados em que o volume seja representativo. Deve-se buscar o máximo de informações disponíveis para a análise exploratória.

A abordagem de imputação que você escolher depende do aleatoriedade dos dados faltantes e do seu conhecimento sobre o negócio. Imputar dados pode ser simples ou bastante difícil. Onde estão os dados perdidos? Quais variáveis incluem valores NA?

Um bom tutorial para se aprender mais sobre a imputação de dados pode ser encontrado aqui.

No caso das fontes dos dados (sources) podemos, simplesmente, substituir os NAs pela expressão “Desconhecida”.

bike$sources[is.na(bike$sources)] <- "Desconhecida"

Como só há um NA agora, na variável “humidity”, podemos omitir este dados de bike, ou substituí-lo por algum valor que faça sentido. Para exemplificar, tomaremos a segunda medida e vamos substituir o valor faltante pela média de todos os valores de humidade.

Note que é necessário incluir na.rm = TRUE na função mean().

bike$humidity[is.na(bike$humidity)] <- mean(bike$humidity, na.rm = TRUE)

# Calcula o número total de NA´s
sum(is.na(bike))
## [1] 0

Variáveis categóricas

Como vimos, algumas variáveis que foram lidas como numéricas são, na realidade, categóricas. Vamos acertar isso.

As variáveis “holiday” e “workingday” são binárias: 0 para não e 1 para sim. Vamos torná-las categóricas e criar os níveis e labels adequados.

A variável “season” apresenta valores em c(1, 2, 3, 4) e vamos nomeá-la para c(primavera, verao, outono, inverno).

A variável “weather” também apresenta valores em c(1, 2, 3, 4) e vamos alterar para c(nublado, neblina, chuva, chuva_forte).

Para as variáveis de escala ordinal, “season” e “weather”, vamos definir o fator utilizando fatores ordenados. É necessário fornecer os parâmetros níveis (levels) e rótulos (labels), colocando os níveis na ordem que desejarmos. Se uma ordem não é declarada, o R ordena os fatores alfabeticamente.

bike$holiday <- factor(bike$holiday, levels = c(0,1),
                                     labels = c("nao", "sim"))
  
bike$workingday <- factor(bike$workingday, levels = c(0,1),
                                           labels = c("nao", "sim"))
  
bike$season <- factor(bike$season, levels = c(1, 2, 3, 4),
                                   labels = c("primavera", 
                                              "verao", 
                                              "outono", 
                                              "inverno"),
                                   ordered = TRUE)
  
bike$weather <- factor(bike$weather, levels = c(1, 2, 3, 4),
                                     labels = c("nublado", 
                                                "neblina", 
                                                "chuva", 
                                                "chuva_forte"),
                                     ordered = TRUE)
bike

Conversão de datas

O segredo para conversões bem-sucedidas de datas é conhecer o formato das datas nos dados de entrada. Há várias funções no R para visualizá-las. Um típico exemplo de valor da variável datetime é um string como 10/17/2012 21:00, ou seja, o formato é mm/dd/yyyy hh:mm.

As funções no pacote lubridate são nomeadas usando letras representando a ordem dos dados de entrada. No caso atual, deveremos utilizar a função mdy_hm().

if(!require("lubridate")) install.packages("lubridate")

suppressMessages(suppressWarnings(library(lubridate)))

bike$datetime <- mdy_hm(bike$datetime)
glimpse(bike)
## Rows: 17,379
## Columns: 13
## $ datetime   <dttm> 2011-01-01 00:00:00, 2011-01-01 01:00:00, 2011-01-01 02...
## $ season     <ord> primavera, primavera, primavera, primavera, primavera, p...
## $ holiday    <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, n...
## $ workingday <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, n...
## $ weather    <ord> nublado, nublado, nublado, nublado, nublado, neblina, nu...
## $ temp       <dbl> 9.84, 9.02, 9.02, 9.84, 9.84, 9.84, 9.02, 8.20, 9.84, 13...
## $ atemp      <dbl> 14.395, 13.635, 13.635, 14.395, 14.395, 12.880, 13.635, ...
## $ humidity   <dbl> 81, 80, 80, 75, 75, 75, 80, 86, 75, 76, 76, 81, 77, 72, ...
## $ windspeed  <dbl> 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 6.0032, 0.0000, ...
## $ casual     <dbl> 3, 8, 5, 3, 0, 0, 2, 1, 1, 8, 12, 26, 29, 47, 35, 40, 41...
## $ registered <dbl> 13, 32, 27, 10, 1, 1, 0, 2, 7, 6, 24, 30, 55, 47, 71, 70...
## $ count      <dbl> 16, 40, 32, 13, 1, 1, 2, 3, 8, 14, 36, 56, 84, 94, 106, ...
## $ sources    <chr> "ad campaign", "www.yahoo.com", "www.google.fi", "AD cam...

Uma alternativa bem interessante: segregar data e hora

Caso queiramos segregar a data da hora (lembrando que estamos falando de aluguel de bicicletas), podemos criar duas variáveis data e hora para ampliar o espectro da nossa análise exploratória de dados.

bike <- bike %>% 
  tidyr::separate(datetime, 
                  into = c("data", "hora"), 
                  sep = " ",
                  remove = FALSE)

glimpse(bike)
## Rows: 17,379
## Columns: 15
## $ datetime   <dttm> 2011-01-01 00:00:00, 2011-01-01 01:00:00, 2011-01-01 02...
## $ data       <chr> "2011-01-01", "2011-01-01", "2011-01-01", "2011-01-01", ...
## $ hora       <chr> "00:00:00", "01:00:00", "02:00:00", "03:00:00", "04:00:0...
## $ season     <ord> primavera, primavera, primavera, primavera, primavera, p...
## $ holiday    <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, n...
## $ workingday <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, n...
## $ weather    <ord> nublado, nublado, nublado, nublado, nublado, neblina, nu...
## $ temp       <dbl> 9.84, 9.02, 9.02, 9.84, 9.84, 9.84, 9.02, 8.20, 9.84, 13...
## $ atemp      <dbl> 14.395, 13.635, 13.635, 14.395, 14.395, 12.880, 13.635, ...
## $ humidity   <dbl> 81, 80, 80, 75, 75, 75, 80, 86, 75, 76, 76, 81, 77, 72, ...
## $ windspeed  <dbl> 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 6.0032, 0.0000, ...
## $ casual     <dbl> 3, 8, 5, 3, 0, 0, 2, 1, 1, 8, 12, 26, 29, 47, 35, 40, 41...
## $ registered <dbl> 13, 32, 27, 10, 1, 1, 0, 2, 7, 6, 24, 30, 55, 47, 71, 70...
## $ count      <dbl> 16, 40, 32, 13, 1, 1, 2, 3, 8, 14, 36, 56, 84, 94, 106, ...
## $ sources    <chr> "ad campaign", "www.yahoo.com", "www.google.fi", "AD cam...

Tranformando data em formato DATE

bike$data <- as.Date(bike$data)

Transformando HMS (hora, minuto, segundo)

if(!require("hms")) install.packages("hms")
suppressMessages(suppressWarnings(library(hms)))

bike$hora <- as_hms(bike$hora)

glimpse(bike)
## Rows: 17,379
## Columns: 15
## $ datetime   <dttm> 2011-01-01 00:00:00, 2011-01-01 01:00:00, 2011-01-01 02...
## $ data       <date> 2011-01-01, 2011-01-01, 2011-01-01, 2011-01-01, 2011-01...
## $ hora       <time> 00:00:00, 01:00:00, 02:00:00, 03:00:00, 04:00:00, 05:00...
## $ season     <ord> primavera, primavera, primavera, primavera, primavera, p...
## $ holiday    <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, n...
## $ workingday <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, n...
## $ weather    <ord> nublado, nublado, nublado, nublado, nublado, neblina, nu...
## $ temp       <dbl> 9.84, 9.02, 9.02, 9.84, 9.84, 9.84, 9.02, 8.20, 9.84, 13...
## $ atemp      <dbl> 14.395, 13.635, 13.635, 14.395, 14.395, 12.880, 13.635, ...
## $ humidity   <dbl> 81, 80, 80, 75, 75, 75, 80, 86, 75, 76, 76, 81, 77, 72, ...
## $ windspeed  <dbl> 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 6.0032, 0.0000, ...
## $ casual     <dbl> 3, 8, 5, 3, 0, 0, 2, 1, 1, 8, 12, 26, 29, 47, 35, 40, 41...
## $ registered <dbl> 13, 32, 27, 10, 1, 1, 0, 2, 7, 6, 24, 30, 55, 47, 71, 70...
## $ count      <dbl> 16, 40, 32, 13, 1, 1, 2, 3, 8, 14, 36, 56, 84, 94, 106, ...
## $ sources    <chr> "ad campaign", "www.yahoo.com", "www.google.fi", "AD cam...

Agrupando os dados

contagem <- bike %>% 
  dplyr::select(data, temp, humidity, casual, count) %>% 
  group_by(data) %>% 
  summarise(med.count = median(count, na.rm = TRUE)) # mediana dos dados

contagem
## # A tibble: 731 x 2
##    data       med.count
##    <date>         <dbl>
##  1 2011-01-01      35.5
##  2 2011-01-02      22  
##  3 2011-01-03      56.5
##  4 2011-01-04      57  
##  5 2011-01-05      62  
##  6 2011-01-06      62  
##  7 2011-01-07      59  
##  8 2011-01-08      29  
##  9 2011-01-09      22.5
## 10 2011-01-10      41.5
## # ... with 721 more rows

Um gráfico das medianas das contagens.

# O pacote "ggplot2" é carregado com o "tidyverse"

ggplot(contagem, aes(data, med.count)) +
  geom_line(col = "steelblue") +
         labs(x = "Data", 
              y = "Mediana de contagens", 
          title = "Rental Bike - San Francisco") +
  scale_x_date(limits = as.Date(c("2011-01-01","2012-12-31")))

Quase pronto

Neste ponto do processo, os dados estão resumidos, corrigidos e convertidos. Falta apenas padronizar o que for necessário. Por exemplo, podemos observar que a coluna sources, a fonte de publicidade de onde o cliente conheceu o serviço de bicicletas, é um string (conjunto de caracteres). Se deixarmos desta forma, o R não poderá agrupar itens a partir dessa fontes.

O necessário padrão, nesse caso, é transformar sources em um fator. Entretanto, antes de simplesmente usar as.factor(bike$sources), vamos verificar quantas fontes diferentes estão registradas.

unique(bike$sources)
##  [1] "ad campaign"      "www.yahoo.com"    "www.google.fi"    "AD campaign"     
##  [5] "Twitter"          "www.bing.com"     "www.google.co.uk" "facebook page"   
##  [9] "Ad Campaign"      "twitter"          "Desconhecida"     "www.google.com"  
## [13] "direct"           "blog"             "Direct"

Note que há observações com letras maiúsculas e minúsculas, sites, página do facebook etc..

O pacote stringr contém muitas funções para manipular strings. O seguinte código mostra duas dessas funções, bem como o uso de subsetting para converter todos os atrings para letras minúsculas e excluir eventuais excessos de espaço em branco:

bike$sources <- tolower(bike$sources)
bike$sources <- str_trim(bike$sources)

unique(bike$sources)
##  [1] "ad campaign"      "www.yahoo.com"    "www.google.fi"    "twitter"         
##  [5] "www.bing.com"     "www.google.co.uk" "facebook page"    "desconhecida"    
##  [9] "www.google.com"   "direct"           "blog"

Especialistas em publicidade propõem que, quando se trata de sites, o importante não é necessariamente qual é mecanismo de busca que clientes usam, mas sim que a pessoa encontrou os serviços de compartilhamento de bicicletas na Web. O código a seguir realiza esta adaptação:

sitios_web <- "(www.[a-z]*.[a-z]*)" # utilizando expressões regulares: todos os strings começando com "www."
atual <- unique(str_subset(bike$sources, sitios_web))
bike$sources <- ifelse(bike$sources %in% atual, "web", bike$sources)

O código anterior faz o seguinte:

  • Atribui uma expressão regular à variável sitios_web, que agora é um string que pode ser utilizado para pesquisar todas as variantes de strings começando com “www.”.

  • Utiliza a função str_subset() para encontrar essas instâncias e atribuí-las à variável atual.

  • Substitui os strings que começam com “www.” por “web”.

unique(bike$sources)
## [1] "ad campaign"   "web"           "twitter"       "facebook page"
## [5] "desconhecida"  "direct"        "blog"

Se for desejável manter os dados originais, basta criar outra coluna: por exemplo, com bike$sources2 <- ifelse(bike$sources %in% atual, "web", bike$sources). A coluna original seria mantida no data frame bike.

A última providência é converter a variável sources em fator:

bike$sources <- as.factor(bike$sources)

glimpse(bike)
## Rows: 17,379
## Columns: 15
## $ datetime   <dttm> 2011-01-01 00:00:00, 2011-01-01 01:00:00, 2011-01-01 02...
## $ data       <date> 2011-01-01, 2011-01-01, 2011-01-01, 2011-01-01, 2011-01...
## $ hora       <time> 00:00:00, 01:00:00, 02:00:00, 03:00:00, 04:00:00, 05:00...
## $ season     <ord> primavera, primavera, primavera, primavera, primavera, p...
## $ holiday    <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, n...
## $ workingday <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, n...
## $ weather    <ord> nublado, nublado, nublado, nublado, nublado, neblina, nu...
## $ temp       <dbl> 9.84, 9.02, 9.02, 9.84, 9.84, 9.84, 9.02, 8.20, 9.84, 13...
## $ atemp      <dbl> 14.395, 13.635, 13.635, 14.395, 14.395, 12.880, 13.635, ...
## $ humidity   <dbl> 81, 80, 80, 75, 75, 75, 80, 86, 75, 76, 76, 81, 77, 72, ...
## $ windspeed  <dbl> 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 6.0032, 0.0000, ...
## $ casual     <dbl> 3, 8, 5, 3, 0, 0, 2, 1, 1, 8, 12, 26, 29, 47, 35, 40, 41...
## $ registered <dbl> 13, 32, 27, 10, 1, 1, 0, 2, 7, 6, 24, 30, 55, 47, 71, 70...
## $ count      <dbl> 16, 40, 32, 13, 1, 1, 2, 3, 8, 14, 36, 56, 84, 94, 106, ...
## $ sources    <fct> ad campaign, web, web, ad campaign, twitter, web, ad cam...

Finalmente

Normalmente é uma boa ideia alterar os nomes das variáveis (colunas) de data frames obtidos externamete de modo a se tornarem mais adequados às nossas necessidades de apresentação e relatórios. O pacote dplyrpossui a função rename() que pode ser aplicada a tibbles para essa finalidade. Como exemplo, vamos traduzir para o português alguns nomes:

bike <- bike %>% rename(data_hora = datetime,
                        estacao = season,
                        feriado = holiday,
                        dia_trabalho = workingday,
                        clima = weather, 
                        humidade = humidity,
                        vento = windspeed,
                        registrado = registered,
                        cont = count,
                        fontes = sources)

glimpse(bike)
## Rows: 17,379
## Columns: 15
## $ data_hora    <dttm> 2011-01-01 00:00:00, 2011-01-01 01:00:00, 2011-01-01 ...
## $ data         <date> 2011-01-01, 2011-01-01, 2011-01-01, 2011-01-01, 2011-...
## $ hora         <time> 00:00:00, 01:00:00, 02:00:00, 03:00:00, 04:00:00, 05:...
## $ estacao      <ord> primavera, primavera, primavera, primavera, primavera,...
## $ feriado      <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao,...
## $ dia_trabalho <fct> nao, nao, nao, nao, nao, nao, nao, nao, nao, nao, nao,...
## $ clima        <ord> nublado, nublado, nublado, nublado, nublado, neblina, ...
## $ temp         <dbl> 9.84, 9.02, 9.02, 9.84, 9.84, 9.84, 9.02, 8.20, 9.84, ...
## $ atemp        <dbl> 14.395, 13.635, 13.635, 14.395, 14.395, 12.880, 13.635...
## $ humidade     <dbl> 81, 80, 80, 75, 75, 75, 80, 86, 75, 76, 76, 81, 77, 72...
## $ vento        <dbl> 0.0000, 0.0000, 0.0000, 0.0000, 0.0000, 6.0032, 0.0000...
## $ casual       <dbl> 3, 8, 5, 3, 0, 0, 2, 1, 1, 8, 12, 26, 29, 47, 35, 40, ...
## $ registrado   <dbl> 13, 32, 27, 10, 1, 1, 0, 2, 7, 6, 24, 30, 55, 47, 71, ...
## $ cont         <dbl> 16, 40, 32, 13, 1, 1, 2, 3, 8, 14, 36, 56, 84, 94, 106...
## $ fontes       <fct> ad campaign, web, web, ad campaign, twitter, web, ad c...

Sucesso! Os dados estão resumidos, limpos, convertidos e adaptados. Podemos, agora, gravar um arquivo que poderá ser utilizado para futuras análises.

write_csv(bike, "Dados/limpos_sharing_data.csv")

Referências

1 Jay Gendron, Introduction to R for business intelligence _ learn how to leverage the power of R