library(tidyverse)
-- Attaching packages --------------------------------------- tidyverse 1.2.1 --
v ggplot2 3.1.0     v purrr   0.2.5
v tibble  2.1.3     v dplyr   0.8.3
v tidyr   0.8.2     v stringr 1.3.1
v readr   1.3.1     v forcats 0.3.0
-- Conflicts ------------------------------------------ tidyverse_conflicts() --
x dplyr::filter() masks stats::filter()
x dplyr::lag()    masks stats::lag()
library(sf)
Linking to GEOS 3.6.1, GDAL 2.2.3, PROJ 4.9.3
library(lubridate)

Attaching package: 㤼㸱lubridate㤼㸲

The following object is masked from 㤼㸱package:base㤼㸲:

    date
delitos <- read.csv("./data/delitos.csv")
delitos <- delitos %>%
                sample_n(5000)

Las cinco instrucciones básicas de dplyr

Todas pueden ser usadas en conjunto con group_by() que cambia el “scope” de cada función: en lugar de operar sobre todo el dataset, lo hace al interior de cada grupo definido.

Las cinco instrucciones básicas de dplyr

Estas 6 funciones proveen los verbos para un “lenguaje” de manipulación de datos. Todas funcionan de forma parecida

  1. El primer argumento es un dataframe
  2. Los siguientes argumentos decriben qué hacer con el data frame, usando los nombres de variables sin comillas
  3. El resultado es un nuevo dataframe

Filtrando filas con filter()

Permite subsetear observaciones basados en sus valores.

Filtrando filas con filter()

f <- filter(delitos, 
            comuna=='Comuna 6' | comuna=='Comuna 10')
head(f)

Filtrando filas con filter()

Para usar los filtros de forma efectiva es importante tener en cuenta los operadores que se usan

Un error común:

Operadores lógicos

Filtrando filas con filter()

Seleccionemos los registros que ocurrieron en diciembre y enero

filter(delitos, month(ymd(fecha)) == 1 | month(ymd(fecha)) == 12)

Otra forma:

filter(delitos, month(ymd(fecha)) %in% c(1,12))

Filtrando filas con filter()

Simplificar expresiones complicadas Ley de De Morgan:

rara traer los delitos que NO fueron en la Comuna 1 y NO en el primer trimestre del año, ambas líneas producen el mismo resultado:

filter(delitos, !(comuna=='Comuna 6' | month(ymd(fecha)) > 3))
filter(delitos, (!comuna=='Comuna 6' & !month(ymd(fecha)) > 3))

Filtrando filas con filter()

Missing data

Los NA son tramposos en R.

  • Casi cualquier operación incluyendo un NA va a devolver otro NA
x <- NA
y <- NA
x == y
[1] NA

Filtrando filas con filter()

Missing data

  • Para detectar NA se puede usar la función is.na(x)
is.na(x)
[1] TRUE
df <- data.frame(x = c(1, NA, 3))
filter(df, x > 1)
filter(df, x > 1 | is.na(x))

Ordenando filas con arrange()

f<-arrange(delitos, comuna, ymd(fecha), hms(hora))
head(f)

Ordenando filas con arrange()

f<-arrange(delitos, comuna, desc(ymd(fecha)), desc(hms(hora)))
head(f)

Seleccionando columnas con select()

f<-select(delitos, comuna, barrio, tipo_delito) # Selección por nombre
head(f)
f<-select(delitos, comuna:fecha) # Selección por rango de nombres
head(f)
f<-select(delitos, -(comuna:fecha)) # Selección de todas las columnas excepto las que están en el rango de nombres
head(f)

Seleccionando columnas con select()

Algunas funciones útiles

  • starts_with("abc"): matchea nombres que empiezan con “abc”.
  • ends_with("xyz"): matchea nombres que terminan con “xyz”.
  • contains("ijk"): matchea nombres que contienen con “ijk”.
  • matches("(.)\\1"): selecciona variables que matchean con una regex
  • num_range("x", 1:3): matchea x1, x2 y x3.

Seleccionando columnas con select()

f<-select(delitos, comuna, barrio, tipo_delito, everything())
head(f)

Seleccionando columnas con select()

head(rename(delitos, COMUNA=comuna))

Transformando columnas con mutate()

f<-mutate(delitos, 
          hora_simple = hour(hms(hora)),
          dia=day(ymd(fecha)),
          mes=month(ymd(fecha)),
          year=year(ymd(fecha)))
head(f)

Transformando columnas con mutate()

Algunas operaciones de creación útiles

  • Operadores aritméticos: +, -, *, /, ^, son útiles en conjunción con estadísticos: zscore = (x - mean(x))/sd(x)
  • Logs: log(), log2(), log10(): útiles cuando nos encontramos con datos de escalas muy diversas. También para convertir relaciones multiplicativas en aditivas -sumamente práctico para la etapa de modelado-.
  • Offsets: lead() y lag()
  • Acumuladores: cumsum(), cumprod(), cummin(), cummax(), cummean()

  • Muchos más en R for Data Science

group_by + summarize()

f<-group_by(delitos, f=month(ymd(fecha), label=TRUE))
summarize(f, delay=n())
LS0tDQp0aXRsZTogIkludHJvZHVjY2nDs24gYSBsYSBDaWVuY2lhIGRlIERhdG9zIHBhcmEgQ2llbnTDrWZpY29zIFNvY2lhbGVzIg0Kc3VidGl0bGU6ICJVbmlkYWQgMS4gUHJvZ3JhbWFjacOzbiBFc3RhZMOtc3RpY2EgZW4gUjogSW50cm9kdWNjacOzbiBhIFIgYmFzZSINCmF1dGhvcjogIkRyLiBHZXJtYW4gUm9zYXRpIg0Kb3V0cHV0OiBodG1sX25vdGVib29rDQotLS0NCg0KYGBge3J9DQpsaWJyYXJ5KHRpZHl2ZXJzZSkNCmxpYnJhcnkoc2YpDQpsaWJyYXJ5KGx1YnJpZGF0ZSkNCmBgYCAgICAgDQoNCmBgYHtyLCBlY2hvPVRSVUV9DQpkZWxpdG9zIDwtIHJlYWQuY3N2KCIuLi9kYXRhL2RlbGl0b3MuY3N2IikNCmRlbGl0b3MgPC0gZGVsaXRvcyAlPiUNCiAgICAgICAgICAgICAgICBzYW1wbGVfbig1MDAwKQ0KYGBgDQoNCg0KIyMgTGFzIGNpbmNvIGluc3RydWNjaW9uZXMgYsOhc2ljYXMgZGUgYGRwbHlyYA0KDQoNCiogRWxlZ2lyIG9ic2VydmFjaW9uZXMgZW4gZnVuY2nDs24gYSBzdXMgdmFsb3JlczogYGZpbHRlcigpYC4NCiogUmVvcmRlbmFyIGxhcyBmaWxhcyBgYXJyYW5nZSgpYA0KKiBTZWxlY2Npb25hciB2YXJpYWJsZXMgZGUgYWN1ZXJkbyBhIHN1IG5vbWJyZTogYHNlbGVjdCgpYA0KKiBDcmVhciB2YXJpYWJsZXMgbnVldmFzIGVuIGZ1bmNpw7NuIGRlIHZhcmlhYmxlcyB5YSBleGlzdGVudGVzOiBgbXV0YXRlKClgDQoqIENvbGFwc2FyIHZhbG9yZXMgYSB1biBzb2xvIHJlc3VtZW46IGBzdW1tYXJpc2UoKWANCg0KDQpUb2RhcyBwdWVkZW4gc2VyIHVzYWRhcyBlbiBjb25qdW50byBjb24gYGdyb3VwX2J5KClgIHF1ZSBjYW1iaWEgZWwgInNjb3BlIiBkZSBjYWRhIGZ1bmNpw7NuOiBlbiBsdWdhciBkZSBvcGVyYXIgc29icmUgdG9kbyBlbCBkYXRhc2V0LCBsbyBoYWNlIGFsIGludGVyaW9yIGRlIGNhZGEgZ3J1cG8gZGVmaW5pZG8uDQoNCg0KIyMgTGFzIGNpbmNvIGluc3RydWNjaW9uZXMgYsOhc2ljYXMgZGUgYGRwbHlyYA0KDQpFc3RhcyA2IGZ1bmNpb25lcyBwcm92ZWVuIGxvcyB2ZXJib3MgcGFyYSB1biAibGVuZ3VhamUiIGRlIG1hbmlwdWxhY2nDs24gZGUgZGF0b3MuDQpUb2RhcyBmdW5jaW9uYW4gZGUgZm9ybWEgcGFyZWNpZGENCg0KMS4gRWwgcHJpbWVyIGFyZ3VtZW50byBlcyB1biBkYXRhZnJhbWUNCjIuIExvcyBzaWd1aWVudGVzIGFyZ3VtZW50b3MgZGVjcmliZW4gcXXDqSBoYWNlciBjb24gZWwgZGF0YSBmcmFtZSwgdXNhbmRvIGxvcyBub21icmVzIGRlIHZhcmlhYmxlcyBzaW4gY29taWxsYXMNCjMuIEVsIHJlc3VsdGFkbyBlcyB1biBudWV2byBkYXRhZnJhbWUNCg0KDQojIyBGaWx0cmFuZG8gZmlsYXMgY29uIGBmaWx0ZXIoKWANCg0KUGVybWl0ZSBzdWJzZXRlYXIgb2JzZXJ2YWNpb25lcyBiYXNhZG9zIGVuIHN1cyB2YWxvcmVzLiANCg0KKiBFbCBwcmltZXIgYXJndW1lbnRvIGVzIGVsIGRhdGFmcmFtZQ0KKiBMb3Mgc2lndWllbnRlcywgbGFzIGV4cHJlc2lvbmVzIGZpbHRyYW4gZWwgZGF0YXNldA0KDQojIyBGaWx0cmFuZG8gZmlsYXMgY29uIGBmaWx0ZXIoKWANCiAgICAgICAgDQpgYGB7ciBlY2hvPVRSVUV9DQpmIDwtIGZpbHRlcihkZWxpdG9zLCANCiAgICAgICAgICAgIGNvbXVuYT09J0NvbXVuYSA2JyB8IGNvbXVuYT09J0NvbXVuYSAxMCcpDQpoZWFkKGYpDQpgYGANCg0KIyMgRmlsdHJhbmRvIGZpbGFzIGNvbiBgZmlsdGVyKClgDQpQYXJhIHVzYXIgbG9zIGZpbHRyb3MgZGUgZm9ybWEgZWZlY3RpdmEgZXMgaW1wb3J0YW50ZSB0ZW5lciBlbiBjdWVudGEgbG9zIG9wZXJhZG9yZXMgcXVlIHNlIHVzYW4NCg0KVW4gZXJyb3IgY29tw7puOiANCg0KKiBgZmlsdGVyKGRlbGl0b3MsIGNvbXVuYT0nQ29tdW5hIDYnKWANCg0KIyMjIyBPcGVyYWRvcmVzIGzDs2dpY29zDQohW10oLi4vUm1hcmtkb3ducy9pbWdzL3RyYW5zZm9ybS1sb2dpY2FsLnBuZykNCg0KDQojIyBGaWx0cmFuZG8gZmlsYXMgY29uIGBmaWx0ZXIoKWANClNlbGVjY2lvbmVtb3MgbG9zIHJlZ2lzdHJvcyBxdWUgb2N1cnJpZXJvbiBlbiBkaWNpZW1icmUgeSBlbmVybw0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KZmlsdGVyKGRlbGl0b3MsIG1vbnRoKHltZChmZWNoYSkpID09IDEgfCBtb250aCh5bWQoZmVjaGEpKSA9PSAxMikNCmBgYA0KDQpPdHJhIGZvcm1hOg0KDQoNCmBgYHtyLCBlY2hvPVRSVUV9DQpmaWx0ZXIoZGVsaXRvcywgbW9udGgoeW1kKGZlY2hhKSkgJWluJSBjKDEsMTIpKQ0KYGBgDQoNCg0KIyMgRmlsdHJhbmRvIGZpbGFzIGNvbiBgZmlsdGVyKClgDQpTaW1wbGlmaWNhciBleHByZXNpb25lcyBjb21wbGljYWRhcw0KKkxleSBkZSBEZSBNb3JnYW46Kg0KIA0KKiBgISh4ICYgeSkgPT0gIXggfCAheWANCiogYCEoeCB8IHkpID09ICF4ICYgIXlgDQoNCnJhcmEgdHJhZXIgbG9zIGRlbGl0b3MgcXVlIE5PIGZ1ZXJvbiBlbiBsYSBDb211bmEgMSB5IE5PIGVuIGVsIHByaW1lciB0cmltZXN0cmUgZGVsIGHDsW8sIGFtYmFzIGzDrW5lYXMgcHJvZHVjZW4gZWwgbWlzbW8gcmVzdWx0YWRvOg0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KZmlsdGVyKGRlbGl0b3MsICEoY29tdW5hPT0nQ29tdW5hIDYnIHwgbW9udGgoeW1kKGZlY2hhKSkgPiAzKSkNCmZpbHRlcihkZWxpdG9zLCAoIWNvbXVuYT09J0NvbXVuYSA2JyAmICFtb250aCh5bWQoZmVjaGEpKSA+IDMpKQ0KYGBgDQoNCg0KIyMgRmlsdHJhbmRvIGZpbGFzIGNvbiBgZmlsdGVyKClgDQojIyMgTWlzc2luZyBkYXRhDQoNCkxvcyBgTkFgIHNvbiB0cmFtcG9zb3MgZW4gUi4NCg0KKiBDYXNpIGN1YWxxdWllciBvcGVyYWNpw7NuIGluY2x1eWVuZG8gdW4gYE5BYCB2YSBhIGRldm9sdmVyIG90cm8gYE5BYA0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KeCA8LSBOQQ0KeSA8LSBOQQ0KDQp4ID09IHkNCmBgYA0KDQoNCiMjIEZpbHRyYW5kbyBmaWxhcyBjb24gYGZpbHRlcigpYA0KIyMjIE1pc3NpbmcgZGF0YQ0KDQoqIFBhcmEgZGV0ZWN0YXIgYE5BYCBzZSBwdWVkZSB1c2FyIGxhIGZ1bmNpw7NuIGBpcy5uYSh4KWANCg0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KaXMubmEoeCkNCmBgYA0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KZGYgPC0gZGF0YS5mcmFtZSh4ID0gYygxLCBOQSwgMykpDQoNCmZpbHRlcihkZiwgeCA+IDEpDQoNCmZpbHRlcihkZiwgeCA+IDEgfCBpcy5uYSh4KSkNCmBgYA0KDQojIyBPcmRlbmFuZG8gZmlsYXMgY29uIGBhcnJhbmdlKClgDQoqIGBhcnJhbmdlKClgIGZ1bmNpb25hIGRlIGZvcm1hIHNpbWlsYXIgYSBgZmlsdGVyKClgIHBlcm8gZW4gbHVnYXIgZGUgc2VsZWNjaW9uYXIgZmlsYXMsIGNhbWJpYSBzdSBvcmRlbg0KKiBUb21hIHVuIGRhdGFmcmFtZSB5IHVuIHNldCBkZSBjb2x1bW5hcyAobyBleHByZXNpb25lcyBtw6FzIGNvbXBsaWNhZGFzKQ0KDQoNCmBgYHtyLCBlY2hvPVRSVUV9DQpmPC1hcnJhbmdlKGRlbGl0b3MsIGNvbXVuYSwgeW1kKGZlY2hhKSwgaG1zKGhvcmEpKQ0KaGVhZChmKQ0KYGBgDQoNCiMjIE9yZGVuYW5kbyBmaWxhcyBjb24gYGFycmFuZ2UoKWANCiogVXNhbW9zIGBkZXNjKClgIHBhcmEgb3JkZW5hciBkZSBmb3JtYSBkZXNjZW5kZW50ZQ0KDQpgYGB7ciBlY2hvPVRSVUV9DQpmPC1hcnJhbmdlKGRlbGl0b3MsIGNvbXVuYSwgZGVzYyh5bWQoZmVjaGEpKSwgZGVzYyhobXMoaG9yYSkpKQ0KaGVhZChmKQ0KYGBgDQoNCiogTG9zIGBOQWAgc2llbXByZSBxdWVkYW4gYWwgZmluYWwgZGUgbGEgdGFibGEuDQoNCg0KIyMgU2VsZWNjaW9uYW5kbyBjb2x1bW5hcyBjb24gYHNlbGVjdCgpYA0KKiBFcyBoYWJpdHVhbCBlbmNvbnRyYXJzZSBjb24gZGF0YXNldHMgZGUgY2llbnRvcyBvIG1pbGVzIGRlIHZhcmlhYmxlcy4gDQoqIGBzZWxlY3QoKWAgcGVybWl0ZSBjb25jZW50cmFyc2UgZW4gbGFzIHZhcmlhYmxlcyBxdWUgYSB1bm8gbGUgcmVzdWx0ZW4gcmVsZXZhbnRlcw0KKiBTZSBiYXNhIGVuIGxvcyBub21icmVzIGRlIGxhcyB2YXJpYWJsZXMgDQoNCmBgYHtyLCBlY2hvPVRSVUV9DQpmPC1zZWxlY3QoZGVsaXRvcywgY29tdW5hLCBiYXJyaW8sIHRpcG9fZGVsaXRvKSAjIFNlbGVjY2nDs24gcG9yIG5vbWJyZQ0KaGVhZChmKQ0KDQpmPC1zZWxlY3QoZGVsaXRvcywgY29tdW5hOmZlY2hhKSAjIFNlbGVjY2nDs24gcG9yIHJhbmdvIGRlIG5vbWJyZXMNCmhlYWQoZikNCg0KZjwtc2VsZWN0KGRlbGl0b3MsIC0oY29tdW5hOmZlY2hhKSkgIyBTZWxlY2Npw7NuIGRlIHRvZGFzIGxhcyBjb2x1bW5hcyBleGNlcHRvIGxhcyBxdWUgZXN0w6FuIGVuIGVsIHJhbmdvIGRlIG5vbWJyZXMNCmhlYWQoZikNCmBgYA0KDQojIyBTZWxlY2Npb25hbmRvIGNvbHVtbmFzIGNvbiBgc2VsZWN0KClgDQojIyMgQWxndW5hcyBmdW5jaW9uZXMgw7p0aWxlcw0KDQoqIGBzdGFydHNfd2l0aCgiYWJjIilgOiBtYXRjaGVhIG5vbWJyZXMgcXVlIGVtcGllemFuIGNvbiDigJxhYmPigJ0uDQoqIGBlbmRzX3dpdGgoInh5eiIpYDogbWF0Y2hlYSBub21icmVzIHF1ZSB0ZXJtaW5hbiBjb24g4oCceHl64oCdLg0KKiBgY29udGFpbnMoImlqayIpYDogbWF0Y2hlYSBub21icmVzIHF1ZSBjb250aWVuZW4gY29uIOKAnGlqa+KAnS4NCiogYG1hdGNoZXMoIiguKVxcMSIpYDogc2VsZWNjaW9uYSB2YXJpYWJsZXMgcXVlIG1hdGNoZWFuIGNvbiB1bmEgcmVnZXgNCiogYG51bV9yYW5nZSgieCIsIDE6MylgOiBtYXRjaGVhIHgxLCB4MiB5IHgzLg0KDQoNCiMjIFNlbGVjY2lvbmFuZG8gY29sdW1uYXMgY29uIGBzZWxlY3QoKWANCiogUGFyYSBjYW1iaWFyIGVsIG9yZGVuIGRlIGxhcyBjb2x1bW5hcyBlcyDDunRpbCB1c2FyIGBldmVyeXRoaW5nKClgDQoNCmBgYHtyLCBlY2hvPVRSVUV9DQpmPC1zZWxlY3QoZGVsaXRvcywgY29tdW5hLCBiYXJyaW8sIHRpcG9fZGVsaXRvLCBldmVyeXRoaW5nKCkpDQpoZWFkKGYpDQpgYGANCg0KIyMgU2VsZWNjaW9uYW5kbyBjb2x1bW5hcyBjb24gYHNlbGVjdCgpYA0KKiBQYXJhIHJlbm9tYnJhciBwdWVkZSB1c2Fyc2UgYHJlbmFtZSgpYA0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KaGVhZChyZW5hbWUoZGVsaXRvcywgQ09NVU5BPWNvbXVuYSkpDQpgYGANCg0KIyMgVHJhbnNmb3JtYW5kbyBjb2x1bW5hcyBjb24gYG11dGF0ZSgpYA0KKiBTdWVsZSBzZXIgw7p0aWwgY3JlYXIgbnVldmFzIGNvbHVtbmFzIGNvbW8gZnVuY2lvbmVzIGRlIGNvbHVtbmFzIHlhIGV4aXN0ZW50ZXMuDQoqIGBtdXRhdGUoKWAgc2llbXByZSBhZ3JlZ2EgbnVldmFzIGNvbHVtbmFzIGFsIGZpbmFsIGRlbCBkYXRhc2V0DQoNCmBgYHtyLCBlY2hvPVRSVUV9DQpmPC1tdXRhdGUoZGVsaXRvcywgDQogICAgICAgICAgaG9yYV9zaW1wbGUgPSBob3VyKGhtcyhob3JhKSksDQogICAgICAgICAgZGlhPWRheSh5bWQoZmVjaGEpKSwNCiAgICAgICAgICBtZXM9bW9udGgoeW1kKGZlY2hhKSksDQogICAgICAgICAgeWVhcj15ZWFyKHltZChmZWNoYSkpKQ0KaGVhZChmKQ0KYGBgDQoNCiMjIFRyYW5zZm9ybWFuZG8gY29sdW1uYXMgY29uIGBtdXRhdGUoKWANCiMjIyBBbGd1bmFzIG9wZXJhY2lvbmVzIGRlIGNyZWFjacOzbiDDunRpbGVzDQoNCiogT3BlcmFkb3JlcyBhcml0bcOpdGljb3M6IGArYCwgYC1gLCBgKmAsIGAvYCwgYF5gLCBzb24gw7p0aWxlcyBlbiBjb25qdW5jacOzbiBjb24gZXN0YWTDrXN0aWNvczoNCmB6c2NvcmUgPSAoeCAtIG1lYW4oeCkpL3NkKHgpYA0KKiBMb2dzOiBgbG9nKClgLCBgbG9nMigpYCwgYGxvZzEwKClgOiDDunRpbGVzIGN1YW5kbyBub3MgZW5jb250cmFtb3MgY29uIGRhdG9zIGRlIGVzY2FsYXMgbXV5IGRpdmVyc2FzLiBUYW1iacOpbiBwYXJhIGNvbnZlcnRpciByZWxhY2lvbmVzIG11bHRpcGxpY2F0aXZhcyBlbiBhZGl0aXZhcyAtc3VtYW1lbnRlIHByw6FjdGljbyBwYXJhIGxhIGV0YXBhIGRlIG1vZGVsYWRvLS4NCiogT2Zmc2V0czogYGxlYWQoKWAgeSBgbGFnKClgDQoqIEFjdW11bGFkb3JlczogYGN1bXN1bSgpYCwgYGN1bXByb2QoKWAsIGBjdW1taW4oKWAsIGBjdW1tYXgoKWAsIGBjdW1tZWFuKClgDQouLi4NCg0KKiBNdWNob3MgbcOhcyBlbiBbUiBmb3IgRGF0YSBTY2llbmNlXShodHRwczovL3I0ZHMuaGFkLmNvLm56L3RyYW5zZm9ybS5odG1sI2FkZC1uZXctdmFyaWFibGVzLXdpdGgtbXV0YXRlKQ0KDQoNCiMjIGBncm91cF9ieWAgKyBgc3VtbWFyaXplKClgDQoqIGBncm91cF9ieWAgY2FtYmlhIGxhIHVuaWRhZCBkZSBhbsOhbHNpc2kgZGVsIGRhdGFzZXQgYSBncnVwb3MuIEFzw60sIGFsIGxsYW1hciBhIGN1YWxxeXVlciB2ZXJibyBkZSBgZHBseXJgIHNlIGFwbGljYSAicG9yIGdydXBvIiwNCiogQ09udGVvIGRlIGRlbGl0b3MgcG9yIG1lcw0KDQpgYGB7ciwgZWNobz1UUlVFfQ0KZjwtZ3JvdXBfYnkoZGVsaXRvcywgZj1tb250aCh5bWQoZmVjaGEpLCBsYWJlbD1UUlVFKSkNCnN1bW1hcml6ZShmLCBkZWxheT1uKCkpDQpgYGANCg==