2014-11-28

Duplicar forma en Excel

Title

Problema

Cuando copiamos una forma (Ctrl+C) y la volvemos a pegar (Ctrl+V), Excel la presenta desplazada (abajo a la derecha de la original).

Solución

  1. Seleccionamos la forma.
  2. Ctrl+J para duplicar la forma. Ctrl+D si nuestro Excel está en inglés.
  3. Arrastramos la forma a la posición deseada.
  4. Ctrl+J de nuevo. La forma se pegará duplicando también la posición relativa respecto del objeto original.

Solución en imágenes

Referencias:

2014-11-26

Conectando R con Ms Access mediante RODBC

Title El paquete RODBC conecta R con Ms Access. Con él podremos acceder a tablas y consultas ya creadas en Access: leer, guardar, copiar y manipular datos de tablas y consultas. El paquete emplea la conectividad ODBC (Open Database Connectivity) para establecer la conexión con Ms Access y mediante SQL (Structured Query Language) se interactúa con la base de datos.

Conexión de R con Ms Access

Instalamos y cargamos el paquete RODBC

install.packages("RODBC")
library(RODBC)
# Listado de DSNs disponibles
odbcDataSources()
                                             Excel Files 
"Microsoft Excel Driver (*.xls, *.xlsx, *.xlsm, *.xlsb)" 
                                      MS Access Database 
              "Microsoft Access Driver (*.mdb, *.accdb)" 
Establecemos la conexión, el canal. Emplearemos como ejemplo la base de datos Neptuno.mdb

# Interactivamente
canal <- odbcConnectAccess(file.choose()) 
# Escribiendo la ruta
neptuno <- "C:/Users/User1/Documents/R/Neptuno.mdb" # Ruta correspondiente
canal <- odbcConnectAccess(neptuno) 
# Base de datos en el directorio de trabajo
canal <- odbcConnectAccess("Neptuno.mdb") 
# Descargando el fichero zip
# en el directorio de trabajo
url <- "https://sites.google.com/site/nubededatosblogspotcom/Neptuno.zip"
download.file(url, "Neptuno")
unzip("Neptuno")
canal <- odbcConnectAccess("Neptuno.mdb") 
# Descargando el fichero zip
# en un archivo temporal
temp <- tempfile()
download.file("https://sites.google.com/site/nubededatosblogspotcom/Neptuno.zip", temp)
unzip(temp)
unlink(temp)
canal <- odbcConnectAccess("Neptuno.mdb") 
Detalles de la conexión

canal
RODBC Connection 1
Details:
  case=nochange
  DBQ=C:\Users\User1\Documents\R\Neptuno.mdb
  Driver={Microsoft Access Driver (*.mdb)}
  DriverId=25
  FIL=MS Access
  MaxBufferSize=2048
  PageTimeout=5
  UID=admin

Listado de tablas y consultas

Devuelve un data frame de las tablas y consultas accesibles desde la conexión ODBC establecida. Está compuesto de cinco columnas: catalog, schema, name, type and remarks. Incluye las tablas del sistema por defecto.

sqlTables(canal) 
       TABLE_CAT TABLE_SCHEM        TABLE_NAME   TABLE_TYPE REMARKS
1 C:\\R\\Neptuno        <NA> MSysAccessObjects SYSTEM TABLE    <NA>
2 C:\\R\\Neptuno        <NA>     MSysAccessXML SYSTEM TABLE    <NA>
3 C:\\R\\Neptuno        <NA>          MSysACEs SYSTEM TABLE    <NA>
4 C:\\R\\Neptuno        <NA>       MSysCmdbars SYSTEM TABLE    <NA>
5 C:\\R\\Neptuno        <NA>   MSysIMEXColumns SYSTEM TABLE    <NA>
6 C:\\R\\Neptuno        <NA>     MSysIMEXSpecs SYSTEM TABLE    <NA>
Para obtener una columna específica, empleamos el símbolo $ seguido del nombre de la columna.

sqlTables(canal)$TABLE_NAME # All objects' names
Especificamos el argumento tableType para elegir, tablas del sistema, tablas o consultas.

# Tablas del sistema
sqlTables(canal, tableType = "SYSTEM TABLE")$TABLE_NAME 
 [1] "MSysAccessObjects"          "MSysAccessXML"             
 [3] "MSysACEs"                   "MSysCmdbars"               
 [5] "MSysIMEXColumns"            "MSysIMEXSpecs"             
 [7] "MSysNameMap"                "MSysNavPaneGroupCategories"
 [9] "MSysNavPaneGroups"          "MSysNavPaneGroupToObjects" 
[11] "MSysNavPaneObjectIDs"       "MSysObjects"               
[13] "MSysQueries"                "MSysRelationships" 
# Tablas
sqlTables(canal, tableType = "TABLE")$TABLE_NAME
[1] "Categorías"          "Clientes"            "Compañías de envíos"
[4] "Detalles de pedidos" "Empleados"           "Pedidos"            
[7] "Productos"           "Proveedores"   
# Consultas
sqlTables(canal, tableType = "VIEW")$TABLE_NAME 
 [1] "Clientes y proveedores por ciudad"
 [2] "Consulta de pedidos"              
 [3] "Detalle de pedidos con descuento" 
 [4] "Facturas"                         
 [5] "Filtro facturas"                  
 [6] "Lista alfabética de productos"  

Estructura de las columnas

Devuelve un data frame con la información de las columnas de las tablas o consultas de la conexión establecida (canal).

 [1] "TABLE_CAT"         "TABLE_SCHEM"      
 [3] "TABLE_NAME"        "COLUMN_NAME"      
 [5] "DATA_TYPE"         "TYPE_NAME"        
 [7] "COLUMN_SIZE"       "BUFFER_LENGTH"    
 [9] "DECIMAL_DIGITS"    "NUM_PREC_RADIX"   
[11] "NULLABLE"          "REMARKS"          
[13] "COLUMN_DEF"        "SQL_DATA_TYPE"    
[15] "SQL_DATETIME_SUB"  "CHAR_OCTET_LENGTH"
[17] "ORDINAL_POSITION"  "IS_NULLABLE"      
[19] "ORDINAL" 
Para obtener una columna específica, empleamos el símbolo $ seguido del nombre de la columna.

sqlColumns(canal, "Clientes")$COLUMN_NAME
 [1] "IdCliente"      "NombreCompañía" "NombreContacto"
 [4] "CargoContacto"  "Dirección"      "Ciudad"        
 [7] "Región"         "CódPostal"      "País"          
[10] "Teléfono"       "Fax"      

Manipulación de datos

Antes de manipular datos es recomendable hacer una copia de seguridad. Las funciones sqlUpdate y sqlDrop ocasionan cambios o pérdidas de datos irreversibles.

    Leer e importar datos

Tenemos dos opciones:

  1. sqlFetch tanto para tablas como consultas ya existentes.
  2. ConsultaDePedidos <- sqlFetch(canal, sqtable = "Detalles de pedidos")
    # Para limitar el nº de filas importadas: max
    ConsultaDePedidos <- sqlFetch(canal, sqtable = "Detalles de pedidos", max = 100)
    
  3. sqlQuery para enviar consultas SQL a la base de datos de Ms Access. Se puede incluir cualquier sentencia válida de SQL, incluyendo la creación, modificación, actualización o selección.
  4. Clientes <- sqlQuery(canal, "SELECT * FROM Clientes")
    # Para limitar el nº de filas leídas: max
    Clientes <- sqlQuery(canal, "SELECT * FROM Clientes", max = 10)
    
Para evitar errores cuando el nombre de las tablas o consultas incluyen espacios en blanco, los escribimos entre corchetes.

ConsultaDePedidos <- sqlQuery(canal, "SELECT * FROM [Consulta de pedidos]")
Una consulta más compleja, Facturas de la Neptuno.mdb, copiando el código directamente SQL. Sustituimos las comillas dobles " " por simples ' '[Nombre] & ' ' & [Apellidos] para evitar el error: Error: unexpected string constant.

Facturas <- sqlQuery(canal, "SELECT Pedidos.Destinatario, Pedidos.DirecciónDestinatario, Pedidos.CiudadDestinatario,                          Pedidos.RegiónDestinatario, Pedidos.CódPostalDestinatario, Pedidos.PaísDestinatario, Pedidos.IdCliente, Clientes.NombreCompañía, Clientes.Dirección, Clientes.Ciudad, Clientes.Región, Clientes.CódPostal, Clientes.País, [Nombre] & ' ' & [Apellidos] AS Vendedor, Pedidos.IdPedido, Pedidos.FechaPedido, Pedidos.FechaEntrega, Pedidos.FechaEnvío, [Compañías de envíos].NombreCompañía, [Detalles de pedidos].IdProducto, Productos.NombreProducto, [Detalles de pedidos].PrecioUnidad, [Detalles de pedidos].Cantidad, [Detalles de pedidos].Descuento, CCur([Detalles de pedidos].PrecioUnidad*[Cantidad]*(1-[Descuento])/100)*100 AS PrecioConDescuento, Pedidos.Cargo
FROM Productos INNER JOIN ((Empleados INNER JOIN ([Compañías de envíos] INNER JOIN (Clientes INNER JOIN Pedidos ON Clientes.IdCliente = Pedidos.IdCliente) ON [Compañías de envíos].IdCompañíaEnvíos = Pedidos.FormaEnvío) ON Empleados.IdEmpleado = Pedidos.IdEmpleado) INNER JOIN [Detalles de pedidos] ON Pedidos.IdPedido = [Detalles de pedidos].IdPedido) ON Productos.IdProducto = [Detalles de pedidos].IdProducto")
Source: local data frame [2,155 x 26]

           Destinatario DirecciónDestinatario CiudadDestinatario
1           Wilman Kala         Keskuskatu 45           Helsinki
2           Wilman Kala         Keskuskatu 45           Helsinki
3           Wilman Kala         Keskuskatu 45           Helsinki
4    Toms Spezialitäten         Luisenstr. 48            Münster
5    Toms Spezialitäten         Luisenstr. 48            Münster
6         Hanari Carnes       Rua do Paço, 67     Río de Janeiro
7         Hanari Carnes       Rua do Paço, 67     Río de Janeiro
8         Hanari Carnes       Rua do Paço, 67     Río de Janeiro
9  Victuailles en stock    2, rue du Commerce               Lyon
10 Victuailles en stock    2, rue du Commerce               Lyon
..                  ...                   ...                ...
Variables not shown: RegiónDestinatario (fctr), CódPostalDestinatario (fctr), PaísDestinatario (fctr), IdCliente (fctr), NombreCompañía (fctr), Dirección (fctr), Ciudad (fctr), Región (fctr), CódPostal (fctr), País (fctr), Vendedor (fctr), IdPedido (int), FechaPedido (time), FechaEntrega (time), FechaEnvío (time), NombreCompañía.1 (fctr), IdProducto (int), NombreProducto (fctr), PrecioUnidad (dbl), Cantidad (int), Descuento (dbl), PrecioConDescuento (dbl), Cargo (dbl)

    Creación de tablas

Para crear una tabla en Access a partir de un data frame utilizamos la función sqlSave. Los principales argumentos son:

channel - conexión creada con odbcConnect.
dat - data frame.
tablename - nombre de la tabla creada, por defecto el del data frame.
rownames - valor lógico (TRUE o FALSE) o el nombre de la columna de los nombres de de fila.
addPK - valor lógico, para establecer los rownames (nombres de fila) como clave principal.

# Nombre de la nueva tabla el del data frame 
sqlSave(canal, women, rownames = FALSE) 
# Especificando el nombre de la nueva tabla
sqlSave(canal, women, "mujeres", rownames = FALSE)
# filas (rownames) como clave principal
sqlSave(canal, women, "mujeres", rownames = "filas", addPK = TRUE)

    Actualización de tablas

sqlUpdate actualiza la tabla siempre que las filas ya existan. Si no, generará un error: [RODBC] Failed exec in Update. Los principales argumentos son:

channel - conexión creada con odbcConnect.
dat - data frame.
tablename - nombre de la tabla creada, por defecto el del data frame.
index - columna que empleará como clave principal, común al da addPK - valor lógico, para establecer los rownames (nombres de fila) como clave principal.

Ejemplo 1

# Tabla con clave principal filas
sqlSave(canal, women, "mujeres", rownames = "filas", addPK = TRUE)
# La columna filas es un campo de texto (VARCHAR)
sqlColumns(canal, "mujeres")[c(4, 6)]
  COLUMN_NAME TYPE_NAME
1       filas   VARCHAR
2      height    DOUBLE
3      weight    DOUBLE
Datos originales:

sqlFetch(canal, "mujeres", max = 6)
  filas height weight
1     1     58    115
2     2     59    117
3     3     60    120
4     4     61    123
5     5     62    126
6     6     63    129
# Data frame act con los registros a actualizar
# Por ser filas un campo de texto 
# en la tabla mujeres as.character

filas <- as.character(c(1, 2, 3)) 
height <- c(70, 75, 80)
weight <- c(120, 125, 130)
act <- data.frame(filas, height, weight)
# Actualizamos usando filas como index
sqlUpdate(canal, act, "mujeres", index = "filas")
Datos actualizados:

sqlFetch(canal, "mujeres", max = 6)
  filas height weight
1     1     70    120
2     2     75    125
3     3     80    130
4     4     61    123
5     5     62    126
6     6     63    129

Ejemplo 2

Otro ejemplo actualizando la tabla Clientes de Neptuno.

# Data frame act con los registros a actualizar
IdCliente <- c("ALFKI", "BLAUS", "ANATR", "ANTON")
NombreCompañía <- c("Alfred J. Kwak", "Der Blaue Reiter", 
                    "Anaconda","Anton Pirulero")
act <- data.frame(IdCliente, NombreCompañía)

# Actualización usando la clave principal IdCliente 
sqlUpdate(canal, act, "Clientes", index = "IdCliente") 
  IdCliente     NombreCompañía
1     ALFKI     Alfred J. Kwak
2     ANATR           Anaconda
3     ANTON     Anton Pirulero
4     AROUT    Around the Horn
5     BERGS Berglunds snabbköp
6     BLAUS   Der Blaue Reiter 

Eliminación de tablas

Para eliminar tablas o consultas de la base de datos empleamos la función sqlDrop. Cuidado pues la acción es irreversible.

sqlDrop(channel = canal, "women")

Referencias

2014-11-24

Duplicar forma en PowerPoint

Title

Problema

Cuando copiamos una forma (Ctrl+C) y la volvemos a pegar (Ctrl+V), PowerPoint la presenta desplazada (abajo a la derecha de la original).

Solución

  1. Seleccionamos la forma.
  2. Ctrl+Alt+D para duplicar la forma. Ctrl+D si nuestro PowerPoint está en inglés.
  3. Arrastramos la forma a la posición deseada.
  4. Ctrl+Alt+D de nuevo. La forma se pegará duplicando también la posición relativa respecto del objeto original.

Solución en imágenes

Referencias:

2014-11-20

Calculadora y gráfica de la distribución normal estándar en R

Title Creamos una función muy sencilla para calcular y representar la probabilidad de un área bajo la curva de la función de densidad de la distribución normal estándar N(0, 1).

No solicitará dos valores, el límite inferior x1 y el superior x2. La función pnorm devuelve la probabilidad a la izquierda del valor especificado.

Intervalo: Pr(x1<X<x2) = Pr(X<x2) − Pr(X<x1)

  • Para calcular la probabilidad comprendida dentro de un intervalo, restamos de la probabilidad del límite superior x2 la probabilidad del límite inferior.
Cola izquierda: Pr(X<x2)

  • Para calcular la probabilidad por debajo de un valor, solamente introducimos el límite superior x2. Cuando nos solicite el límite inferior x1, lo dejamos en blanco y presionamos la tecla Entrar.
Cola derecha: Pr(X>x1)

  • Para calcular la probabilidad por encima de un valor, solamente introducimos el límite inferior x1. Cuando no solicite el límite superior x2, lo dejamos en blanco y presionamos la tecla Entrar.

Función

fun <- function(){
# Convertimos vector de carácter a numérico
  x1 <- as.numeric(readline("¿Cuál es el límite inferior x1?"))
  x2 <- as.numeric(readline("¿Cuál es el límite superior x2?"))
# Gestión de errores
  if (is.na(x1))  {
    x1 <- -100
  }
  if (is.na(x2))  {
    x2 <- 100
  }
# Cálculo de probabilidad  
  prob <- pnorm(x2) - pnorm(x1)
# Gráfico
  curve(dnorm(x), xlim = c(-3, 3), las = 1, main = c("Probabilidad:", 
        round(prob, 4)))
# Sombreamos el área
  cord.x <- seq(x1, x2, 0.1)
  cord.y <- dnorm(cord.x)
  polygon(c(x1, cord.x, x2),c(0, cord.y ,0),col = "skyblue")
# Resultado en la consola  
  prob
}

Intervalos

La probabilidad en el intervalos entre -0.6745 y 0.6745.

# Ejecutamos la función
fun()
En la consola nos preguntará los dos límites del intervalo. Escribimos cada uno y presionamos la tecla entrar.

¿Cuál es el valor inferior x1?-0.6745
¿Cuál es el valot superior x2?0.6745
La consola arrojará el resultado:

[1] 0.5000065
Creará el siguiente gráfico con el área sombreada y la probabilidad redondeada en el título del mismo.

Cola de la izquierda

Dejamos el límite inferior en blanco

¿Cuál es el límite inferior x1?
¿Cuál es el límite superior x2?1
[1] 0.8413447

Cola de la derecha

Dejamos el límite superior en blanco

¿Cuál es el límite inferior x1?2.1
¿Cuál es el límite superior x2?
[1] 0.01786442
Entradas relacionadas:

2014-11-18

Regresión lineal simple para principiantes en Excel

Title La regresión lineal simple sirve para evaluar la relación entre dos variables, una variable independiente X o predictora y una variable dependiente o explicada Y. Se trata de encontrar una ecuación lineal con fines predictivos.

Datos

Como ejemplo, usamos los datos del peso corporal y del corazón de una muestra gatos machos y hembras del paquete MASS en R. Importamos o copiamos los datos en Excel. Tendremos 4 columnas con 144 observaciones. Fichero cats.csv

Obs - número de observaciones
Sex - sexo
Bwt - Body Weight, peso corporal
Hwt - Heart Weight, peso del corazón

Diagrama de dispersión

1. Seleccionamos las columnas Bwt y Hwt.
2. En la ficha Insertar, en el grupo Gráficos, hacemos clic en Dispersión.

Recta de regresión y R²

3. Botón secundario sobre los puntos del gráfico y seleccionamos Agregar línea de tendencia.

4. En Opciones de línea de tendencia, por defecto aparece marcado el tipo lineal, y en la parte inferior marcamos Presentar ecuación en el gráfico y Presentar el valor R cuadrado en el gráfico.
5. Formateamos el gráfico apropiadamente

Alternativa

1. En la ficha Presentación, en el grupo Análisis, clic en Línea de tendencia.

2. Clic sobre la línea de tendencia y seleccionamos Formato de línea de tendencia y, en la parte inferior, marcamos Presentar ecuación en el gráfico y Presentar el valor R cuadrado en el gráfico.

Aplicación del modelo

Con la ecuación de la recta de regresión podemos calcular el valor de la variable dependiente Y introduciendo un valor de la variable independiente X en la misma: y = mx + b

Definimos los nombres:

Bwt= =Hoja1!$C$2:$C$145
Hwt = =Hoja1!$D$2:$D$145

Calculamos la pendiente y la intersección en Y:

m - pendiente: =PENDIENTE(Hwt;Bwt)
b - intersección Y: =INTERSECCION.EJE(Hwt;Bwt)

Ejemplos:

Si un gato pesa 5 Kg, ¿cuál es el peso estimado de su corazón?: = 5*4,03406-0,35666 = 19,81365
Si un gato pesa 3 Kg, ¿cuál es el peso estimado de su corazón?: = 3*4,03406-0,35666 = 11,74552

Bondad del modelo

R², el coeficiente de determinación, nos informa de la bondad del ajuste del modelo. Se calcula elevando al cuadrado el coeficiente de correlación de Pearson. Varía entre 0 y 1.

    0 - las variables son independientes
    1 - existe una relación perfecta entre las variables
En nuestro ejemplo es 0,6466. Indica que conociendo el peso de un gato mejoramos un 64,66% nuestra estimación del peso del corazón, si usamos nuestro modelo en lugar del peso medio del corazón de un gato.

Referencias

2014-11-16

Función scan en R: manualmente y desde el portapapeles

Title La función scan nos permite tanto introducir datos directamente en la consola como desde el portapapeles o desde un fichero. En esta entrada trataremos de los dos primeros casos Es necesario especificar el tipo de objeto que importamos: numérico, carácter, complejo o lógico. Por defecto es numérico. Si los datos leídos no corresponden al tipo, ya sea por defecto o especificado a través de what, se genera un mensaje de error. Por ello diferenciaremos números, caracteres o una mezcla de ambos.

La función scan funciona con datos copiados de columnas desde HTML, Excel o desde Access. Si queremos copiar desde una fila, podemos transponerla previamente.

Números

1. Seleccionamos y copiamos los datos que queremos introducir en R. En nuestro caso desde Excel.

2. Ejecutamos el siguiente código en la consola.

x <- scan(dec = ",")
Especificamos el separador decimal coma pues por defecto es el punto y generaría un error.

3. En la consola aparecerá

 x <- scan(dec = ",")
1:
4. Presionamos Ctrl+V o bien botón secundario del ratón y seleccionamos pegar (paste).

> x <- scan(dec = ",")
1: 168,2624113
2: 205,9148936
3: 210
4: 212,3758865
5: 215,9361702
6: 222,9929078
7: 230
8: 231,3404255
9: 234,7588652
10: 240,893617
11: 
Read 10 items
De esta manera habremos creado un vector numérico. Podemos comprobarlo y la suma de 2.172,47 que nos daba en Excel.

str(x)

num [1:10] 168 206 210 212 216 ...
sum(x)

 [1] 2172.475

Caracteres

1. Seleccionamos y copiamos los datos de la columna que queremos introducir en R. En nuestro caso desde Excel, pero también se puede desde Access.

2. Ejecutamos el siguiente código en la consola.

x <- scan(what = character()) # Alternativa 1
x <- scan(what = "") # Alternativa 2
Especificamos el tipo de datos que leerá, caracteres en este caso.

3. En la consola aparecerá

 > x <- scan(what = character())
1:
4. Presionamos Ctrl+V o bien botón secundario del ratón y seleccionamos pegar (paste).

> x <- scan(what = character())
1: a
2: b
3: c
4: d
5: e
6: f
7: g
8: h
9: i
10: j
11: 
Read 10 items
De esta manera habremos creado un vector de caracteres. Podemos comprobarlo con:

str(x)

chr [1:10] "a" "b" "c" "d" "e" "f" "g" "h" "i" "j"

Números y caracteres

En este caso podríamos emplear una lista especificando los tipos para cada ítem.

x <- scan(what = list("", 0, 0, "", "", 0, "", "", "", "")) # Lista
> x <- scan(what = list("", 0, 0, "", "", 0, "", "", "", ""))
1: a
1: 1
1: 2
1: d
1: e
1: 10
1: g
1: h
1: i
1: j
2: 
Read 1 record
str(x)
List of 10
 $ : chr "a"
 $ : num 1
 $ : num 2
 $ : chr "d"
 $ : chr "e"
 $ : num 10
 $ : chr "g"
 $ : chr "h"
 $ : chr "i"
 $ : chr "j"
O bien leer todos como caracteres y manipularlos posteriormente:

x <- scan(what = "") # Como caracteres

Delimitador de campos

Si tratamos de leer números o caracteres con espacios en blanco introducimos el argumento sep para que tratar como delimitador el salto de línea y no el espacio en blanco. De esta manera cada fila será un ítem.

# Para números
x <- scan(sep = "\n")
 x <- scan(sep = "\n")
1: 1 2 4
2: 55 3
3: 88      7
4: 
Read 3 items
# Para texto
x <- scan(what = "", sep = "\n")
> x <- scan(what = "", sep = "\n")
1: APPLIANCES/DEVICES
2: BABY CARE
3: BATH & SHOWER
4: 
Read 3 items

Saltar la primera línea

Por ejemplo, si copiamos el encabezado de la columna y queremos eliminarlo, en nuestro ejemplo Etiquetas de fila. Como estamos pegando directamente desde el portapapeles, aunque especifiquemos el argumento skip = 1, importará la primera línea. Por ello, utilizamos esta alternativa.

x <- scan(what = "", sep = "\n") # Importamos como antes
 > x <- scan(what = "", sep = "\n")
1: Etiquetas de fila
2: APPLIANCES/DEVICES
3: BABY CARE
4: BATH & SHOWER
5: BODY CARE
6: BOOTS
7: CASUAL
8: 
Read 7 items
x <- x[-1] # Eliminamos primer elemento del vector
data.frame(x)
                   x
1 APPLIANCES/DEVICES
2          BABY CARE
3      BATH & SHOWER
4          BODY CARE
5              BOOTS
6             CASUAL

Entrada manual en la consola

En lugar de pegar el contenido, escribimos en la consola.

Nube de datos