Creando tablas de resumen

En una hoja de cálculo, las tablas dinámicas o pivot tables son potentes herramientas para resumir los datos de diferentes maneras. Podemos crear estas tablas utilizando las funciones group_by y summarize del paquete dplyr.

Echemos un vistazo a nuestro informe, justo después de leer los datos, creamos una tabla de resumen con el número de ensayos y el rendimiento media de cada cultivar de nuestro conjunto de datos.

Podemos utilizar group_by() para agrupar nuestros datos por cultivar y summarize() para calcular el número de ensayos y el rendimiento_ajustado medio para cada grupo.

cultivares %>% 
  group_by(Cultivar) %>% 
  summarise(cantidad = n(),
            rendimiento_ajustado_medio = round(mean(Rendimiento_Ajustado, na.rm = TRUE), 2))
## # A tibble: 19 × 3
##    Cultivar        cantidad rendimiento_ajustado_medio
##    <chr>              <int>                      <dbl>
##  1 ACA 203                3                      2309 
##  2 ACA 203 CL            57                      3089.
##  3 ACA 203 CL DM          3                      3771.
##  4 ACA 211 CL             9                      2870.
##  5 ACA 350 CL PLUS       18                      3439.
##  6 ACA 769                1                      3744 
##  7 ACA 861              185                      3004.
##  8 ACA 862                1                      3483 
##  9 ACA 862 HO            14                      2673.
## 10 ACA 863               82                      3022.
## 11 ACA 864 DM            31                      3474.
## 12 ACA 865               12                      3256.
## 13 ACA 866 HO            21                      2846.
## 14 ACA 867               43                      3394.
## 15 ACA 868 HO            15                      3645.
## 16 ACA 876                1                      1691 
## 17 ACA 884                1                      1654 
## 18 ACA 885                1                      1574 
## 19 ACA 886                1                      1588

La función n() devuelve el número de casos y la función mean calcula la media o promedio. El parámetro na.rm = TRUE indica a la función que elimine los valores faltantes (NA) antes de realizar el cálculo.

Pregunta: ¿Qué pasa si no se utiliza group_by() antes de summarise()? Probémoslo y discutamos lo que ocurre.

cultivares %>% 
  summarise(cantidad = n(),
            rendimiento_ajustado_medio = round(mean(Rendimiento_Ajustado, na.rm = TRUE), 2))
## # A tibble: 1 × 2
##   cantidad rendimiento_ajustado_medio
##      <int>                      <dbl>
## 1      499                      3094.

Así que si no agrupamos por el cultivar primero, obtendremos una sola estadística de resumen (n y media en este caso) para todo el conjunto de datos.

Ahora, queremos la media del rendimiento en toneladas y con dos decimales. Podemos cambiar nuestra llamada a summarise() para obtener ese cálculo.

cultivares %>% 
  group_by(Cultivar) %>% 
  summarise(cantidad = n(),
            rendimiento_ajustado_medio = round(mean(Rendimiento_Ajustado/1000, na.rm = TRUE), 2))
## # A tibble: 19 × 3
##    Cultivar        cantidad rendimiento_ajustado_medio
##    <chr>              <int>                      <dbl>
##  1 ACA 203                3                       2.31
##  2 ACA 203 CL            57                       3.09
##  3 ACA 203 CL DM          3                       3.77
##  4 ACA 211 CL             9                       2.87
##  5 ACA 350 CL PLUS       18                       3.44
##  6 ACA 769                1                       3.74
##  7 ACA 861              185                       3   
##  8 ACA 862                1                       3.48
##  9 ACA 862 HO            14                       2.67
## 10 ACA 863               82                       3.02
## 11 ACA 864 DM            31                       3.47
## 12 ACA 865               12                       3.26
## 13 ACA 866 HO            21                       2.85
## 14 ACA 867               43                       3.39
## 15 ACA 868 HO            15                       3.65
## 16 ACA 876                1                       1.69
## 17 ACA 884                1                       1.65
## 18 ACA 885                1                       1.57
## 19 ACA 886                1                       1.59

Primero dividimos el rendimiento ajustado por 1000 para transformarlo de kilogramos a toneladas y luego utilizamos la función round() para redondear a sólo dos decimales.

Ahora estamos en el punto en el que queremos guardar esta información resumida como una variable para poder utilizarla en posteriores análisis y formatos.

Así que vamos a añadir una asignación de variable a esa primera línea:

resumen <- cultivares %>% 
  group_by(Cultivar) %>% 
  summarise(cantidad = n(),
            rendimiento_ajustado_medio = round(mean(Rendimiento_Ajustado/1000, na.rm = TRUE), 2))

Dándole formato a la tabla

Para que nuestra tabla se vea mejor en un informe, tenemos que cambiar algunos de sus elementos. Por ejemplo, el nombre de las variables debe ser informativo para una persona (de momento son nombres útiles para una computadora), y podemos añadirle un título y cambiar la alineación de los números.

Podemos hacerlo con la función kable.

resumen %>% 
  knitr::kable(col.names = c("Cultivar", "Cantidad", "Rendimiento Ajustado Medio"),
               align = "lcc",
               caption = "Resumen de los Cultivares en el dataset.")
Resumen de los Cultivares en el dataset.
Cultivar Cantidad Rendimiento Ajustado Medio
ACA 203 3 2.31
ACA 203 CL 57 3.09
ACA 203 CL DM 3 3.77
ACA 211 CL 9 2.87
ACA 350 CL PLUS 18 3.44
ACA 769 1 3.74
ACA 861 185 3.00
ACA 862 1 3.48
ACA 862 HO 14 2.67
ACA 863 82 3.02
ACA 864 DM 31 3.47
ACA 865 12 3.26
ACA 866 HO 21 2.85
ACA 867 43 3.39
ACA 868 HO 15 3.65
ACA 876 1 1.69
ACA 884 1 1.65
ACA 885 1 1.57
ACA 886 1 1.59

Podemos hacer mucho más con otras funciones (o “verbos”) de dplyr. Veamos algunos más.

Creando nuevas variables

Muchas veces querremos trabajar con información que se deriva de los datos originales. Esto se suele hacer añadiendo una nueva columna. Lo hacemos con la función mutate().

Podemos añadir una nueva variable (llamada prop) que represente la proporción de ensayos en cada localidad con el uso de mutate().

cultivares %>% 
  group_by(Localidad) %>% 
  summarise(cantidad = n(),
            rendimiento_ajustado_medio = round(mean(Rendimiento_Ajustado, na.rm = TRUE), 2)) %>%
  mutate(prop = cantidad/nrow(cultivares))
## # A tibble: 58 × 4
##    Localidad cantidad rendimiento_ajustado_medio    prop
##    <chr>        <int>                      <dbl>   <dbl>
##  1 Anguil          21                      3156. 0.0421 
##  2 Ascasubi         5                      4996. 0.0100 
##  3 Asturias         7                      4216. 0.0140 
##  4 Balcarce        59                      2856. 0.118  
##  5 Barrow          34                      2665. 0.0681 
##  6 Bellocq         31                      3899. 0.0621 
##  7 Bolívar          5                      3931  0.0100 
##  8 Bordenave        3                      4624  0.00601
##  9 Bulnes          11                      2980. 0.0220 
## 10 Carhue           2                      2879  0.00401
## # ℹ 48 more rows

Filtrando los datos

En nuestro informe también realizamos un gráfico de un cultivar específico. Para ello necesitamos mantener sólo los datos del cultivar que queremos analizar. Utilizamos la función filter() para filtrar filas de un data.frame, esta función devuelve un nuevo data.frame con sólo las filas que satisfacen algunas condiciones.

Podemos utilizar operadores lógicos (>, <, >=, <=, ==) para crear condiciones a partir de variables numéricas. Estos operadores también son útiles para fechas y cadenas de texto. El siguiente código aplica una condición (“que sea igual a”) para datos de tipo texto (la columna especie).

cultivares %>% 
  filter(Cultivar == "ACA 861")
## # A tibble: 185 × 21
##    Cultivar Empresa Floracion_dias Altura_cm Densidad_sem Rendimiento
##    <chr>    <chr>            <dbl>     <dbl>        <dbl>       <dbl>
##  1 ACA 861  ACA                 62       181        66229        4571
##  2 ACA 861  ACA                 68       129        53345        2598
##  3 ACA 861  ACA                 74       149        54286        2902
##  4 ACA 861  ACA                 73       156        42682        3097
##  5 ACA 861  ACA                 61       155        44818        3316
##  6 ACA 861  ACA                 68        NA        44193        4140
##  7 ACA 861  ACA                 69       167        40001        4201
##  8 ACA 861  ACA                 69       168        40650        3200
##  9 ACA 861  ACA                 72       173        56260        3858
## 10 ACA 861  ACA                 71        NA        52858        4464
## # ℹ 175 more rows
## # ℹ 15 more variables: Aceite_porcentaje <dbl>, Rendimiento_Ajustado <dbl>,
## #   Campania <chr>, Localidad <chr>, Latitud <dbl>, Longitud <dbl>,
## #   Ensayo <chr>, `Tipo Ensayo` <chr>, Epoca <chr>, Distancia_surcos <dbl>,
## #   Tipo_Siembra <chr>, Densidad_siembra <dbl>, Fecha_Siembra <chr>,
## #   Testigo <chr>, Visible <chr>

Actividad: Escribe el código necesario para filtrar todos los ensayos de la localidad Anguil.

Actividad: Ahora escribe el código para filtrar todos los cultivares con un rendimiento mayor a 5000 kg/ha.

LS0tDQp0aXRsZTogIk1hbmlwdWxhbmRvIGRhdG9zIg0Kb3V0cHV0OiANCiAgaHRtbF9kb2N1bWVudDoNCiAgICBjb2RlX2Rvd25sb2FkOiB0cnVlDQogICAgdG9jOiB0cnVlDQogICAgdG9jX2Zsb2F0OiBmYWxzZQ0KICAgIGhpZ2hsaWdodDogdGFuZ28NCi0tLQ0KDQpgYGB7ciBzZXR1cCwgaW5jbHVkZT1GQUxTRX0NCmtuaXRyOjpvcHRzX2NodW5rJHNldCgNCgllY2hvID0gVFJVRSwNCgltZXNzYWdlID0gRkFMU0UsDQoJd2FybmluZyA9IEZBTFNFDQopDQoNCmxpYnJhcnkodGlkeXZlcnNlKQ0KY3VsdGl2YXJlcyA8LSByZWFkX2NzdigiZGF0b3MvUk5HX3NtYWxsLmNzdiIpDQpgYGANCg0KIyMgQ3JlYW5kbyB0YWJsYXMgZGUgcmVzdW1lbg0KDQpFbiB1bmEgaG9qYSBkZSBjw6FsY3VsbywgbGFzIHRhYmxhcyBkaW7DoW1pY2FzIG8gcGl2b3QgdGFibGVzIHNvbiBwb3RlbnRlcyBoZXJyYW1pZW50YXMgcGFyYSByZXN1bWlyIGxvcyBkYXRvcyBkZSBkaWZlcmVudGVzIG1hbmVyYXMuIFBvZGVtb3MgY3JlYXIgZXN0YXMgdGFibGFzIHV0aWxpemFuZG8gbGFzIGZ1bmNpb25lcyBgZ3JvdXBfYnlgIHkgYHN1bW1hcml6ZWAgZGVsIHBhcXVldGUgZHBseXIuIA0KDQpFY2hlbW9zIHVuIHZpc3Rhem8gYSBudWVzdHJvIGluZm9ybWUsIGp1c3RvIGRlc3B1w6lzIGRlIGxlZXIgbG9zIGRhdG9zLCBjcmVhbW9zIHVuYSB0YWJsYSBkZSByZXN1bWVuIGNvbiBlbCBuw7ptZXJvIGRlIGVuc2F5b3MgeSBlbCByZW5kaW1pZW50byBtZWRpYSBkZSBjYWRhIGN1bHRpdmFyIGRlIG51ZXN0cm8gY29uanVudG8gZGUgZGF0b3MuDQoNClBvZGVtb3MgdXRpbGl6YXIgYGdyb3VwX2J5KClgIHBhcmEgYWdydXBhciBudWVzdHJvcyBkYXRvcyBwb3IgKipjdWx0aXZhcioqIHkgYHN1bW1hcml6ZSgpYCBwYXJhIGNhbGN1bGFyIGVsIG7Dum1lcm8gZGUgZW5zYXlvcyB5IGVsICoqcmVuZGltaWVudG9fYWp1c3RhZG8qKiBtZWRpbyBwYXJhIGNhZGEgZ3J1cG8uDQoNCmBgYHtyfQ0KDQpjdWx0aXZhcmVzICU+JSANCiAgZ3JvdXBfYnkoQ3VsdGl2YXIpICU+JSANCiAgc3VtbWFyaXNlKGNhbnRpZGFkID0gbigpLA0KICAgICAgICAgICAgcmVuZGltaWVudG9fYWp1c3RhZG9fbWVkaW8gPSByb3VuZChtZWFuKFJlbmRpbWllbnRvX0FqdXN0YWRvLCBuYS5ybSA9IFRSVUUpLCAyKSkNCg0KYGBgDQoNCkxhIGZ1bmNpw7NuIGBuKClgIGRldnVlbHZlIGVsIG7Dum1lcm8gZGUgY2Fzb3MgeSBsYSBmdW5jacOzbiBgbWVhbmAgY2FsY3VsYSBsYSBtZWRpYSBvIHByb21lZGlvLiBFbCBwYXLDoW1ldHJvIGBuYS5ybSA9IFRSVUVgIGluZGljYSBhIGxhIGZ1bmNpw7NuIHF1ZSBlbGltaW5lIGxvcyB2YWxvcmVzIGZhbHRhbnRlcyAoYE5BYCkgYW50ZXMgZGUgcmVhbGl6YXIgZWwgY8OhbGN1bG8uDQoNCj4gUHJlZ3VudGE6IMK/UXXDqSBwYXNhIHNpIG5vIHNlIHV0aWxpemEgYGdyb3VwX2J5KClgIGFudGVzIGRlIGBzdW1tYXJpc2UoKWA/IFByb2LDqW1vc2xvIHkgZGlzY3V0YW1vcyBsbyBxdWUgb2N1cnJlLg0KDQpgYGB7cn0NCmN1bHRpdmFyZXMgJT4lIA0KICBzdW1tYXJpc2UoY2FudGlkYWQgPSBuKCksDQogICAgICAgICAgICByZW5kaW1pZW50b19hanVzdGFkb19tZWRpbyA9IHJvdW5kKG1lYW4oUmVuZGltaWVudG9fQWp1c3RhZG8sIG5hLnJtID0gVFJVRSksIDIpKQ0KYGBgDQoNCkFzw60gcXVlIHNpIG5vIGFncnVwYW1vcyBwb3IgZWwgY3VsdGl2YXIgcHJpbWVybywgb2J0ZW5kcmVtb3MgdW5hIHNvbGEgZXN0YWTDrXN0aWNhIGRlIHJlc3VtZW4gKG4geSBtZWRpYSBlbiBlc3RlIGNhc28pIHBhcmEgdG9kbyBlbCBjb25qdW50byBkZSBkYXRvcy4NCg0KQWhvcmEsIHF1ZXJlbW9zIGxhIG1lZGlhIGRlbCByZW5kaW1pZW50byBlbiB0b25lbGFkYXMgeSBjb24gZG9zIGRlY2ltYWxlcy4gUG9kZW1vcyBjYW1iaWFyIG51ZXN0cmEgbGxhbWFkYSBhIGBzdW1tYXJpc2UoKWAgcGFyYSBvYnRlbmVyIGVzZSBjw6FsY3Vsby4gIA0KDQpgYGB7cn0NCmN1bHRpdmFyZXMgJT4lIA0KICBncm91cF9ieShDdWx0aXZhcikgJT4lIA0KICBzdW1tYXJpc2UoY2FudGlkYWQgPSBuKCksDQogICAgICAgICAgICByZW5kaW1pZW50b19hanVzdGFkb19tZWRpbyA9IHJvdW5kKG1lYW4oUmVuZGltaWVudG9fQWp1c3RhZG8vMTAwMCwgbmEucm0gPSBUUlVFKSwgMikpDQoNCmBgYA0KDQpQcmltZXJvIGRpdmlkaW1vcyBlbCByZW5kaW1pZW50byBhanVzdGFkbyBwb3IgMTAwMCBwYXJhIHRyYW5zZm9ybWFybG8gZGUga2lsb2dyYW1vcyBhIHRvbmVsYWRhcyB5IGx1ZWdvIHV0aWxpemFtb3MgbGEgZnVuY2nDs24gYHJvdW5kKClgIHBhcmEgcmVkb25kZWFyIGEgc8OzbG8gZG9zIGRlY2ltYWxlcy4NCg0KQWhvcmEgZXN0YW1vcyBlbiBlbCBwdW50byBlbiBlbCBxdWUgcXVlcmVtb3MgZ3VhcmRhciBlc3RhIGluZm9ybWFjacOzbiByZXN1bWlkYSBjb21vIHVuYSB2YXJpYWJsZSBwYXJhIHBvZGVyIHV0aWxpemFybGEgZW4gcG9zdGVyaW9yZXMgYW7DoWxpc2lzIHkgZm9ybWF0b3MuDQoNCkFzw60gcXVlIHZhbW9zIGEgYcOxYWRpciB1bmEgYXNpZ25hY2nDs24gZGUgdmFyaWFibGUgYSBlc2EgcHJpbWVyYSBsw61uZWE6DQoNCmBgYHtyfQ0KcmVzdW1lbiA8LSBjdWx0aXZhcmVzICU+JSANCiAgZ3JvdXBfYnkoQ3VsdGl2YXIpICU+JSANCiAgc3VtbWFyaXNlKGNhbnRpZGFkID0gbigpLA0KICAgICAgICAgICAgcmVuZGltaWVudG9fYWp1c3RhZG9fbWVkaW8gPSByb3VuZChtZWFuKFJlbmRpbWllbnRvX0FqdXN0YWRvLzEwMDAsIG5hLnJtID0gVFJVRSksIDIpKQ0KYGBgDQoNCiMjIETDoW5kb2xlIGZvcm1hdG8gYSBsYSB0YWJsYQ0KDQpQYXJhIHF1ZSBudWVzdHJhIHRhYmxhIHNlIHZlYSBtZWpvciBlbiB1biBpbmZvcm1lLCB0ZW5lbW9zIHF1ZSBjYW1iaWFyIGFsZ3Vub3MgZGUgc3VzIGVsZW1lbnRvcy4gUG9yIGVqZW1wbG8sIGVsIG5vbWJyZSBkZSBsYXMgdmFyaWFibGVzIGRlYmUgc2VyIGluZm9ybWF0aXZvIHBhcmEgdW5hIHBlcnNvbmEgKGRlIG1vbWVudG8gc29uIG5vbWJyZXMgw7p0aWxlcyBwYXJhIHVuYSBjb21wdXRhZG9yYSksIHkgcG9kZW1vcyBhw7FhZGlybGUgdW4gdMOtdHVsbyB5IGNhbWJpYXIgbGEgYWxpbmVhY2nDs24gZGUgbG9zIG7Dum1lcm9zLg0KDQpQb2RlbW9zIGhhY2VybG8gY29uIGxhIGZ1bmNpw7NuIGBrYWJsZWAuDQoNCmBgYHtyfQ0KcmVzdW1lbiAlPiUgDQogIGtuaXRyOjprYWJsZShjb2wubmFtZXMgPSBjKCJDdWx0aXZhciIsICJDYW50aWRhZCIsICJSZW5kaW1pZW50byBBanVzdGFkbyBNZWRpbyIpLA0KICAgICAgICAgICAgICAgYWxpZ24gPSAibGNjIiwNCiAgICAgICAgICAgICAgIGNhcHRpb24gPSAiUmVzdW1lbiBkZSBsb3MgQ3VsdGl2YXJlcyBlbiBlbCBkYXRhc2V0LiIpDQpgYGANCg0KUG9kZW1vcyBoYWNlciBtdWNobyBtw6FzIGNvbiBvdHJhcyBmdW5jaW9uZXMgKG8gInZlcmJvcyIpIGRlIGRwbHlyLiBWZWFtb3MgYWxndW5vcyBtw6FzLg0KDQojIyBDcmVhbmRvIG51ZXZhcyB2YXJpYWJsZXMNCg0KTXVjaGFzIHZlY2VzIHF1ZXJyZW1vcyB0cmFiYWphciBjb24gaW5mb3JtYWNpw7NuIHF1ZSBzZSBkZXJpdmEgZGUgbG9zIGRhdG9zIG9yaWdpbmFsZXMuIEVzdG8gc2Ugc3VlbGUgaGFjZXIgYcOxYWRpZW5kbyB1bmEgbnVldmEgY29sdW1uYS4gTG8gaGFjZW1vcyBjb24gbGEgZnVuY2nDs24gYG11dGF0ZSgpYC4NCg0KUG9kZW1vcyBhw7FhZGlyIHVuYSBudWV2YSB2YXJpYWJsZSAobGxhbWFkYSBgcHJvcGApIHF1ZSByZXByZXNlbnRlIGxhIHByb3BvcmNpw7NuIGRlIGVuc2F5b3MgZW4gY2FkYSAqKmxvY2FsaWRhZCoqIGNvbiBlbCB1c28gZGUgYG11dGF0ZSgpYC4gDQoNCmBgYHtyfQ0KDQpjdWx0aXZhcmVzICU+JSANCiAgZ3JvdXBfYnkoTG9jYWxpZGFkKSAlPiUgDQogIHN1bW1hcmlzZShjYW50aWRhZCA9IG4oKSwNCiAgICAgICAgICAgIHJlbmRpbWllbnRvX2FqdXN0YWRvX21lZGlvID0gcm91bmQobWVhbihSZW5kaW1pZW50b19BanVzdGFkbywgbmEucm0gPSBUUlVFKSwgMikpICU+JQ0KICBtdXRhdGUocHJvcCA9IGNhbnRpZGFkL25yb3coY3VsdGl2YXJlcykpDQoNCmBgYA0KDQojIyBGaWx0cmFuZG8gbG9zIGRhdG9zDQoNCkVuIG51ZXN0cm8gaW5mb3JtZSB0YW1iacOpbiByZWFsaXphbW9zIHVuIGdyw6FmaWNvIGRlIHVuIGN1bHRpdmFyIGVzcGVjw61maWNvLiBQYXJhIGVsbG8gbmVjZXNpdGFtb3MgbWFudGVuZXIgc8OzbG8gbG9zIGRhdG9zIGRlbCBjdWx0aXZhciBxdWUgcXVlcmVtb3MgYW5hbGl6YXIuICBVdGlsaXphbW9zIGxhIGZ1bmNpw7NuIGBmaWx0ZXIoKWAgcGFyYSBmaWx0cmFyIGZpbGFzIGRlIHVuIGRhdGEuZnJhbWUsIGVzdGEgZnVuY2nDs24gZGV2dWVsdmUgdW4gbnVldm8gZGF0YS5mcmFtZSBjb24gc8OzbG8gbGFzIGZpbGFzIHF1ZSBzYXRpc2ZhY2VuIGFsZ3VuYXMgY29uZGljaW9uZXMuDQoNClBvZGVtb3MgdXRpbGl6YXIgb3BlcmFkb3JlcyBsw7NnaWNvcyAoYD5gLCBgPGAsIGA+PWAsIGA8PWAsIGA9PWApIHBhcmEgY3JlYXIgY29uZGljaW9uZXMgYSBwYXJ0aXIgZGUgdmFyaWFibGVzIG51bcOpcmljYXMuIEVzdG9zIG9wZXJhZG9yZXMgdGFtYmnDqW4gc29uIMO6dGlsZXMgcGFyYSBmZWNoYXMgeSBjYWRlbmFzIGRlIHRleHRvLiBFbCBzaWd1aWVudGUgY8OzZGlnbyBhcGxpY2EgdW5hIGNvbmRpY2nDs24gKCJxdWUgc2VhIGlndWFsIGEiKSBwYXJhIGRhdG9zIGRlIHRpcG8gdGV4dG8gKGxhIGNvbHVtbmEgZXNwZWNpZSkuDQoNCmBgYHtyfQ0KY3VsdGl2YXJlcyAlPiUgDQogIGZpbHRlcihDdWx0aXZhciA9PSAiQUNBIDg2MSIpDQpgYGANCg0KPiBBY3RpdmlkYWQ6IEVzY3JpYmUgZWwgY8OzZGlnbyBuZWNlc2FyaW8gcGFyYSBmaWx0cmFyIHRvZG9zIGxvcyBlbnNheW9zIGRlIGxhIGxvY2FsaWRhZCBBbmd1aWwuDQoNCj4gQWN0aXZpZGFkOiBBaG9yYSBlc2NyaWJlIGVsIGPDs2RpZ28gcGFyYSBmaWx0cmFyIHRvZG9zIGxvcyBjdWx0aXZhcmVzIGNvbiB1biByZW5kaW1pZW50byBtYXlvciBhIDUwMDAga2cvaGEuDQoNCg==