library("tidyverse") # Muchas cosas cool

# Incluidas en tidyverse, en caso de errores cargandolo
library("dplyr")     # Manipulación de datos mediante gramatica propia
library("magrittr")  # Operadores cañeria (pipes) %>%)
library("readr")     # Traducción (pharsing) de archivos a una tibble
library("stringr")   # Operadores consistentes para strings

La función mutate() de dplyr permite crear nuevas variables manteniendo las ya existentes. Por ejemplo, sacando el promedio de dos variables u operaciones similares.

# Importando datos de un CSV
data.location <- 'https://raw.githubusercontent.com/DeepenData/clases/master/06_mutate_pipes_regex/data_oct_08_2020.csv' # Reemplazar por dirección local si bajan el archivo
sim.without.outliers <- read_csv(data.location) # Importa la data a "sim.without.outliers"

Utilizando mutate para manipulación de datos

Accediendo a datos tabulados

La gramatica de R utiliza [] y $ para acceder a objetos dentro de una estructura de datos. Con un dataframe como el sacado de un CSV, esto son las filas, columnas, celdas individuales, etc. Dado que un dataframe puede contener dataframes, este modo de acceso puede ir varios niveles de profundidad .

  • sim.without.outliers$1 saca la primera como vector
  • sim.without.outliers[1] saca la columna 1
  • sim.without.outliers[ ,c(1,6)] saca las columnas 1 y 6
  • sim.without.outliers[ ,c(1:6)] saca las columnas de 1 a 6
  • sim.without.outliers[ ,-c(1,6)] saca todas las columnas menos la 1 y 6
  • sim.without.outliers[c(10:110) ,c(2:6)] saca las filas 10 a 110 (100 en total) de las columnas 2 a 6
  • sim.without.outliers[[1]] Sacamos la columna 1 como vector
# Accediendo a data en un objeto
sim.without.outliers[c(10:200) , -c(1:2)] %>% rowMeans
##   [1]  139729846  403769779  234968788   92103404  313284946 1986643266
##   [7]  185451555   96949821  297823265  242665441  196689926  221408800
##  [13]  697139689  294169896  466591033  130369358  221895861  193585278
##  [19]  323598926  114885079  169819294  296689100  204991230  363420937
##  [25] 1273488639 1415642358  751130039  219287099 1563532695  156000468
##  [31]  163044979  196698725  937558479  154535089  433849482  265089467
##  [37]  176242474  114132862 1759893346  363406125  352426298 1044366175
##  [43]  217210021  139208188   61625723  214466955 2319197368  341474397
##  [49]  315602657  959714222  231168455  340082205 1702837213   71141852
##  [55]   53590128   69835464  849104264  316974795  669475074  239267080
##  [61]  138415788   38084241  122917363  707210452  131371803   80951210
##  [67]  317049039  387806781  402019145   89318005   42766989  100954015
##  [73]  242148670   91210924  177894231  464119826  424034496  890335348
##  [79]  474612349  302939270  506484703 1423200472  144241227  185573951
##  [85]  226552549  220726226  190740330  134159135  142220681  243602376
##  [91]  589350273  306984211  809625162  149428841  108687956  340960733
##  [97]  574932184  480901622  238201412 1933132104  236258554  159149151
## [103]  262820305  416437439 1102423653  140017375  182516403  621130490
## [109]  153334103  306507300  479508331 3469022045  146495781  442771648
## [115]  228733701  819689414  299310438  204691347   89564724  281922746
## [121] 1048251440  251089685  337268681 1403280232  310831822  183285718
## [127]   65256307  636942314  353517291  752791078  518799772  699126693
## [133]  380430492 1612209546  169167132  238439583  504001844  153499925
## [139]  203339788  501007077  720071937  514661942  128704058  179853953
## [145]  386816373   56670410  228352427  459598946  504996276   81775682
## [151]  149113060  391979457  289189643 1345879436  151710336  615610679
## [157]  612782783  273949798  210046600  132733280  265878974  260044842
## [163]  607307774  150602719  636874776  212049659  171202362  370767704
## [169]  197661137  174662130  532279756  869478213  476075536  413874167
## [175]  175618194  160299360  227732659  121155779  355542686  177362600
## [181]  294619732  247363565  249091282  964198873  309077761  195145767
## [187]  180927522  745479145  941136589  270529420  115453214
sim.without.outliers['treatment_1']/sim.without.outliers['treatment_2'] %>% log2 -> hola

sim.without.outliers$nueva_columna <- hola # Llena la columna con "hola"
sim.without.outliers$nueva_columna <- NULL # Elimina una columna

Para trabajar con columnas en un dataframe, usamos dplyr::mutate(). Esto crea una nueva columna a partir de existentes, preservando las originales.

# Modificando la tabla con mutate() para calcular el Fold-change (log2/log2)
sim.without.outliers %>% # Tirando data por la cañeria 
  # Hace un promedio de las columnas TREAT(MENT)
  mutate(`Mean treatment` = rowMeans(select(., starts_with("treat")))) %>%
  # Hace un promedio de las columnas CONTROL 
  mutate(`Mean control` = rowMeans(select(., starts_with("control")))) %>%
  # Calcula el fold-change de TRATAMIENTO sobre CONTROL
  mutate(`log2Ratio` = log2(.[['Mean treatment']] / .[['Mean control']])) -> mutated.sim

Funciones personalizadas

Creamos funciones para evitar escribir miles de lineas de codigo cada vez que queremos repetir algo. Podemos agruparlas y hacer una libreria para proyectos grandes, donde reutilizamos las funciones, o para recursiones.

Es importante considerar que las funciones son para cosas con un comportamiento predecible, e idealmente estable. Para analisis de datos, usualmente tenemos que limpiar los datasets, para tener una estructura “estándar” que nuestras funciones acepten, e idealmente definir un comportamiento de error para las funciones.

# Creamos funciones personalizadas para reutilizar codigo

# Aumenta por el cambio +- fracción del cambio. Es decir 3 +- 0.3 (2.7-3.3)
an.increase             <- function(x,change=3,fraction=.1) {
                                    runif(1, min= (change*x - fraction*(change*x)), max=(change*x + fraction*(change*x)))
                                     }

# Disminuye por el cambio +- fracción del cambio. Es decir 0.2 +- 0.1 (0.1-0.3)
a.decrease               <- function(x,change=.2,fraction=.1) {
                                    runif(1, min= (change*x - fraction*(change*x )), max=(change*x + fraction*(change*x )))
                                      }

Podemos crear una función para el pipeline más complejo que hicimos para el calculo del fold-change.

generate_mean_log2Ratio <- function(x, a.letter){
                                                x %>% mutate(`Mean treatment` = rowMeans(select(., starts_with("treat")))) %>% 
                                                mutate(`Mean control` = rowMeans(select(., starts_with("control")))) %>%  
                                                mutate(log2Ratio = log2(.[['Mean treatment']] / .[['Mean control']])) %>% 
                                                # Les añadiremos un identidicador al final, por """motivos""" (ver luego)
                                                rename_at(  vars(matches('^treat|^contr|^mean|log2', ignore.case = TRUE)), funs(paste0(., a.letter)))}
# Generando sets para correlaciones 
sim.without.outliers %>% 
  generate_mean_log2Ratio(' A') -> A # Calcula el fold-change inicial sin cambios

sim.without.outliers %>% 
  mutate(across(starts_with("treatment"), an.increase)) %>% 
  generate_mean_log2Ratio(' B') -> B # Fold-change aumenta 1.4-1.7 veces

sim.without.outliers %>% 
  mutate(across(starts_with("treatment"), a.decrease))  %>% 
  generate_mean_log2Ratio(' C') -> C # Fold-change disminuye -3.3 - -1.7 veces

# Creando el dataset final
cbind(A,                                               # Parte con la data A
      select(B, matches('tre|con|log')),               # Añade columnas de B
      select(C, matches('tre|con|log'))) -> final.data # Añade columnas de C y guarda
final.data

Pipes complicadas

Tipos de Pipes

Las funciones de pipes vienen mejor definidas en magrittr.
R no incluye pipes en base.

  • %>% la pipe tradicional que conocemos y amamos; pasa un obejeto a la entrada de la función
  • %$% permite pasar adicionalmente los nombres del objeto
  • %<>% pipe bidireccional, que sirve para modificar el objeto de la entrada
  • %T% una tee, que permite sacar muestras del pipeline, o derivar a otros pipes
final.data %$% name %>% 
  head # Sin head el output es de 3300 cosas
## [1] "bg_1" "bg_2" "bg_3" "bg_4" "bg_5" "bg_6"
final.data %$% cor(`log2Ratio A`,`log2Ratio B`) # Correlación entre A y B
## [1] 0.7043315
final.data %$% cbind(`log2Ratio A`, `log2Ratio B`, `log2Ratio C`) %>% colSums -> my.col.sum

my.col.sum %>%  subset(.>0) -> my.col.sum
my.col.sum %<>% subset(.>0) # Pipe bidireccional util para actualizar cosas

final.data %>% select(matches('log2')) %T>% plot() %>% # %T% permite sacar "muestras" del pipe
select(matches('B|C')) -> my.cols

Usando sistemas de identificadores

# Esto crea las descripciones del sistema o como estan descritas
# Molestias de los datos ómicos
my.terms <- c('system 1','system 2.7.9','subsystem A','subsystem B and A') # Sistemas super-sistemicos

sample(my.terms, nrow(final.data)/2,  replace = T)        -> terms.col # Genera una columna de terminos de 1650 lineas . 

sample(final.data$name, nrow(final.data)/2,  replace = F) -> names.sample # saca 1650 nombres sin duplicados, para una tabla donde habran termiminos para sistemas de identificadores

data.frame(terms.col,names.sample) -> my.info # hacemos una tabla con datos de multiples funciones 

inner_join(final.data,my.info, by = c('name'='names.sample'))-> final.data.with.terms # elimina los datos que no tienen los terminos de sistemas que usamos

full_join(final.data,my.info, by = c('name'='names.sample')) -> final.data.with.terms.nas # terminos en que algunos tienen descriptores y otros no

Filtrado de filas

final.data.with.terms.nas %>% # Nuestra data media sucia sin los nombres sistemicos
  filter(`log2Ratio A` < 0 & `log2Ratio B` < 0 & `log2Ratio C` < 0) %>% # TODO: porque no funciona con "?
  drop_na # Elimina todas las filas con NA

Expresiones regulares

Las expresiones regulares, regex, son (generalizadamente) patrones de texto que definen un criterio de busqeda en un string. Por ejemplo, a... se referiria a cualquier string que sea “a” seguido por tres caracteres, como “aaaa”, “a123”, “a”, etc. Diversos lenguajes usan distintas gramaticas de regex, pero en general usan los mismos comodines y expresiones base. R incluye paquetes base que usan regex, pero stringr tiene funciones más detalladas. Sitios como regex101 permiten testear y analizar expresiones regulares.

# Detectando un patron
final.data.with.terms.nas %>% .[['name']] %>% 
  str_detect('DE') %>% # Detecta si hay o no, tira un vectro booleano
  which # Tira una lista de las columnas donde es str_detect es TRUE
##   [1] 3001 3002 3003 3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014 3015
##  [16] 3016 3017 3018 3019 3020 3021 3022 3023 3024 3025 3026 3027 3028 3029 3030
##  [31] 3031 3032 3033 3034 3035 3036 3037 3038 3039 3040 3041 3042 3043 3044 3045
##  [46] 3046 3047 3048 3049 3050 3051 3052 3053 3054 3055 3056 3057 3058 3059 3060
##  [61] 3061 3062 3063 3064 3065 3066 3067 3068 3069 3070 3071 3072 3073 3074 3075
##  [76] 3076 3077 3078 3079 3080 3081 3082 3083 3084 3085 3086 3087 3088 3089 3090
##  [91] 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105
## [106] 3106 3107 3108 3109 3110 3111 3112 3113 3114 3115 3116 3117 3118 3119 3120
## [121] 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135
## [136] 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150
## [151] 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165
## [166] 3166 3167 3168 3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180
## [181] 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195
## [196] 3196 3197 3198 3199 3200 3201 3202 3203 3204 3205 3206 3207 3208 3209 3210
## [211] 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225
## [226] 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240
## [241] 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252 3253 3254 3255
## [256] 3256 3257 3258 3259 3260 3261 3262 3263 3264 3265 3266 3267 3268 3269 3270
## [271] 3271 3272 3273 3274 3275 3276 3277 3278 3279 3280 3281 3282 3283 3284 3285
## [286] 3286 3287 3288 3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300
# TODO: que hacia any()?
final.data.with.terms.nas %>% .[['name']] %>% str_detect('DE') %>% any
## [1] TRUE
final.data.with.terms.nas %>% .[['name']] %>% str_extract('DE.\\d+')  %>%  .[!is.na(.)]
##   [1] "DE_1"   "DE_2"   "DE_3"   "DE_4"   "DE_5"   "DE_6"   "DE_7"   "DE_8"  
##   [9] "DE_9"   "DE_10"  "DE_11"  "DE_12"  "DE_13"  "DE_14"  "DE_15"  "DE_16" 
##  [17] "DE_17"  "DE_18"  "DE_19"  "DE_20"  "DE_21"  "DE_22"  "DE_23"  "DE_24" 
##  [25] "DE_25"  "DE_26"  "DE_27"  "DE_28"  "DE_29"  "DE_30"  "DE_31"  "DE_32" 
##  [33] "DE_33"  "DE_34"  "DE_35"  "DE_36"  "DE_37"  "DE_38"  "DE_39"  "DE_40" 
##  [41] "DE_41"  "DE_42"  "DE_43"  "DE_44"  "DE_45"  "DE_46"  "DE_47"  "DE_48" 
##  [49] "DE_49"  "DE_50"  "DE_51"  "DE_52"  "DE_53"  "DE_54"  "DE_55"  "DE_56" 
##  [57] "DE_57"  "DE_58"  "DE_59"  "DE_60"  "DE_61"  "DE_62"  "DE_63"  "DE_64" 
##  [65] "DE_65"  "DE_66"  "DE_67"  "DE_68"  "DE_69"  "DE_70"  "DE_71"  "DE_72" 
##  [73] "DE_73"  "DE_74"  "DE_75"  "DE_76"  "DE_77"  "DE_78"  "DE_79"  "DE_80" 
##  [81] "DE_81"  "DE_82"  "DE_83"  "DE_84"  "DE_85"  "DE_86"  "DE_87"  "DE_88" 
##  [89] "DE_89"  "DE_90"  "DE_91"  "DE_92"  "DE_93"  "DE_94"  "DE_95"  "DE_96" 
##  [97] "DE_97"  "DE_98"  "DE_99"  "DE_100" "DE_101" "DE_102" "DE_103" "DE_104"
## [105] "DE_105" "DE_106" "DE_107" "DE_108" "DE_109" "DE_110" "DE_111" "DE_112"
## [113] "DE_113" "DE_114" "DE_115" "DE_116" "DE_117" "DE_118" "DE_119" "DE_120"
## [121] "DE_121" "DE_122" "DE_123" "DE_124" "DE_125" "DE_126" "DE_127" "DE_128"
## [129] "DE_129" "DE_130" "DE_131" "DE_132" "DE_133" "DE_134" "DE_135" "DE_136"
## [137] "DE_137" "DE_138" "DE_139" "DE_140" "DE_141" "DE_142" "DE_143" "DE_144"
## [145] "DE_145" "DE_146" "DE_147" "DE_148" "DE_149" "DE_150" "DE_151" "DE_152"
## [153] "DE_153" "DE_154" "DE_155" "DE_156" "DE_157" "DE_158" "DE_159" "DE_160"
## [161] "DE_161" "DE_162" "DE_163" "DE_164" "DE_165" "DE_166" "DE_167" "DE_168"
## [169] "DE_169" "DE_170" "DE_171" "DE_172" "DE_173" "DE_174" "DE_175" "DE_176"
## [177] "DE_177" "DE_178" "DE_179" "DE_180" "DE_181" "DE_182" "DE_183" "DE_184"
## [185] "DE_185" "DE_186" "DE_187" "DE_188" "DE_189" "DE_190" "DE_191" "DE_192"
## [193] "DE_193" "DE_194" "DE_195" "DE_196" "DE_197" "DE_198" "DE_199" "DE_200"
## [201] "DE_201" "DE_202" "DE_203" "DE_204" "DE_205" "DE_206" "DE_207" "DE_208"
## [209] "DE_209" "DE_210" "DE_211" "DE_212" "DE_213" "DE_214" "DE_215" "DE_216"
## [217] "DE_217" "DE_218" "DE_219" "DE_220" "DE_221" "DE_222" "DE_223" "DE_224"
## [225] "DE_225" "DE_226" "DE_227" "DE_228" "DE_229" "DE_230" "DE_231" "DE_232"
## [233] "DE_233" "DE_234" "DE_235" "DE_236" "DE_237" "DE_238" "DE_239" "DE_240"
## [241] "DE_241" "DE_242" "DE_243" "DE_244" "DE_245" "DE_246" "DE_247" "DE_248"
## [249] "DE_249" "DE_250" "DE_251" "DE_252" "DE_253" "DE_254" "DE_255" "DE_256"
## [257] "DE_257" "DE_258" "DE_259" "DE_260" "DE_261" "DE_262" "DE_263" "DE_264"
## [265] "DE_265" "DE_266" "DE_267" "DE_268" "DE_269" "DE_270" "DE_271" "DE_272"
## [273] "DE_273" "DE_274" "DE_275" "DE_276" "DE_277" "DE_278" "DE_279" "DE_280"
## [281] "DE_281" "DE_282" "DE_283" "DE_284" "DE_285" "DE_286" "DE_287" "DE_288"
## [289] "DE_289" "DE_290" "DE_291" "DE_292" "DE_293" "DE_294" "DE_295" "DE_296"
## [297] "DE_297" "DE_298" "DE_299" "DE_300"
# Detección de patrones algo más avanzada
final.data.with.terms.nas %>% .[['name']] %>% str_extract('[aA-zZ]E.1\\d$') %>%  .[!is.na(.)]
##  [1] "DE_10" "DE_11" "DE_12" "DE_13" "DE_14" "DE_15" "DE_16" "DE_17" "DE_18"
## [10] "DE_19"
final.data.with.terms.nas %>% .[['name']] %>% str_extract('[aA-zZ]E.1\\d+') %>% .[!is.na(.)] 
##   [1] "DE_10"  "DE_11"  "DE_12"  "DE_13"  "DE_14"  "DE_15"  "DE_16"  "DE_17" 
##   [9] "DE_18"  "DE_19"  "DE_100" "DE_101" "DE_102" "DE_103" "DE_104" "DE_105"
##  [17] "DE_106" "DE_107" "DE_108" "DE_109" "DE_110" "DE_111" "DE_112" "DE_113"
##  [25] "DE_114" "DE_115" "DE_116" "DE_117" "DE_118" "DE_119" "DE_120" "DE_121"
##  [33] "DE_122" "DE_123" "DE_124" "DE_125" "DE_126" "DE_127" "DE_128" "DE_129"
##  [41] "DE_130" "DE_131" "DE_132" "DE_133" "DE_134" "DE_135" "DE_136" "DE_137"
##  [49] "DE_138" "DE_139" "DE_140" "DE_141" "DE_142" "DE_143" "DE_144" "DE_145"
##  [57] "DE_146" "DE_147" "DE_148" "DE_149" "DE_150" "DE_151" "DE_152" "DE_153"
##  [65] "DE_154" "DE_155" "DE_156" "DE_157" "DE_158" "DE_159" "DE_160" "DE_161"
##  [73] "DE_162" "DE_163" "DE_164" "DE_165" "DE_166" "DE_167" "DE_168" "DE_169"
##  [81] "DE_170" "DE_171" "DE_172" "DE_173" "DE_174" "DE_175" "DE_176" "DE_177"
##  [89] "DE_178" "DE_179" "DE_180" "DE_181" "DE_182" "DE_183" "DE_184" "DE_185"
##  [97] "DE_186" "DE_187" "DE_188" "DE_189" "DE_190" "DE_191" "DE_192" "DE_193"
## [105] "DE_194" "DE_195" "DE_196" "DE_197" "DE_198" "DE_199"
final.data.with.terms.nas %>% .[['name']] %>% str_extract('[aA-zZ]E.1\\d.+') %>% .[!is.na(.)]
##   [1] "DE_100" "DE_101" "DE_102" "DE_103" "DE_104" "DE_105" "DE_106" "DE_107"
##   [9] "DE_108" "DE_109" "DE_110" "DE_111" "DE_112" "DE_113" "DE_114" "DE_115"
##  [17] "DE_116" "DE_117" "DE_118" "DE_119" "DE_120" "DE_121" "DE_122" "DE_123"
##  [25] "DE_124" "DE_125" "DE_126" "DE_127" "DE_128" "DE_129" "DE_130" "DE_131"
##  [33] "DE_132" "DE_133" "DE_134" "DE_135" "DE_136" "DE_137" "DE_138" "DE_139"
##  [41] "DE_140" "DE_141" "DE_142" "DE_143" "DE_144" "DE_145" "DE_146" "DE_147"
##  [49] "DE_148" "DE_149" "DE_150" "DE_151" "DE_152" "DE_153" "DE_154" "DE_155"
##  [57] "DE_156" "DE_157" "DE_158" "DE_159" "DE_160" "DE_161" "DE_162" "DE_163"
##  [65] "DE_164" "DE_165" "DE_166" "DE_167" "DE_168" "DE_169" "DE_170" "DE_171"
##  [73] "DE_172" "DE_173" "DE_174" "DE_175" "DE_176" "DE_177" "DE_178" "DE_179"
##  [81] "DE_180" "DE_181" "DE_182" "DE_183" "DE_184" "DE_185" "DE_186" "DE_187"
##  [89] "DE_188" "DE_189" "DE_190" "DE_191" "DE_192" "DE_193" "DE_194" "DE_195"
##  [97] "DE_196" "DE_197" "DE_198" "DE_199"
final.data.with.terms.nas %>% .[['terms.col']] %>% str_extract('^s.*m') %>% 
  na.exclude %>% # Es como lo de arriba, pero tira más cosas. Puede ser incomodo
  sample(10) %>% unique
## [1] "system"    "subsystem"
# Reemplazo de patrones (subsystem -> comparment) # TODO: compartment?
final.data.with.terms.nas %>% .[['terms.col']] %>% str_replace('subsyst.*','comparment') %>% na.exclude() %>% sample(10)
##  [1] "comparment"   "comparment"   "system 2.7.9" "system 1"     "comparment"  
##  [6] "system 2.7.9" "comparment"   "system 1"     "comparment"   "system 1"

Workflow de la vida real

final.data.with.terms.nas %>% 
  filter(str_detect(name, # en la columna "name"
                    regex('de.*', # Busca "de*"
                          ignore_case = T)) & # sin diferencias Minuscula/Mayuscula
         str_detect(terms.col, # Busca en la columna "term.cols"
                    regex('B.*A', ignore_case = F))) # ...terminos que empiezan con B y terminan en A
final.data.with.terms.nas %>% 
  filter(str_detect(name, # en la columna "name"
                    regex('de.*',  # ... el patrón "de*"
                          ignore_case = T)) & # sin diferencias Minuscula/Mayuscula
         str_detect(terms.col, # en la columna "term.cols"
                    regex('\\d.\\d',  # ... el patrón "\\d.\\d"
                          ignore_case = F)) & # sin diferencias Minuscula/Mayuscula
           `log2Ratio C` <0) %>% # Y el fold-change es menor a 0
  select(matches('log|name|term')) 
  • %in% permite detectar si un elemento esta en un objeto. Devuelve TRUE/FALSE.
    Puede usarse como un complemento de los comparadores ==, >, <= en sentencias if(){}
if(T){'ok'}
## [1] "ok"
if(F){'ok'}
if('system 2.7.9' %in% final.data.with.terms.nas$terms.col){'ok'}
## [1] "ok"
# "system 2.7.9" está en "final.data..." así que TRUE -> 'ok'

final.data.with.terms.nas %>% {
                               if('system 2.7.9' %in% final.data.with.terms.nas$terms.col) print('ok') else str_extract(.[['terms.col']], 'system.*' )
                               } %>%
                                  na.omit %>% unique -> unicos
## [1] "ok"
mis.datos <- list(final.data.with.terms.nas, unicos, c(1,2,4,5,5,NA))

Guardando datos en formato RDS y RData

R posee formatos propios para guardar datasets, los que tienen la ventaja de conservar propiedades como etiquetas, la estructura, etc; y permitir serializar y comprimir (usando gzip) los datos. Dependiendo de la data, un RDS puede ser 10 veces más pequeño que un CSV.

  • .RDS son R Data Single, un unico objeto.
  • .RData o .Rda, multiples objetos de R.
list.files()
##  [1] "06_mutate_pipes_regex.html"    "06_mutate_pipes_regex.Rmd"    
##  [3] "06_mutate_pipes_regex_files"   "AA_mis_datos.rds"             
##  [5] "AA_some_data.RData"            "clase_3_AA_oct_08_2020.Rmd"   
##  [7] "data_oct_08_2020.csv"          "final.data.with.terms.nas.rds"
##  [9] "rsconnect"                     "some_data.RData"
list.files(path = ".", pattern = 'aa',  ignore.case = T)
## [1] "AA_mis_datos.rds"           "AA_some_data.RData"        
## [3] "clase_3_AA_oct_08_2020.Rmd"
list.files(pattern = 'csv', full.names = T)
## [1] "./data_oct_08_2020.csv"
# Save an object to a file
saveRDS(mis.datos, file = "AA_mis_datos.rds")
# Restore the object
hola <- readRDS(file = "AA_mis_datos.rds")
hola[[1]] -> HOLA1
hola[[2]] -> HOLA2
# Save multiple objects
save(HOLA1, HOLA2, file = "AA_some_data.RData")
load("some_data.RData")
unicos
## [1] "system 2.7.9"   "system A"       "system B and A" "system 1"

  1. FONDECYT Postdoctoral Fellow, Universidad de Chile, ↩︎

  2. Pregrado, Universidad de Chile↩︎