galaaz 0.5.0 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +46 -0
- data/LICENSE +0 -0
- data/README.md +1416 -667
- data/Rakefile +68 -41
- data/bin/galaaz-bootstrap +137 -0
- data/bin/galaaz-jruby +11 -0
- data/bin/galaaz-ruby +16 -0
- data/bin/galaaz_jruby_env.inc.sh +6 -0
- data/bin/galaaz_ruby_env.inc.sh +36 -0
- data/bin/gbookdown +63 -0
- data/bin/gknit +83 -13
- data/bin/gknit-draft.rb +0 -0
- data/bin/gstudio +5 -3
- data/bin/gstudio_irb.rb +0 -0
- data/bin/gstudio_pry.rb +0 -0
- data/bin/install-tinytex +6 -0
- data/bin/run_all_rspec +44 -0
- data/bin/run_example +17 -0
- data/bin/run_old_rspec +20 -0
- data/bin/run_rspec +24 -0
- data/bin/run_rspec_subset +38 -0
- data/bin/run_slow_rspec +20 -0
- data/blogs/R-on-Rails-Planning-Document.md +940 -0
- data/blogs/README.md +100 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.Rmd +38 -66
- data/blogs/galaaz_ggplot/galaaz_ggplot.log +754 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot.md +115 -155
- data/blogs/galaaz_ggplot/galaaz_ggplot.tex +607 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-gfm/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-gfm/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-html/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/midwest_rb.png +0 -0
- data/blogs/galaaz_ggplot/galaaz_ggplot_files/figure-markdown_github/scatter_plot_rb.png +0 -0
- data/blogs/galaaz_ggplot/midwest.Rmd +3 -3
- data/blogs/galaaz_ggplot/midwest_external_png +0 -0
- data/blogs/gknit/gknit.Rmd +47 -52
- data/blogs/gknit/gknit.md +1430 -0
- data/blogs/gknit/gknit_files/figure-gfm/bubble-1.png +0 -0
- data/blogs/gknit/gknit_files/figure-gfm/diverging_bar.png +0 -0
- data/blogs/gknit/gknit_files/figure-html/bubble-1.png +0 -0
- data/blogs/gknit/gknit_files/figure-html/diverging_bar.png +0 -0
- data/blogs/gknit/lst.rds +0 -0
- data/blogs/gknit/model.rb +1 -1
- data/blogs/gknit/stats.bib +0 -0
- data/blogs/manual/include_model_local_repro.Rmd +14 -0
- data/blogs/manual/include_model_local_repro.md +75 -0
- data/blogs/manual/lst.rds +0 -0
- data/blogs/manual/manual.Rmd +855 -239
- data/blogs/manual/manual.log +1786 -0
- data/blogs/manual/manual.md +1416 -667
- data/blogs/manual/manual.tex +1883 -1161
- data/blogs/manual/manual_files/figure-html/bubble-1.png +0 -0
- data/blogs/manual/manual_files/figure-html/diverging_bar.png +0 -0
- data/blogs/manual/manual_files/figure-latex/bubble-1.png +0 -0
- data/blogs/manual/model.rb +1 -1
- data/blogs/nse_dplyr/nse_dplyr.Rmd +84 -111
- data/blogs/nse_dplyr/nse_dplyr.log +928 -0
- data/blogs/nse_dplyr/nse_dplyr.md +198 -229
- data/blogs/oh_my/not_so.rb +0 -0
- data/blogs/oh_my/oh_my.Rmd +1234 -25
- data/blogs/oh_my/oh_my.log +804 -0
- data/blogs/oh_my/oh_my.md +1663 -86
- data/blogs/oh_my/oh_my.tex +821 -0
- data/blogs/oh_my/old.Rmd +15 -14
- data/blogs/ruby_plot/ruby_plot.Rmd +58 -82
- data/blogs/ruby_plot/ruby_plot.log +885 -0
- data/blogs/ruby_plot/ruby_plot.md +71 -102
- data/blogs/ruby_plot/ruby_plot.tex +940 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-gfm/violin_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-html/violin_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/dose_len.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_delivery.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facet_by_dose.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_by_delivery_color2.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_decorations.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_jitter.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/facets_with_points.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_box_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/final_violin_plot.png +0 -0
- data/blogs/ruby_plot/ruby_plot_files/figure-latex/violin_with_jitter.png +0 -0
- data/blogs/test/test.Rmd +14 -0
- data/blogs/test/test.md +10 -0
- data/examples/50Plots_MasterList/Images/midwest-scatterplot.PNG +0 -0
- data/examples/50Plots_MasterList/ScatterPlot.rb +2 -1
- data/examples/50Plots_MasterList/scatter_plot.rb +1 -0
- data/examples/Bibliography/master.bib +0 -0
- data/examples/Bibliography/stats.bib +0 -0
- data/examples/R/calc.R +0 -0
- data/examples/R/java_interop.R +0 -0
- data/examples/bioconductor_deseq2_airway/Documentation/DESeq2-airway-walkthrough.md +56 -0
- data/examples/bioconductor_deseq2_airway/bench_galaaz_three_same_process.rb +54 -0
- data/examples/bioconductor_deseq2_airway/bench_r_three_same_process.R +34 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz.rb +34 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_galaaz_optimized.rb +35 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_minimal.R +30 -0
- data/examples/bioconductor_deseq2_airway/deseq2_airway_pipeline_for_bench.R +36 -0
- data/examples/islr/all.rb +14 -0
- data/examples/islr/ch2.spec.rb +38 -7
- data/examples/islr/ch3.spec.rb +12 -2
- data/examples/islr/ch3_boston.rb +28 -0
- data/examples/islr/ch3_multiple_regression.rb +1 -0
- data/examples/islr/ch6.spec.rb +25 -1
- data/examples/islr/x_y_rnorm.jpg +0 -0
- data/examples/latex_templates/Test-acm_article/acm_proc_article-sp.cls +0 -0
- data/examples/latex_templates/Test-acm_article/sigproc.bib +0 -0
- data/examples/latex_templates/Test-acs_article/acs-Test-acs_article.bib +0 -0
- data/examples/latex_templates/Test-acs_article/acs-my_output.bib +0 -0
- data/examples/latex_templates/Test-aea_article/BibFile.bib +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.Rmd +0 -0
- data/examples/latex_templates/Test-aea_article/references.bib +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.Rmd +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdfsync +0 -0
- data/examples/latex_templates/Test-ieee_article/IEEEtran.bst +0 -0
- data/examples/latex_templates/Test-ieee_article/mybibfile.bib +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJournal.sty +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJreferences.bib +0 -0
- data/examples/latex_templates/Test-rjournal_article/Test-rjournal_article.Rmd +0 -0
- data/examples/misc/baseball.csv +0 -0
- data/examples/misc/ggplot.rb +5 -3
- data/examples/misc/moneyball.rb +1 -0
- data/examples/misc/subsetting.rb +1 -0
- data/examples/multithread_shards_to_r/shards_to_r.rb +68 -0
- data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.Rmd +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/attend-grade-relationships.csv +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.Rmd +0 -0
- data/examples/rmarkdown/svm-xaringan-example/svm-xaringan-example.Rmd +0 -0
- data/examples/sthda_ggplot/README.md +0 -0
- data/examples/sthda_ggplot/RUN.md +41 -0
- data/examples/sthda_ggplot/all.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/density_gg.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_area.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_density.rb +3 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_dotplot.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_freqpoly.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/geom_histogram.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/histogram_density.rb +1 -0
- data/examples/sthda_ggplot/one_variable_continuous/stat.rb +1 -0
- data/examples/sthda_ggplot/one_variable_discrete/bar.rb +1 -0
- data/examples/sthda_ggplot/qplots/box_violin_dot.rb +1 -0
- data/examples/sthda_ggplot/qplots/scatter_plots.rb +1 -0
- data/examples/sthda_ggplot/scatter_gg.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_bin2d.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_density2d.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_bivariate/geom_hex.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/geom_point.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/geom_smooth.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_cont/misc.rb +1 -0
- data/examples/sthda_ggplot/two_variables_cont_function/geom_area.rb +5 -3
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_bar.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_boxplot.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_dotplot.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_jitter.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_line.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_cont/geom_violin.rb +1 -0
- data/examples/sthda_ggplot/two_variables_disc_disc/geom_jitter.rb +1 -0
- data/examples/sthda_ggplot/two_variables_error/geom_crossbar.rb +1 -0
- data/ext/new_bridge/Makefile +46 -0
- data/ext/new_bridge/galaaz_gatekeeper_phase0.cpp +12 -0
- data/ext/new_bridge/galaaz_gatekeeper_phase1.cpp +1639 -0
- data/lib/R_interface/galaaz_device.R +20 -0
- data/lib/R_interface/include_engine.R +109 -0
- data/lib/R_interface/new_bridge_adapter.rb +824 -0
- data/lib/R_interface/r.rb +177 -25
- data/lib/R_interface/r_arrow.rb +113 -0
- data/lib/R_interface/r_libs.R +3 -3
- data/lib/R_interface/r_methods.rb +13 -126
- data/lib/R_interface/r_module_s.rb +0 -0
- data/lib/R_interface/rbinary_operators.rb +20 -2
- data/lib/R_interface/rclosure.rb +5 -1
- data/lib/R_interface/rdata_frame.rb +34 -70
- data/lib/R_interface/rdevice.rb +125 -0
- data/lib/R_interface/rdevices.R +0 -0
- data/lib/R_interface/renvironment.rb +10 -4
- data/lib/R_interface/rexpression.rb +5 -1
- data/lib/R_interface/rindexed_object.rb +41 -13
- data/lib/R_interface/rlanguage.rb +20 -62
- data/lib/R_interface/rlist.rb +115 -25
- data/lib/R_interface/rlogical_operators.rb +0 -0
- data/lib/R_interface/rmatrix.rb +2 -11
- data/lib/R_interface/rmd_indexed_object.rb +5 -1
- data/lib/R_interface/robject.rb +348 -290
- data/lib/R_interface/rpkg.rb +0 -0
- data/lib/R_interface/rsupport.rb +609 -328
- data/lib/R_interface/rsupport_scope.rb +2 -1
- data/lib/R_interface/rsymbol.rb +50 -0
- data/lib/R_interface/ruby_callback.rb +2 -3
- data/lib/R_interface/ruby_extensions.rb +225 -175
- data/lib/R_interface/runary_operators.rb +0 -0
- data/lib/R_interface/rvector.rb +162 -31
- data/lib/galaaz.rb +0 -0
- data/lib/galaaz_jruby.rb +22 -0
- data/lib/galaaz_ruby.rb +34 -0
- data/lib/gknit/diagnostics.rb +50 -0
- data/lib/gknit/draft.rb +23 -17
- data/lib/gknit/include_engine.rb +15 -7
- data/lib/gknit/knitr_engine.rb +223 -74
- data/lib/gknit/rb_engine.rb +3 -3
- data/lib/gknit/ruby_engine.rb +0 -0
- data/lib/gknit.rb +1 -0
- data/lib/new_bridge/bootstrap/windows_bootstrap.rb +285 -0
- data/lib/new_bridge/envelope.rb +51 -0
- data/lib/new_bridge/eval_result.rb +26 -0
- data/lib/new_bridge/framing.rb +39 -0
- data/lib/new_bridge/instance_pool_client.rb +38 -0
- data/lib/new_bridge/r_instance_manager.rb +404 -0
- data/lib/new_bridge/session_client.rb +530 -0
- data/lib/new_bridge/tcp_framed.rb +44 -0
- data/lib/new_bridge.rb +9 -0
- data/lib/util/exec_ruby.rb +95 -20
- data/lib/util/inline_file.rb +35 -30
- data/new_bridge_specs/benchmark_phase5_5_unboxing_spec.rb +96 -0
- data/new_bridge_specs/eval_r_async_spec.rb +113 -0
- data/new_bridge_specs/integration_phase5_1_concurrent_spec.rb +50 -0
- data/new_bridge_specs/integration_phase5_1_eval_spec.rb +16 -0
- data/new_bridge_specs/integration_phase5_1_r_api_spec.rb +25 -0
- data/new_bridge_specs/integration_phase5_1_smoke_spec.rb +31 -0
- data/new_bridge_specs/integration_phase5_2_dataframe_unboxing_spec.rb +19 -0
- data/new_bridge_specs/integration_phase5_2_handle_eval_unboxing_spec.rb +25 -0
- data/new_bridge_specs/integration_phase5_3_callback_args_spec.rb +28 -0
- data/new_bridge_specs/integration_phase5_3_callback_error_spec.rb +22 -0
- data/new_bridge_specs/integration_phase5_3_callback_timeout_spec.rb +28 -0
- data/new_bridge_specs/integration_phase5_3_callbacks_smoke_spec.rb +22 -0
- data/new_bridge_specs/integration_phase5_3_edge_cases_spec.rb +52 -0
- data/new_bridge_specs/integration_phase5_3_nested_spec.rb +30 -0
- data/new_bridge_specs/integration_phase5_4_concurrent_sessions_spec.rb +53 -0
- data/new_bridge_specs/integration_phase5_4_nested_session_callbacks_spec.rb +49 -0
- data/new_bridge_specs/integration_phase5_4_session_routing_spec.rb +38 -0
- data/new_bridge_specs/integration_phase5_5_stress_concurrency_spec.rb +52 -0
- data/new_bridge_specs/integration_phase5_5_unbox_walk_spec.rb +46 -0
- data/new_bridge_specs/phase0_protocol_spec.rb +96 -0
- data/new_bridge_specs/phase1_req_ret_spec.rb +66 -0
- data/new_bridge_specs/phase2_multi_instance_spec.rb +67 -0
- data/new_bridge_specs/phase3_callbacks_spec.rb +71 -0
- data/new_bridge_specs/phase4_2_hardening_spec.rb +252 -0
- data/new_bridge_specs/phase4_3_r_instance_manager_spec.rb +85 -0
- data/new_bridge_specs/phase4_nested_callbacks_spec.rb +123 -0
- data/r_requires/ggplot.rb +0 -0
- data/r_requires/knitr.rb +0 -0
- data/specs/all.rb +15 -11
- data/specs/arrow_from_ruby_batches_spec.rb +50 -0
- data/specs/arrow_semantics_spec.rb +64 -0
- data/specs/bridge_concurrent_spec.rb +46 -0
- data/specs/bridge_nested_spec.rb +25 -0
- data/specs/dataframe_semantics_spec.rb +122 -0
- data/specs/dataframe_single_index_logical_filter_spec.rb +21 -0
- data/specs/dispatch_probe_cache_spec.rb +38 -0
- data/specs/dispatch_probe_error_class_fallback_spec.rb +20 -0
- data/specs/dispatch_probe_fallback_spec.rb +18 -0
- data/specs/environment_semantics_spec.rb +89 -0
- data/specs/field_access_spec.rb +31 -0
- data/specs/figures/bg.jpeg +0 -0
- data/specs/figures/bg.png +0 -0
- data/specs/figures/bg.svg +168 -57
- data/specs/figures/dose_len.png +0 -0
- data/specs/figures/no_args.jpeg +0 -0
- data/specs/figures/no_args.png +0 -0
- data/specs/figures/no_args.svg +168 -57
- data/specs/figures/width_height.jpeg +0 -0
- data/specs/figures/width_height.png +0 -0
- data/specs/figures/width_height_units1.jpeg +0 -0
- data/specs/figures/width_height_units1.png +0 -0
- data/specs/figures/width_height_units2.jpeg +0 -0
- data/specs/figures/width_height_units2.png +0 -0
- data/specs/formula_semantics_spec.rb +81 -0
- data/specs/galaaz_util_exec_ruby_spec.rb +85 -0
- data/specs/galaaz_util_inline_file_spec.rb +54 -0
- data/specs/gknit_cli_option_permutation_spec.rb +24 -0
- data/specs/gknit_include_engine_spec.rb +72 -0
- data/specs/gknit_install_timeout_report_spec.rb +69 -0
- data/specs/gknit_internal_error_report_spec.rb +57 -0
- data/specs/gknit_vector_map_output_spec.rb +59 -0
- data/specs/globalenv_guardrail_spec.rb +52 -0
- data/specs/language_expression_semantics_spec.rb +145 -0
- data/specs/list_semantics_spec.rb +111 -0
- data/specs/new_bridge_bulk_dataframe_transfer_spec.rb +44 -0
- data/specs/new_bridge_bulk_vector_transfer_spec.rb +73 -0
- data/specs/new_bridge_callback_timeout_spec.rb +69 -0
- data/specs/new_bridge_eval_r_fallback_spec.rb +55 -0
- data/specs/nil_null_spec.rb +42 -0
- data/specs/object_build_phase2_spec.rb +53 -0
- data/specs/phase1_callback_bridge_spec.rb +84 -0
- data/specs/phase2_gknit_generic_rendering_guardrail_spec.rb +46 -0
- data/specs/phase2_gknit_no_raw_code_leakage_spec.rb +43 -0
- data/specs/phase3_gknit_generic_graphics_capture_spec.rb +71 -0
- data/specs/plot_device_semantics_spec.rb +28 -0
- data/specs/plot_snapshot_semantics_spec.rb +58 -0
- data/specs/protocol_result_spec.rb +236 -0
- data/specs/r_batch_fail_fast_spec.rb +47 -0
- data/specs/r_bridge_bootstrap_spec.rb +11 -0
- data/specs/r_devices.spec.rb +1 -1
- data/specs/r_eval.spec.rb +16 -18
- data/specs/r_function.spec.rb +1 -1
- data/specs/r_instance_manager_spec.rb +285 -0
- data/specs/r_list_apply.spec.rb +15 -15
- data/specs/r_matrix.spec.rb +0 -0
- data/specs/r_nse.spec.rb +5 -5
- data/specs/r_object_send_dispatch_spec.rb +13 -0
- data/specs/r_vector_comparator_spec.rb +8 -0
- data/specs/r_vector_creation.spec.rb +0 -0
- data/specs/r_vector_functions.spec.rb +0 -0
- data/specs/r_vector_object.spec.rb +0 -0
- data/specs/r_vector_operators.spec.rb +0 -0
- data/specs/r_vector_structured_scalar_reads_spec.rb +35 -0
- data/specs/r_vector_subsetting.spec.rb +0 -0
- data/specs/range_helper_spec.rb +21 -0
- data/specs/rsupport_scope_spec.rb +28 -0
- data/specs/rsupport_var_name_thread_safety_spec.rb +24 -0
- data/specs/scalar_character_spec.rb +44 -0
- data/specs/scoped_symbol_dsl_refinement_spec.rb +40 -0
- data/specs/session_env_bridge_spec.rb +25 -0
- data/specs/simplecov_bootstrap_spec.rb +10 -0
- data/specs/spec_helper.rb +10 -0
- data/specs/tmp.rb +0 -0
- data/specs/unboxing_recursion_regression_spec.rb +30 -0
- data/specs/unboxing_spec.rb +49 -0
- data/specs/verify_callbacks.rb +42 -0
- data/sty/galaaz.sty +0 -0
- data/version.rb +1 -1
- metadata +219 -63
- data/blogs/galaaz_ggplot/galaaz_ggplot.html +0 -520
- data/blogs/galaaz_ggplot/galaaz_ggplot.pdf +0 -0
- data/blogs/galaaz_ggplot/midwest.html +0 -188
- data/blogs/gknit/gknit.html +0 -2266
- data/blogs/gknit/gknit.pdf +0 -0
- data/blogs/manual/manual.html +0 -4638
- data/blogs/manual/manual.pdf +0 -0
- data/blogs/manual/manual_files/figure-latex/diverging_bar.pdf +0 -0
- data/blogs/nse_dplyr/nse_dplyr.html +0 -878
- data/blogs/nse_dplyr/nse_dplyr.pdf +0 -0
- data/blogs/oh_my/oh_my.html +0 -568
- data/blogs/ruby_plot/ruby_plot.html +0 -544
- data/blogs/ruby_plot/ruby_plot.pdf +0 -0
- data/examples/latex_templates/Test-acs_article/Test-acs_article.pdf +0 -0
- data/examples/latex_templates/Test-aea_article/Test-aea_article.pdf +0 -0
- data/examples/latex_templates/Test-amq_article/Test-amq_article.pdf +0 -0
- data/examples/latex_templates/Test-amq_article/pics/Figure2.pdf +0 -0
- data/examples/latex_templates/Test-asa_article/Test-asa_article.pdf +0 -0
- data/examples/latex_templates/Test-ieee_article/Test-ieee_article.pdf +0 -0
- data/examples/latex_templates/Test-rjournal_article/RJwrapper.pdf +0 -0
- data/examples/latex_templates/Test-springer_article/Test-springer_article.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-anon-ms-example/svm-rmarkdown-anon-ms-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-article-example/svm-rmarkdown-article-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-beamer-example/svm-rmarkdown-beamer-example.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-cv/svm-rmarkdown-cv.pdf +0 -0
- data/examples/rmarkdown/svm-rmarkdown-syllabus-example/svm-rmarkdown-syllabus-example.pdf +0 -0
- data/specs/r_dataframe.spec.rb +0 -379
- data/specs/r_environment.spec.rb +0 -140
- data/specs/r_formula.spec.rb +0 -232
- data/specs/r_language.spec.rb +0 -112
- data/specs/r_list.spec.rb +0 -293
- data/specs/r_plots.spec.rb +0 -72
- data/specs/ruby_expression.spec.rb +0 -316
|
@@ -3,8 +3,8 @@ title: "Non Standard Evaluation in dplyr with Galaaz"
|
|
|
3
3
|
author:
|
|
4
4
|
- "Rodrigo Botafogo"
|
|
5
5
|
- "Daniel Mossé - University of Pittsburgh"
|
|
6
|
-
tags: [Tech, Data Science, Ruby, R,
|
|
7
|
-
date: "10/05/2019"
|
|
6
|
+
tags: [Tech, Data Science, Ruby, R, JRuby, "GNU R", Galaaz, dplyr]
|
|
7
|
+
date: "10/05/2019 (narrative updated for Galaaz 2.0, 2026)"
|
|
8
8
|
output:
|
|
9
9
|
html_document:
|
|
10
10
|
self_contained: true
|
|
@@ -24,7 +24,7 @@ fontsize: 11pt
|
|
|
24
24
|
|
|
25
25
|
# Introduction
|
|
26
26
|
|
|
27
|
-
According to Steven Sagaert answer on Quora about
|
|
27
|
+
According to Steven Sagaert’s answer on Quora about “Is programming language R overrated?”:
|
|
28
28
|
|
|
29
29
|
> R is a sophisticated language with an unusual (i.e. non-mainstream) set of features. It‘s
|
|
30
30
|
> an impure functional programming language with sophisticated metaprogramming and 3
|
|
@@ -37,16 +37,15 @@ According to Steven Sagaert answer on Quora about "Is programming language R ove
|
|
|
37
37
|
> Mastering R (the language) and its ecosystem is not a matter of weeks or months but
|
|
38
38
|
> takes years. The rabbit hole goes pretty deep…
|
|
39
39
|
|
|
40
|
-
Although
|
|
41
|
-
it can also
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
concerned about creating complex computer systems.
|
|
40
|
+
Although a highly configurable language can give programmers a great deal of power,
|
|
41
|
+
it can also take years to master—as noted above. Programming with _dplyr_, for instance,
|
|
42
|
+
means learning evaluation rules that are not always approachable for **statisticians and
|
|
43
|
+
analysts who are not full-time software engineers**. That is not a criticism: R was **built**
|
|
44
|
+
for **statisticians** who need trustworthy results on a deadline, not necessarily for building
|
|
45
|
+
large applications.
|
|
47
46
|
|
|
48
|
-
|
|
49
|
-
|
|
47
|
+
**Unfortunately**, when such a user moves on to more **sophisticated** programming patterns,
|
|
48
|
+
the learning curve can become a real hurdle.
|
|
50
49
|
|
|
51
50
|
In this post we will see how to program with _dplyr_ in Galaaz and how Ruby can simplify
|
|
52
51
|
the learning curve of mastering _dplyr_ coding.
|
|
@@ -58,9 +57,9 @@ a large community, a very large set of libraries and great for web development.
|
|
|
58
57
|
easy to learn. However,
|
|
59
58
|
it lacks libraries for data science, statistics, scientific plotting and machine learning.
|
|
60
59
|
On the other hand, R is considered one of the most powerful languages for solving all of the
|
|
61
|
-
above problems.
|
|
62
|
-
|
|
63
|
-
|
|
60
|
+
above problems. **Python** is a strong competitor, with NumPy, pandas, SciPy, scikit-learn,
|
|
61
|
+
and **many thousands** of other packages on PyPI. We will not dwell on R **versus** Python here:
|
|
62
|
+
both are excellent languages with different strengths.
|
|
64
63
|
Our interest is to bring to yet another excellent language, Ruby, the data science libraries
|
|
65
64
|
that it lacks.
|
|
66
65
|
|
|
@@ -73,37 +72,14 @@ post that programming with _dplyr_ is easier in Galaaz than in R.
|
|
|
73
72
|
|
|
74
73
|
R users are probably quite knowledgeable about _dplyr_. For the Ruby developer, _dplyr_ and
|
|
75
74
|
the _tidyverse_ libraries are a set of libraries for data manipulation in R, developed by
|
|
76
|
-
|
|
75
|
+
Hadley Wickham, Chief Scientist at Posit (formerly RStudio) and a prolific R coder and writer.
|
|
77
76
|
|
|
78
|
-
For the coupling of Ruby and R,
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
GraalVM removes the isolation between programming languages and enables
|
|
86
|
-
interoperability in a shared runtime. It can run either standalone or in
|
|
87
|
-
the context of OpenJDK, Node.js, Oracle Database, or MySQL.
|
|
88
|
-
|
|
89
|
-
GraalVM allows you to write polyglot applications with a seamless way to
|
|
90
|
-
pass values from one language to another. With GraalVM there is no copying
|
|
91
|
-
or marshaling necessary as it is with other polyglot systems. This lets
|
|
92
|
-
you achieve high performance when language boundaries are crossed. Most
|
|
93
|
-
of the time there is no additional cost for crossing a language boundary
|
|
94
|
-
at all.
|
|
95
|
-
|
|
96
|
-
Often developers have to make uncomfortable compromises that require them
|
|
97
|
-
to rewrite their software in other languages. For example:
|
|
98
|
-
|
|
99
|
-
* “That library is not available in my language. I need to rewrite it.”
|
|
100
|
-
* “That language would be the perfect fit for my problem, but we cannot
|
|
101
|
-
run it in our environment.”
|
|
102
|
-
* “That problem is already solved in my language, but the language is
|
|
103
|
-
too slow.”
|
|
104
|
-
|
|
105
|
-
With GraalVM we aim to allow developers to freely choose the right language
|
|
106
|
-
for the task at hand without making compromises.
|
|
77
|
+
For the coupling of Ruby and R, **Galaaz 2.0** uses **[JRuby](https://www.jruby.org/)** (Ruby on the JVM)
|
|
78
|
+
together with **GNU R**. A **bridge** sends expressions and data between Ruby and an R process so that
|
|
79
|
+
Ruby can call **dplyr** and the rest of the tidyverse as if they were part of the same workflow.
|
|
80
|
+
An **earlier** Galaaz line of work used Oracle’s **GraalVM** with **TruffleRuby** and **FastR** in a single
|
|
81
|
+
runtime; that approach is **no longer** the supported stack—see the project **manual** for setup,
|
|
82
|
+
**`bin/galaaz-jruby`**, and **gKnit**.
|
|
107
83
|
|
|
108
84
|
|
|
109
85
|
# Tidyverse and dplyr
|
|
@@ -137,7 +113,7 @@ multiple datasets, programming becomes necessary.
|
|
|
137
113
|
# Programming with dplyr
|
|
138
114
|
|
|
139
115
|
In the vignette ["Programming with dplyr"](https://dplyr.tidyverse.org/articles/programming.html),
|
|
140
|
-
|
|
116
|
+
Hadley Wickham states:
|
|
141
117
|
|
|
142
118
|
> Most dplyr functions use non-standard evaluation (NSE). This is a catch-all term that
|
|
143
119
|
> means they don’t follow the usual R rules of evaluation. Instead, they capture the
|
|
@@ -160,7 +136,7 @@ But then he goes on:
|
|
|
160
136
|
> with a seemingly equivalent object that you’ve defined elsewhere. In other words, this code:
|
|
161
137
|
|
|
162
138
|
|
|
163
|
-
```r
|
|
139
|
+
``` r
|
|
164
140
|
df <- data.frame(x = 1:3, y = 3:1)
|
|
165
141
|
print(filter(df, x == 1))
|
|
166
142
|
#> # A tibble: 1 x 2
|
|
@@ -171,7 +147,7 @@ print(filter(df, x == 1))
|
|
|
171
147
|
> Is not equivalent to this code:
|
|
172
148
|
|
|
173
149
|
|
|
174
|
-
```r
|
|
150
|
+
``` r
|
|
175
151
|
my_var <- x
|
|
176
152
|
#> Error in eval(expr, envir, enclos): object 'x' not found
|
|
177
153
|
filter(df, my_var == 1)
|
|
@@ -180,7 +156,7 @@ filter(df, my_var == 1)
|
|
|
180
156
|
> This makes it hard to create functions with arguments that change how dplyr verbs are computed.
|
|
181
157
|
|
|
182
158
|
As a result of this, programming with _dplyr_ requires learning a set of new ideas and concepts.
|
|
183
|
-
In this vignette
|
|
159
|
+
In this vignette Hadley goes on showing how to program ever more difficult problems with _dplyr_,
|
|
184
160
|
showing the problems it faces and the new concepts needed to solve them.
|
|
185
161
|
|
|
186
162
|
In this blog, we will look at all the problems presented by Harley on the vignette and show how
|
|
@@ -220,7 +196,7 @@ where you are reading this blog) with gKnit (a tool provided by Galaaz). In Rmar
|
|
|
220
196
|
possible to write text and code blocks that are executed to generate the final report. Code
|
|
221
197
|
blocks appear inside a 'box' and the result of their execution appear either in another type
|
|
222
198
|
of 'box' with a different background (HTML) or as normal text (PDF). Every output line from
|
|
223
|
-
the code execution is
|
|
199
|
+
the code execution is preceded by '##'.
|
|
224
200
|
|
|
225
201
|
## Expressions from operators
|
|
226
202
|
|
|
@@ -228,24 +204,36 @@ The code below creates an expression summing two symbols. Note that :a and :b ar
|
|
|
228
204
|
are not bound to any values at the time of expression definition:
|
|
229
205
|
|
|
230
206
|
|
|
231
|
-
```ruby
|
|
207
|
+
``` ruby
|
|
232
208
|
exp1 = :a + :b
|
|
233
209
|
puts exp1
|
|
234
210
|
```
|
|
235
211
|
|
|
236
212
|
```
|
|
237
|
-
##
|
|
213
|
+
## undefined method '+' for an instance of Symbol
|
|
214
|
+
```
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
## /home/rbotafogo/desenv_linux/galaaz/lib/util/exec_ruby.rb:170:in 'exec_ruby'
|
|
218
|
+
## org/jruby/RubyKernel.java:1268:in 'eval'
|
|
219
|
+
## /home/rbotafogo/desenv_linux/galaaz/lib/util/exec_ruby.rb:169:in 'exec_ruby'
|
|
220
|
+
## /home/rbotafogo/desenv_linux/galaaz/lib/gknit/knitr_engine.rb:777:in 'block in initialize'
|
|
221
|
+
## org/jruby/RubyBasicObject.java:2695:in 'instance_eval'
|
|
222
|
+
## org/jruby/RubyBasicObject.java:2723:in 'instance_eval'
|
|
223
|
+
## /home/rbotafogo/desenv_linux/galaaz/lib/gknit/knitr_engine.rb:748:in 'block in initialize'
|
|
224
|
+
## /home/rbotafogo/desenv_linux/galaaz/lib/R_interface/new_bridge_adapter.rb:358:in 'block in register_callback_proc_stub'
|
|
225
|
+
## /home/rbotafogo/desenv_linux/galaaz/lib/new_bridge/session_client.rb:413:in 'block in handle_call'
|
|
238
226
|
```
|
|
239
227
|
In Galaaz, we can build any complex mathematical expression such as:
|
|
240
228
|
|
|
241
229
|
|
|
242
|
-
```ruby
|
|
243
|
-
exp2 = (:a + :b) * 2.0 + :c ** 2 / :z
|
|
230
|
+
``` ruby
|
|
231
|
+
exp2 = (R[:a] + R[:b]) * 2.0 + R[:c] ** 2 / R[:z]
|
|
244
232
|
puts exp2
|
|
245
233
|
```
|
|
246
234
|
|
|
247
235
|
```
|
|
248
|
-
##
|
|
236
|
+
## a + b * 2.0 + c ^ 2L / z
|
|
249
237
|
```
|
|
250
238
|
Expressions are printed with the same format as the equivalent R expressions. The 'L' after
|
|
251
239
|
2 indicates that 2 is an integer.
|
|
@@ -258,8 +246,8 @@ float.
|
|
|
258
246
|
It is also possible to use inequality operators in building expressions:
|
|
259
247
|
|
|
260
248
|
|
|
261
|
-
```ruby
|
|
262
|
-
exp3 = (:a + :b) >= :z
|
|
249
|
+
``` ruby
|
|
250
|
+
exp3 = (R[:a] + R[:b]) >= R[:z]
|
|
263
251
|
puts exp3
|
|
264
252
|
```
|
|
265
253
|
|
|
@@ -269,15 +257,15 @@ puts exp3
|
|
|
269
257
|
Expressions' definition can also make use of normal Ruby variables without any problem:
|
|
270
258
|
|
|
271
259
|
|
|
272
|
-
```ruby
|
|
260
|
+
``` ruby
|
|
273
261
|
x = 20
|
|
274
262
|
y = 30.0
|
|
275
|
-
exp_var = (:a + :b) * x <= :z - y
|
|
263
|
+
exp_var = (R[:a] + R[:b]) * x <= R[:z] - y
|
|
276
264
|
puts exp_var
|
|
277
265
|
```
|
|
278
266
|
|
|
279
267
|
```
|
|
280
|
-
##
|
|
268
|
+
## a + b * 20L <= z - 30.0
|
|
281
269
|
```
|
|
282
270
|
|
|
283
271
|
Galaaz provides both symbolic representations for operators, such as (>, <, !=) as functional
|
|
@@ -285,8 +273,8 @@ notation for those operators such as (.gt, .ge, etc.). So the same expression w
|
|
|
285
273
|
above can also be written as
|
|
286
274
|
|
|
287
275
|
|
|
288
|
-
```ruby
|
|
289
|
-
exp4 = (:a + :b).ge :z
|
|
276
|
+
``` ruby
|
|
277
|
+
exp4 = (R[:a] + R[:b]).ge R[:z]
|
|
290
278
|
puts exp4
|
|
291
279
|
```
|
|
292
280
|
|
|
@@ -302,8 +290,8 @@ In order to write an expression involving '==' we
|
|
|
302
290
|
need to use the method '.eq' and for '=' we need the function '.assign':
|
|
303
291
|
|
|
304
292
|
|
|
305
|
-
```ruby
|
|
306
|
-
exp5 = (:a + :b).eq :z
|
|
293
|
+
``` ruby
|
|
294
|
+
exp5 = (R[:a] + R[:b]).eq R[:z]
|
|
307
295
|
puts exp5
|
|
308
296
|
```
|
|
309
297
|
|
|
@@ -312,8 +300,8 @@ puts exp5
|
|
|
312
300
|
```
|
|
313
301
|
|
|
314
302
|
|
|
315
|
-
```ruby
|
|
316
|
-
exp6 = :y.assign :a + :b
|
|
303
|
+
``` ruby
|
|
304
|
+
exp6 = R[:y].assign R[:a] + R[:b]
|
|
317
305
|
puts exp6
|
|
318
306
|
```
|
|
319
307
|
|
|
@@ -325,19 +313,16 @@ this will generate an error, that might be a bit cryptic (in future releases of
|
|
|
325
313
|
plan to improve the error message).
|
|
326
314
|
|
|
327
315
|
|
|
328
|
-
```ruby
|
|
329
|
-
exp_wrong = (:a + :b) == :z
|
|
316
|
+
``` ruby
|
|
317
|
+
exp_wrong = (R[:a] + R[:b]) == R[:z]
|
|
330
318
|
puts exp_wrong
|
|
331
319
|
```
|
|
332
320
|
|
|
333
321
|
```
|
|
334
|
-
##
|
|
335
|
-
## Error in function (x, y, num.eq = TRUE, single.NA = TRUE, attrib.as.set = TRUE, :
|
|
336
|
-
## object 'a' not found (RError)
|
|
337
|
-
## Translated to internal error
|
|
322
|
+
## false
|
|
338
323
|
```
|
|
339
324
|
The problem lies with the fact that
|
|
340
|
-
when using '==' we are comparing expression (:a + :b) to expression :z with '=='. When this
|
|
325
|
+
when using '==' we are comparing expression (R[:a] + R[:b]) to expression R[:z] with '=='. When this
|
|
341
326
|
comparison is executed, the system tries to evaluate :a, :b and :z, and those symbols, at
|
|
342
327
|
this time, are not bound to anything giving the "object 'a' not found" message.
|
|
343
328
|
|
|
@@ -350,8 +335,8 @@ the function to be part of the expression, we call the function preceeding it
|
|
|
350
335
|
by the letter E, such as 'E.sin(x)'
|
|
351
336
|
|
|
352
337
|
|
|
353
|
-
```ruby
|
|
354
|
-
exp7 = :y.assign E.sin(:x)
|
|
338
|
+
``` ruby
|
|
339
|
+
exp7 = R[:y].assign E.sin(R[:x])
|
|
355
340
|
puts exp7
|
|
356
341
|
```
|
|
357
342
|
|
|
@@ -361,8 +346,8 @@ puts exp7
|
|
|
361
346
|
Function expressions can also be written using '.' notation:
|
|
362
347
|
|
|
363
348
|
|
|
364
|
-
```ruby
|
|
365
|
-
exp8 = :y.assign :x.sin
|
|
349
|
+
``` ruby
|
|
350
|
+
exp8 = R[:y].assign R[:x].sin
|
|
366
351
|
puts exp8
|
|
367
352
|
```
|
|
368
353
|
|
|
@@ -374,8 +359,8 @@ the R concatenate function 'c', that concatenates two or more arguments can be p
|
|
|
374
359
|
an expression as:
|
|
375
360
|
|
|
376
361
|
|
|
377
|
-
```ruby
|
|
378
|
-
exp9 = :x.c(:y)
|
|
362
|
+
``` ruby
|
|
363
|
+
exp9 = R[:x].c(R[:y])
|
|
379
364
|
puts exp9
|
|
380
365
|
```
|
|
381
366
|
|
|
@@ -394,19 +379,19 @@ can be evaluated by calling function 'eval' with a binding.
|
|
|
394
379
|
A binding can be provided with a list or a data frame as shown below:
|
|
395
380
|
|
|
396
381
|
|
|
397
|
-
```ruby
|
|
398
|
-
exp = (:a + :b) * 2.0 + :c ** 2 / :z
|
|
382
|
+
``` ruby
|
|
383
|
+
exp = (R[:a] + R[:b]) * 2.0 + R[:c] ** 2 / R[:z]
|
|
399
384
|
puts exp.eval(R.list(a: 10, b: 20, c: 30, z: 40))
|
|
400
385
|
```
|
|
401
386
|
|
|
402
387
|
```
|
|
403
|
-
## [1]
|
|
388
|
+
## [1] 72.5
|
|
404
389
|
```
|
|
405
390
|
|
|
406
391
|
with a data frame:
|
|
407
392
|
|
|
408
393
|
|
|
409
|
-
```ruby
|
|
394
|
+
``` ruby
|
|
410
395
|
df = R.data__frame(
|
|
411
396
|
a: R.c(1, 2, 3),
|
|
412
397
|
b: R.c(10, 20, 30),
|
|
@@ -417,7 +402,7 @@ puts exp.eval(df)
|
|
|
417
402
|
```
|
|
418
403
|
|
|
419
404
|
```
|
|
420
|
-
## [1]
|
|
405
|
+
## [1] 31 62 93
|
|
421
406
|
```
|
|
422
407
|
|
|
423
408
|
# Using Galaaz to call R functions
|
|
@@ -433,7 +418,7 @@ with 'R.'. For instance, to create a vector in R, the 'c' function is used. In
|
|
|
433
418
|
vector can be created by using 'R.c':
|
|
434
419
|
|
|
435
420
|
|
|
436
|
-
```ruby
|
|
421
|
+
``` ruby
|
|
437
422
|
vec = R.c(1.0, 2, 3)
|
|
438
423
|
puts vec
|
|
439
424
|
```
|
|
@@ -444,7 +429,7 @@ puts vec
|
|
|
444
429
|
A list is created in R with the 'list' function, so in Galaaz we do:
|
|
445
430
|
|
|
446
431
|
|
|
447
|
-
```ruby
|
|
432
|
+
``` ruby
|
|
448
433
|
list = R.list(a: 1.0, b: 2, c: 3)
|
|
449
434
|
puts list
|
|
450
435
|
```
|
|
@@ -462,7 +447,7 @@ puts list
|
|
|
462
447
|
Note that we can use named arguments in our list. The same code in R would be:
|
|
463
448
|
|
|
464
449
|
|
|
465
|
-
```r
|
|
450
|
+
``` r
|
|
466
451
|
lst = list(a = 1, b = 2L, c = 3L)
|
|
467
452
|
print(lst)
|
|
468
453
|
```
|
|
@@ -482,8 +467,8 @@ the expression $y = sin(45^\circ)$, which is $y = 0.850...$. In this case,
|
|
|
482
467
|
we will use 'R.sin':
|
|
483
468
|
|
|
484
469
|
|
|
485
|
-
```ruby
|
|
486
|
-
exp10 = :y.assign R.sin(45)
|
|
470
|
+
``` ruby
|
|
471
|
+
exp10 = R[:y].assign R.sin(45)
|
|
487
472
|
puts exp10
|
|
488
473
|
```
|
|
489
474
|
|
|
@@ -501,42 +486,17 @@ Transportation Statistics.
|
|
|
501
486
|
Let's start by taking a look at this dataset:
|
|
502
487
|
|
|
503
488
|
|
|
504
|
-
```ruby
|
|
489
|
+
``` ruby
|
|
505
490
|
R.library('nycflights13')
|
|
506
491
|
# check it's dimension
|
|
507
|
-
puts
|
|
492
|
+
puts ~R[:flights].dim
|
|
508
493
|
# and the structure
|
|
509
|
-
|
|
494
|
+
~R[:flights].str
|
|
510
495
|
```
|
|
511
496
|
|
|
512
497
|
```
|
|
513
|
-
##
|
|
514
|
-
##
|
|
515
|
-
```
|
|
516
|
-
|
|
517
|
-
```
|
|
518
|
-
## Message:
|
|
519
|
-
## /home/rbotafogo/desenv/galaaz/lib/R_interface/rsupport.rb:90:in `eval'
|
|
520
|
-
## /home/rbotafogo/desenv/galaaz/lib/R_interface/rsupport.rb:270:in `exec_function_name'
|
|
521
|
-
## /home/rbotafogo/desenv/galaaz/lib/R_interface/robject.rb:166:in `method_missing'
|
|
522
|
-
## /home/rbotafogo/desenv/galaaz/lib/util/exec_ruby.rb:105:in `get_binding'
|
|
523
|
-
## /home/rbotafogo/desenv/galaaz/lib/util/exec_ruby.rb:102:in `eval'
|
|
524
|
-
## /home/rbotafogo/desenv/galaaz/lib/util/exec_ruby.rb:102:in `exec_ruby'
|
|
525
|
-
## /home/rbotafogo/desenv/galaaz/lib/gknit/knitr_engine.rb:650:in `block in initialize'
|
|
526
|
-
## /home/rbotafogo/desenv/galaaz/lib/R_interface/ruby_callback.rb:77:in `call'
|
|
527
|
-
## /home/rbotafogo/desenv/galaaz/lib/R_interface/ruby_callback.rb:77:in `callback'
|
|
528
|
-
## (eval):3:in `function(...) {\n rb_method(...)'
|
|
529
|
-
## unknown.r:1:in `in_dir'
|
|
530
|
-
## unknown.r:1:in `block_exec'
|
|
531
|
-
## /usr/local/lib/graalvm-ce-java11-20.0.0/languages/R/library/knitr/R/block.R:92:in `call_block'
|
|
532
|
-
## /usr/local/lib/graalvm-ce-java11-20.0.0/languages/R/library/knitr/R/block.R:6:in `process_group.block'
|
|
533
|
-
## /usr/local/lib/graalvm-ce-java11-20.0.0/languages/R/library/knitr/R/block.R:3:in `<no source>'
|
|
534
|
-
## unknown.r:1:in `withCallingHandlers'
|
|
535
|
-
## unknown.r:1:in `process_file'
|
|
536
|
-
## unknown.r:1:in `<no source>'
|
|
537
|
-
## unknown.r:1:in `<no source>'
|
|
538
|
-
## <REPL>:4:in `<repl wrapper>'
|
|
539
|
-
## <REPL>:1
|
|
498
|
+
## ~(dim(flights))
|
|
499
|
+
## <environment: 0x5f0b6a5b7790>
|
|
540
500
|
```
|
|
541
501
|
|
|
542
502
|
Now, let's use a first verb of _dplyr_: 'filter'. This verb, obviously, will filter the data
|
|
@@ -549,34 +509,34 @@ The second and third arguments are expressions that will be used by the filter f
|
|
|
549
509
|
filter by columns, looking for entries in which the month and day are equal to 1.
|
|
550
510
|
|
|
551
511
|
|
|
552
|
-
```ruby
|
|
553
|
-
puts R.filter(:flights, (:month.eq 1), (:day.eq 1))
|
|
512
|
+
``` ruby
|
|
513
|
+
puts R.filter(:flights, (R[:month].eq 1), (R[:day].eq 1))
|
|
554
514
|
```
|
|
555
515
|
|
|
556
516
|
```
|
|
557
|
-
## # A tibble: 842
|
|
558
|
-
## year month day dep_time sched_dep_time dep_delay arr_time
|
|
559
|
-
## <int> <int> <int> <int> <int> <dbl> <int>
|
|
560
|
-
## 1 2013 1 1 517 515 2 830
|
|
561
|
-
## 2 2013 1 1 533 529 4 850
|
|
562
|
-
## 3 2013 1 1 542 540 2 923
|
|
563
|
-
## 4 2013 1 1 544 545 -1 1004
|
|
564
|
-
## 5 2013 1 1 554 600 -6 812
|
|
565
|
-
## 6 2013 1 1 554 558 -4 740
|
|
566
|
-
## 7 2013 1 1 555 600 -5 913
|
|
567
|
-
## 8 2013 1 1 557 600 -3 709
|
|
568
|
-
## 9 2013 1 1 557 600 -3 838
|
|
569
|
-
## 10 2013 1 1 558 600 -2 753
|
|
570
|
-
## #
|
|
571
|
-
## #
|
|
572
|
-
## # origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
|
|
573
|
-
## # minute <dbl>, time_hour <dttm>
|
|
517
|
+
## # A tibble: 842 × 19
|
|
518
|
+
## year month day dep_time sched_dep_time dep_delay arr_time sched_arr_time
|
|
519
|
+
## <int> <int> <int> <int> <int> <dbl> <int> <int>
|
|
520
|
+
## 1 2013 1 1 517 515 2 830 819
|
|
521
|
+
## 2 2013 1 1 533 529 4 850 830
|
|
522
|
+
## 3 2013 1 1 542 540 2 923 850
|
|
523
|
+
## 4 2013 1 1 544 545 -1 1004 1022
|
|
524
|
+
## 5 2013 1 1 554 600 -6 812 837
|
|
525
|
+
## 6 2013 1 1 554 558 -4 740 728
|
|
526
|
+
## 7 2013 1 1 555 600 -5 913 854
|
|
527
|
+
## 8 2013 1 1 557 600 -3 709 723
|
|
528
|
+
## 9 2013 1 1 557 600 -3 838 846
|
|
529
|
+
## 10 2013 1 1 558 600 -2 753 745
|
|
530
|
+
## # ℹ 832 more rows
|
|
531
|
+
## # ℹ 11 more variables: arr_delay <dbl>, carrier <chr>, flight <int>,
|
|
532
|
+
## # tailnum <chr>, origin <chr>, dest <chr>, air_time <dbl>, distance <dbl>,
|
|
533
|
+
## # hour <dbl>, minute <dbl>, time_hour <dttm>
|
|
574
534
|
```
|
|
575
535
|
|
|
576
536
|
|
|
577
537
|
## Programming with _dplyr_: problems and how to solve them in Galaaz
|
|
578
538
|
|
|
579
|
-
In this section we look at the list of problems that
|
|
539
|
+
In this section we look at the list of problems that Hadley describes in the "Programming with dplyr"
|
|
580
540
|
vignette and show how those problems are solved and coded with Galaaz. Readers interested in
|
|
581
541
|
how those problems are treated in _dplyr_ should read the vignette and use it as a comparison with
|
|
582
542
|
this blog.
|
|
@@ -590,7 +550,7 @@ functions that have a '.' in them, we need to substitute the '.' with '__'. So,
|
|
|
590
550
|
'data.frame' in R, is called in Galaaz as 'R.data\_\_frame':
|
|
591
551
|
|
|
592
552
|
|
|
593
|
-
```ruby
|
|
553
|
+
``` ruby
|
|
594
554
|
df = R.data__frame(x: (1..3), y: (3..1))
|
|
595
555
|
puts df
|
|
596
556
|
```
|
|
@@ -608,16 +568,16 @@ by using dot notation.
|
|
|
608
568
|
|
|
609
569
|
-------FIX---------
|
|
610
570
|
|
|
611
|
-
We prefer to use dot notation as shown
|
|
571
|
+
We prefer to use dot notation as shown below. The argument to 'filter' should be an
|
|
612
572
|
expression. Note that if we gave to filter a Ruby expression such as
|
|
613
573
|
'x == 1', we would get an error, since there is no variable 'x' defined and if 'x' was a variable
|
|
614
574
|
then 'x == 1' would either be 'true' or 'false'. Our goal is to filter our data frame returning
|
|
615
|
-
all rows in which the 'x' value is equal to 1. To express this we want: ':x.eq 1', where :x will
|
|
575
|
+
all rows in which the 'x' value is equal to 1. To express this we want: 'R[:x].eq 1', where :x will
|
|
616
576
|
be interpreted by filter as the 'x' column.
|
|
617
577
|
|
|
618
578
|
|
|
619
|
-
```ruby
|
|
620
|
-
puts df.filter(:x.eq 1)
|
|
579
|
+
``` ruby
|
|
580
|
+
puts df.filter(R[:x].eq 1)
|
|
621
581
|
```
|
|
622
582
|
|
|
623
583
|
```
|
|
@@ -629,21 +589,21 @@ In R, and when coding with 'tidyverse', arguments to a function are usually not
|
|
|
629
589
|
object that you’ve defined elsewhere. In other words, this code
|
|
630
590
|
|
|
631
591
|
|
|
632
|
-
```r
|
|
592
|
+
``` r
|
|
633
593
|
my_var <- x
|
|
634
594
|
filter(df, my_var == 1)
|
|
635
595
|
```
|
|
636
596
|
Generates the following error: "object 'x' not found.
|
|
637
597
|
|
|
638
598
|
However, in Galaaz, arguments are referencially transparent as can be seen by the
|
|
639
|
-
code
|
|
599
|
+
code below. Note initially that 'my_var = R[:x]' will not give the error "object 'x' not found"
|
|
640
600
|
since ':x' is treated as an expression and assigned to my\_var. Then when doing (my\_var.eq 1),
|
|
641
|
-
my\_var is a variable that resolves to ':x' and it becomes equivalent to (:x.eq 1) which is
|
|
601
|
+
my\_var is a variable that resolves to ':x' and it becomes equivalent to (R[:x].eq 1) which is
|
|
642
602
|
what we want.
|
|
643
603
|
|
|
644
604
|
|
|
645
|
-
```ruby
|
|
646
|
-
my_var = :x
|
|
605
|
+
``` ruby
|
|
606
|
+
my_var = R[:x]
|
|
647
607
|
puts df.filter(my_var.eq 1)
|
|
648
608
|
```
|
|
649
609
|
|
|
@@ -651,7 +611,7 @@ puts df.filter(my_var.eq 1)
|
|
|
651
611
|
## x y
|
|
652
612
|
## 1 1 3
|
|
653
613
|
```
|
|
654
|
-
As stated by
|
|
614
|
+
As stated by Hadley
|
|
655
615
|
|
|
656
616
|
> dplyr code is ambiguous. Depending on what variables are defined where,
|
|
657
617
|
> filter(df, x == y) could be equivalent to any of:
|
|
@@ -663,18 +623,18 @@ df[x == df$y, ]
|
|
|
663
623
|
df[x == y, ]
|
|
664
624
|
```
|
|
665
625
|
In galaaz this ambiguity does not exist, filter(df, x.eq y) is not a valid expression as
|
|
666
|
-
expressions are build with symbols. In doing filter(df, :x.eq y) we are looking for elements
|
|
626
|
+
expressions are build with symbols. In doing filter(df, R[:x].eq y) we are looking for elements
|
|
667
627
|
of the 'x' column that are equal to a previously defined y variable. Finally in
|
|
668
|
-
filter(df, :x.eq :y) we are looking for elements in which the 'x' column value is equal to
|
|
628
|
+
filter(df, R[:x].eq R[:y]) we are looking for elements in which the 'x' column value is equal to
|
|
669
629
|
the 'y' column value. This can be seen in the following two chunks of code:
|
|
670
630
|
|
|
671
631
|
|
|
672
|
-
```ruby
|
|
632
|
+
``` ruby
|
|
673
633
|
y = 1
|
|
674
634
|
x = 2
|
|
675
635
|
|
|
676
636
|
# looking for values where the 'x' column is equal to the 'y' column
|
|
677
|
-
puts df.filter(:x.eq :y)
|
|
637
|
+
puts df.filter(R[:x].eq R[:y])
|
|
678
638
|
```
|
|
679
639
|
|
|
680
640
|
```
|
|
@@ -683,10 +643,10 @@ puts df.filter(:x.eq :y)
|
|
|
683
643
|
```
|
|
684
644
|
|
|
685
645
|
|
|
686
|
-
```ruby
|
|
646
|
+
``` ruby
|
|
687
647
|
# looking for values where the 'x' column is equal to the 'y' variable
|
|
688
648
|
# in this case, the number 1
|
|
689
|
-
puts df.filter(:x.eq y)
|
|
649
|
+
puts df.filter(R[:x].eq y)
|
|
690
650
|
```
|
|
691
651
|
|
|
692
652
|
```
|
|
@@ -718,18 +678,19 @@ Unfortunately, in R, this function can fail silently if one of the variables isn
|
|
|
718
678
|
in the data frame, but is present in the global environment. We will not go through here how
|
|
719
679
|
to solve this problem in R.
|
|
720
680
|
|
|
721
|
-
In Galaaz the method mutate_y
|
|
681
|
+
In Galaaz the method mutate_y below will work fine and will never fail silently.
|
|
722
682
|
|
|
723
683
|
|
|
724
|
-
```ruby
|
|
684
|
+
``` ruby
|
|
725
685
|
def mutate_y(df)
|
|
726
|
-
|
|
686
|
+
# Mutate column names are Ruby kwargs (y: …). Use .assign only for R `<-` expressions.
|
|
687
|
+
df.mutate(y: R[:a] + R[:x])
|
|
727
688
|
end
|
|
728
689
|
```
|
|
729
690
|
Here we create a data frame that has only one column named 'x':
|
|
730
691
|
|
|
731
692
|
|
|
732
|
-
```ruby
|
|
693
|
+
``` ruby
|
|
733
694
|
df1 = R.data__frame(x: (1..3))
|
|
734
695
|
puts df1
|
|
735
696
|
```
|
|
@@ -742,33 +703,29 @@ puts df1
|
|
|
742
703
|
```
|
|
743
704
|
|
|
744
705
|
Note that method mutate_y will fail independetly from the fact that variable 'a' is defined and
|
|
745
|
-
in the scope of the method. Variable 'a' has no relationship with the symbol
|
|
706
|
+
in the scope of the method. Variable 'a' has no relationship with the symbol `R[:a]` used in the
|
|
746
707
|
definition of 'mutate\_y' above:
|
|
747
708
|
|
|
748
709
|
|
|
749
|
-
```ruby
|
|
710
|
+
``` ruby
|
|
750
711
|
a = 10
|
|
751
712
|
mutate_y(df1)
|
|
752
713
|
```
|
|
753
714
|
|
|
754
715
|
```
|
|
755
|
-
##
|
|
756
|
-
##
|
|
757
|
-
##
|
|
758
|
-
## In addition: Warning message:
|
|
759
|
-
## In mutate_impl(.data, dots) :
|
|
760
|
-
## mismatched protect/unprotect (unprotect with empty protect stack) (RError)
|
|
761
|
-
## Translated to internal error
|
|
716
|
+
## Error: ℹ In argument: `y = a + x`.
|
|
717
|
+
## Caused by error:
|
|
718
|
+
## ! object 'a' not found
|
|
762
719
|
```
|
|
763
720
|
## Different expressions
|
|
764
721
|
|
|
765
|
-
Let's move to the next problem as presented by
|
|
722
|
+
Let's move to the next problem as presented by Hadley where trying to write a function in R
|
|
766
723
|
that will receive two argumens, the first a variable and the second an expression is not trivial.
|
|
767
|
-
|
|
724
|
+
Below we create a data frame and we want to write a function that groups data by a variable and
|
|
768
725
|
summarises it by an expression:
|
|
769
726
|
|
|
770
727
|
|
|
771
|
-
```r
|
|
728
|
+
``` r
|
|
772
729
|
set.seed(123)
|
|
773
730
|
|
|
774
731
|
df <- data.frame(
|
|
@@ -790,7 +747,7 @@ as.data.frame(df)
|
|
|
790
747
|
## 5 2 1 1 4
|
|
791
748
|
```
|
|
792
749
|
|
|
793
|
-
```r
|
|
750
|
+
``` r
|
|
794
751
|
d2 <- df %>%
|
|
795
752
|
group_by(g1) %>%
|
|
796
753
|
summarise(a = mean(a))
|
|
@@ -804,7 +761,7 @@ as.data.frame(d2)
|
|
|
804
761
|
## 2 2 3.333333
|
|
805
762
|
```
|
|
806
763
|
|
|
807
|
-
```r
|
|
764
|
+
``` r
|
|
808
765
|
d2 <- df %>%
|
|
809
766
|
group_by(g2) %>%
|
|
810
767
|
summarise(a = mean(a))
|
|
@@ -818,10 +775,10 @@ as.data.frame(d2)
|
|
|
818
775
|
## 2 2 3
|
|
819
776
|
```
|
|
820
777
|
|
|
821
|
-
As shown by
|
|
778
|
+
As shown by Hadley, one might expect this function to do the trick:
|
|
822
779
|
|
|
823
780
|
|
|
824
|
-
```r
|
|
781
|
+
``` r
|
|
825
782
|
my_summarise <- function(df, group_var) {
|
|
826
783
|
df %>%
|
|
827
784
|
group_by(group_var) %>%
|
|
@@ -834,24 +791,25 @@ my_summarise <- function(df, group_var) {
|
|
|
834
791
|
|
|
835
792
|
In order to solve this problem, coding with dplyr requires the introduction of many new concepts
|
|
836
793
|
and functions such as 'quo', 'quos', 'enquo', 'enquos', '!!' (bang bang), '!!!' (triple bang).
|
|
837
|
-
Again, we'll leave to
|
|
794
|
+
Again, we'll leave to Hadley the explanation on how to use all those functions.
|
|
838
795
|
|
|
839
796
|
Now, let's try to implement the same function in galaaz. The next code block first prints the
|
|
840
|
-
'df' data frame
|
|
797
|
+
'df' data frame defined previously in R (to access an R variable from Galaaz, we use the tilde
|
|
841
798
|
operator '~' applied to the R variable name as symbol, i.e., ':df'. We then create the
|
|
842
799
|
'my_summarize' method and call it passing the R data frame and the group by variable ':g1':
|
|
843
800
|
|
|
844
801
|
|
|
845
|
-
```ruby
|
|
846
|
-
puts
|
|
847
|
-
print "
|
|
802
|
+
``` ruby
|
|
803
|
+
puts ~R[:df]
|
|
804
|
+
print "
|
|
805
|
+
"
|
|
848
806
|
|
|
849
807
|
def my_summarize(df, group_var)
|
|
850
808
|
df.group_by(group_var).
|
|
851
|
-
summarize(a: :a.mean)
|
|
809
|
+
summarize(a: R[:a].mean)
|
|
852
810
|
end
|
|
853
811
|
|
|
854
|
-
puts my_summarize(:df, :g1)
|
|
812
|
+
puts my_summarize(~R[:df], R[:g1])
|
|
855
813
|
```
|
|
856
814
|
|
|
857
815
|
```
|
|
@@ -862,7 +820,7 @@ puts my_summarize(:df, :g1)
|
|
|
862
820
|
## 4 2 2 4 5
|
|
863
821
|
## 5 2 1 1 4
|
|
864
822
|
##
|
|
865
|
-
## # A tibble: 2
|
|
823
|
+
## # A tibble: 2 × 2
|
|
866
824
|
## g1 a
|
|
867
825
|
## <dbl> <dbl>
|
|
868
826
|
## 1 1 2.5
|
|
@@ -871,12 +829,12 @@ puts my_summarize(:df, :g1)
|
|
|
871
829
|
It works!!! Well, let's make sure this was not just some coincidence
|
|
872
830
|
|
|
873
831
|
|
|
874
|
-
```ruby
|
|
875
|
-
puts my_summarize(:df, :g2)
|
|
832
|
+
``` ruby
|
|
833
|
+
puts my_summarize(~R[:df], R[:g2])
|
|
876
834
|
```
|
|
877
835
|
|
|
878
836
|
```
|
|
879
|
-
## # A tibble: 2
|
|
837
|
+
## # A tibble: 2 × 2
|
|
880
838
|
## g2 a
|
|
881
839
|
## <dbl> <dbl>
|
|
882
840
|
## 1 1 3
|
|
@@ -892,7 +850,7 @@ In the previous section we've managed to get rid of all NSE formulation for a si
|
|
|
892
850
|
does this remain true for more complex examples, or will the Galaaz way prove inpractical for
|
|
893
851
|
more complex code?
|
|
894
852
|
|
|
895
|
-
In the next example
|
|
853
|
+
In the next example Hadley proposes us to write a function that given an expression such as 'a'
|
|
896
854
|
or 'a * b', calculates three summaries. What we want a function that does the same as these R
|
|
897
855
|
statements:
|
|
898
856
|
|
|
@@ -913,7 +871,7 @@ summarise(df, mean = mean(a * b), sum = sum(a * b), n = n())
|
|
|
913
871
|
Let's try it in galaaz:
|
|
914
872
|
|
|
915
873
|
|
|
916
|
-
```ruby
|
|
874
|
+
``` ruby
|
|
917
875
|
def my_summarise2(df, expr)
|
|
918
876
|
df.summarize(
|
|
919
877
|
mean: E.mean(expr),
|
|
@@ -922,8 +880,8 @@ def my_summarise2(df, expr)
|
|
|
922
880
|
)
|
|
923
881
|
end
|
|
924
882
|
|
|
925
|
-
puts my_summarise2((
|
|
926
|
-
puts my_summarise2((
|
|
883
|
+
puts my_summarise2((~R[:df]), :a)
|
|
884
|
+
puts my_summarise2((~R[:df]), R[:a] * R[:b])
|
|
927
885
|
```
|
|
928
886
|
|
|
929
887
|
```
|
|
@@ -938,7 +896,7 @@ careful about is the use of 'E' to build expressions from functions 'mean', 'sum
|
|
|
938
896
|
|
|
939
897
|
## Different input and output variable
|
|
940
898
|
|
|
941
|
-
Now the next challenge presented by
|
|
899
|
+
Now the next challenge presented by Hadley is to vary the name of the output variables based on
|
|
942
900
|
the received expression. So, if the input expression is 'a', we want our data frame columns to
|
|
943
901
|
be named 'mean\_a' and 'sum\_a'. Now, if the input expression is 'b', columns
|
|
944
902
|
should be named 'mean\_b' and 'sum\_b'.
|
|
@@ -964,13 +922,13 @@ mutate(df, mean_b = mean(b), sum_b = sum(b))
|
|
|
964
922
|
#> 4 2 2 5 4 3 15
|
|
965
923
|
#> # … with 1 more row
|
|
966
924
|
```
|
|
967
|
-
In order to solve this problem in R,
|
|
925
|
+
In order to solve this problem in R, Hadley needs to introduce some more new functions and notations:
|
|
968
926
|
'quo_name' and the ':=' operator from package 'rlang'
|
|
969
927
|
|
|
970
928
|
Here is our Ruby code:
|
|
971
929
|
|
|
972
930
|
|
|
973
|
-
```ruby
|
|
931
|
+
``` ruby
|
|
974
932
|
def my_mutate(df, expr)
|
|
975
933
|
mean_name = "mean_#{expr.to_s}"
|
|
976
934
|
sum_name = "sum_#{expr.to_s}"
|
|
@@ -979,8 +937,8 @@ def my_mutate(df, expr)
|
|
|
979
937
|
sum_name => E.sum(expr))
|
|
980
938
|
end
|
|
981
939
|
|
|
982
|
-
puts my_mutate((
|
|
983
|
-
puts my_mutate((
|
|
940
|
+
puts my_mutate((~R[:df]), :a)
|
|
941
|
+
puts my_mutate((~R[:df]), :b)
|
|
984
942
|
```
|
|
985
943
|
|
|
986
944
|
```
|
|
@@ -1007,25 +965,25 @@ and variable mean\_name is not followed by ':' but by '=>'. This is standard Ru
|
|
|
1007
965
|
|
|
1008
966
|
## Capturing multiple variables
|
|
1009
967
|
|
|
1010
|
-
Moving on with new complexities,
|
|
968
|
+
Moving on with new complexities, Hadley proposes us to solve the problem in which the
|
|
1011
969
|
summarise function will receive any number of grouping variables.
|
|
1012
970
|
|
|
1013
971
|
This again is quite standard Ruby. In order to receive an undefined number of paramenters
|
|
1014
972
|
the paramenter is preceded by '*':
|
|
1015
973
|
|
|
1016
974
|
|
|
1017
|
-
```ruby
|
|
975
|
+
``` ruby
|
|
1018
976
|
def my_summarise3(df, *group_vars)
|
|
1019
977
|
df.group_by(*group_vars).
|
|
1020
978
|
summarise(a: E.mean(:a))
|
|
1021
979
|
end
|
|
1022
980
|
|
|
1023
|
-
puts my_summarise3((
|
|
981
|
+
puts my_summarise3((~R[:df]), :g1, :g2)
|
|
1024
982
|
```
|
|
1025
983
|
|
|
1026
984
|
```
|
|
1027
|
-
## # A tibble: 4
|
|
1028
|
-
## # Groups: g1 [
|
|
985
|
+
## # A tibble: 4 × 3
|
|
986
|
+
## # Groups: g1 [2]
|
|
1029
987
|
## g1 g2 a
|
|
1030
988
|
## <dbl> <dbl> <dbl>
|
|
1031
989
|
## 1 1 1 3
|
|
@@ -1049,7 +1007,7 @@ In Ruby, there is no lazy evaluation of parameters and 'a' is always a variable
|
|
|
1049
1007
|
Variables assume their value as soon as they are used, so 'x = a' is immediately evaluate and
|
|
1050
1008
|
variable 'x' will receive the value of variable 'a' as soon as the Ruby statement is executed.
|
|
1051
1009
|
Ruby also provides the notion of a symbol; ':a' is a symbol and does not evaluate to anything.
|
|
1052
|
-
Galaaz uses Ruby symbols to build expressions that are not bound to anything: ':a.eq :b' is
|
|
1010
|
+
Galaaz uses Ruby symbols to build expressions that are not bound to anything: 'R[:a].eq R[:b]' is
|
|
1053
1011
|
clearly an expression and has no relationship whatsoever with the statment 'a = b'. By using
|
|
1054
1012
|
symbols, variables and expressions all the possible ambiguities that are found in R are
|
|
1055
1013
|
eliminated in Galaaz.
|
|
@@ -1059,7 +1017,7 @@ of input they are expecting, they might be expecting regular variables or they m
|
|
|
1059
1017
|
expecting expressions and the R function will know how to deal with an input of the form
|
|
1060
1018
|
'a = b', now for the Ruby developer it might not be immediately clear if it should call the
|
|
1061
1019
|
function passing the value 'true' if variable 'a' is equal to variable 'b' or if it should
|
|
1062
|
-
call the function passing the expression ':a.eq :b'.
|
|
1020
|
+
call the function passing the expression 'R[:a].eq R[:b]'.
|
|
1063
1021
|
|
|
1064
1022
|
|
|
1065
1023
|
# Advanced dplyr features
|
|
@@ -1082,28 +1040,28 @@ In the following examples, we show the use of functions 'group\_by\_at', 'summar
|
|
|
1082
1040
|
features of characters in the Starwars movies:
|
|
1083
1041
|
|
|
1084
1042
|
|
|
1085
|
-
```ruby
|
|
1086
|
-
puts (
|
|
1043
|
+
``` ruby
|
|
1044
|
+
puts (~R[:starwars]).head
|
|
1087
1045
|
```
|
|
1088
1046
|
|
|
1089
1047
|
```
|
|
1090
|
-
## # A tibble: 6
|
|
1091
|
-
## name
|
|
1092
|
-
## <chr>
|
|
1093
|
-
## 1 Luke… 172 77 blond fair blue 19 male
|
|
1094
|
-
## 2 C-3PO
|
|
1095
|
-
## 3 R2-D2
|
|
1096
|
-
## 4
|
|
1097
|
-
## 5 Leia… 150 49 brown light brown 19
|
|
1098
|
-
## 6 Owen
|
|
1099
|
-
## #
|
|
1048
|
+
## # A tibble: 6 × 14
|
|
1049
|
+
## name height mass hair_color skin_color eye_color birth_year sex gender
|
|
1050
|
+
## <chr> <int> <dbl> <chr> <chr> <chr> <dbl> <chr> <chr>
|
|
1051
|
+
## 1 Luke Sky… 172 77 blond fair blue 19 male mascu…
|
|
1052
|
+
## 2 C-3PO 167 75 <NA> gold yellow 112 none mascu…
|
|
1053
|
+
## 3 R2-D2 96 32 <NA> white, bl… red 33 none mascu…
|
|
1054
|
+
## 4 Darth Va… 202 136 none white yellow 41.9 male mascu…
|
|
1055
|
+
## 5 Leia Org… 150 49 brown light brown 19 fema… femin…
|
|
1056
|
+
## 6 Owen Lars 178 120 brown, gr… light blue 52 male mascu…
|
|
1057
|
+
## # ℹ 5 more variables: homeworld <chr>, species <chr>, films <list>,
|
|
1100
1058
|
## # vehicles <list>, starships <list>
|
|
1101
1059
|
```
|
|
1102
|
-
The grouped_mean function
|
|
1060
|
+
The grouped_mean function below will receive a grouping variable and calculate summaries for
|
|
1103
1061
|
the value\_variables given:
|
|
1104
1062
|
|
|
1105
1063
|
|
|
1106
|
-
```r
|
|
1064
|
+
``` r
|
|
1107
1065
|
grouped_mean <- function(data, grouping_variables, value_variables) {
|
|
1108
1066
|
data %>%
|
|
1109
1067
|
group_by_at(grouping_variables) %>%
|
|
@@ -1114,7 +1072,22 @@ grouped_mean <- function(data, grouping_variables, value_variables) {
|
|
|
1114
1072
|
|
|
1115
1073
|
gm = starwars %>%
|
|
1116
1074
|
grouped_mean("eye_color", c("mass", "birth_year"))
|
|
1075
|
+
```
|
|
1117
1076
|
|
|
1077
|
+
```
|
|
1078
|
+
## Warning: `funs()` was deprecated in dplyr 0.8.0.
|
|
1079
|
+
## ℹ Please use a list of either functions or lambdas:
|
|
1080
|
+
##
|
|
1081
|
+
## # Simple named list: list(mean = mean, median = median)
|
|
1082
|
+
##
|
|
1083
|
+
## # Auto named with `tibble::lst()`: tibble::lst(mean, median)
|
|
1084
|
+
##
|
|
1085
|
+
## # Using lambdas list(~ mean(., trim = .2), ~ median(., na.rm = TRUE))
|
|
1086
|
+
## Call `lifecycle::last_lifecycle_warnings()` to see where this warning was
|
|
1087
|
+
## generated.
|
|
1088
|
+
```
|
|
1089
|
+
|
|
1090
|
+
``` r
|
|
1118
1091
|
as.data.frame(gm)
|
|
1119
1092
|
```
|
|
1120
1093
|
|
|
@@ -1140,20 +1113,20 @@ as.data.frame(gm)
|
|
|
1140
1113
|
The same code with Galaaz, becomes:
|
|
1141
1114
|
|
|
1142
1115
|
|
|
1143
|
-
```ruby
|
|
1116
|
+
``` ruby
|
|
1144
1117
|
def grouped_mean(data, grouping_variables, value_variables)
|
|
1145
1118
|
data.
|
|
1146
1119
|
group_by_at(grouping_variables).
|
|
1147
1120
|
mutate(count: E.n).
|
|
1148
|
-
summarise_at(E.c(value_variables, "count"),
|
|
1121
|
+
summarise_at(E.c(value_variables, "count"), R[:mean], na__rm: true).
|
|
1149
1122
|
rename_at(value_variables, E.funs(E.paste0("mean_", value_variables)))
|
|
1150
1123
|
end
|
|
1151
1124
|
|
|
1152
|
-
puts grouped_mean((
|
|
1125
|
+
puts grouped_mean((~R[:starwars]), "eye_color", E.c("mass", "birth_year"))
|
|
1153
1126
|
```
|
|
1154
1127
|
|
|
1155
1128
|
```
|
|
1156
|
-
## # A tibble: 15
|
|
1129
|
+
## # A tibble: 15 × 4
|
|
1157
1130
|
## eye_color mean_mass mean_birth_year count
|
|
1158
1131
|
## <chr> <dbl> <dbl> <dbl>
|
|
1159
1132
|
## 1 black 76.3 33 10
|
|
@@ -1175,17 +1148,13 @@ puts grouped_mean((~:starwars), "eye_color", E.c("mass", "birth_year"))
|
|
|
1175
1148
|
|
|
1176
1149
|
# Further reading
|
|
1177
1150
|
|
|
1178
|
-
|
|
1179
|
-
|
|
1180
|
-
* [GraalVM
|
|
1181
|
-
* [TruffleRuby](https://github.com/oracle/truffleruby)
|
|
1182
|
-
* [FastR](https://github.com/oracle/fastr)
|
|
1183
|
-
* [Faster R with FastR](https://medium.com/graalvm/faster-r-with-fastr-4b8db0e0dceb)
|
|
1184
|
-
* [How to make Beautiful Ruby Plots with Galaaz](https://medium.freecodecamp.org/how-to-make-beautiful-ruby-plots-with-galaaz-320848058857)
|
|
1185
|
-
* [Ruby Plotting with Galaaz: An example of tightly coupling Ruby and R in GraalVM](https://towardsdatascience.com/ruby-plotting-with-galaaz-an-example-of-tightly-coupling-ruby-and-r-in-graalvm-520b69e21021)
|
|
1151
|
+
* [JRuby](https://www.jruby.org/) — Ruby on the JVM (Galaaz 2.0)
|
|
1152
|
+
* [How to make Beautiful Ruby Plots with Galaaz](https://medium.freecodecamp.org/how-to-make-beautiful-ruby-plots-with-galaaz-320848058857) (plots; narrative partly pre-2.0)
|
|
1153
|
+
* [Ruby Plotting with Galaaz in GraalVM](https://towardsdatascience.com/ruby-plotting-with-galaaz-an-example-of-tightly-coupling-ruby-and-r-in-graalvm-520b69e21021) (older stack; ideas still useful)
|
|
1186
1154
|
* [How to do reproducible research in Ruby with gKnit](https://towardsdatascience.com/how-to-do-reproducible-research-in-ruby-with-gknit-c26d2684d64e)
|
|
1187
1155
|
* [R for Data Science](https://r4ds.had.co.nz/)
|
|
1188
1156
|
* [Advanced R](https://adv-r.hadley.nz/)
|
|
1157
|
+
* Historical context: [GraalVM](https://www.graalvm.org/), [TruffleRuby](https://github.com/oracle/truffleruby), [FastR](https://github.com/oracle/fastr)
|
|
1189
1158
|
|
|
1190
1159
|
# Conclusion
|
|
1191
1160
|
|