Goal Docs

Translating dplyr’s examples to Goal

We show below an html highlighted version of the Goal file found at examples/dplyr.goal in the repos.

/ We translate to Goal most examples (as of 2024-09-12) from:
/   https://dplyr.tidyverse.org/articles/dplyr.html
/ We put in a comment the dplyr version for each example (uncomment to print
/ it before the table). We try to write solutions close to dplyr's ones.
(env"GOALLIB")or"GOALLIB"env"../lib"
import"fmt" / assuming GOALLIB contains now goal's lib directory
/ pp[t] pretty prints dict as table, assuming string keys, limiting results to
/ at most 5 rows and 8 columns, using "%.1f" to format floats.
pp:fmt.tbl[;5;8;"%.1f"]
/ Using the csv file adapted from https://swapi.dev for dplyr's examples.
t:{(*'x)!1_'x}@csv 'read"data/starwars.csv" / read csv file into t
t:+sub["_";""]@+t                           / clean non-identifier column names
t:@[t;!"height mass birthyear";"n"$]        / parse numeric columns

/ dim(starwars)
say(nr:#*t;#t) / dimensions
/ 87 14

/ starwars
pp t
/ === Table 87x14 ===
/             name height  mass haircolor     skincolor eyecolor birthyear      sex
/ ---------------- ------ ----- --------- ------------- -------- --------- --------
/ "Luke Skywalker"  172.0  77.0   "blond"        "fair"   "blue"      19.0   "male"
/          "C-3PO"  167.0  75.0      "NA"        "gold" "yellow"     112.0   "none"
/          "R2-D2"   96.0  32.0      "NA" "white, blue"    "red"      33.0   "none"
/    "Darth Vader"  202.0 136.0    "none"       "white" "yellow"      41.9   "male"
/    "Leia Organa"  150.0  49.0   "brown"       "light"  "brown"      19.0 "female"

/ starwars %>% filter(skin_color == "light", eye_color == "brown")
pp(1;..skincolor="light";..eyecolor="brown")#t
/ === Table 7x14 ===
/                name height mass haircolor skincolor eyecolor birthyear      sex
/ ------------------- ------ ---- --------- --------- -------- --------- --------
/       "Leia Organa"  150.0 49.0   "brown"   "light"  "brown"      19.0 "female"
/ "Biggs Darklighter"  183.0 84.0   "black"   "light"  "brown"      24.0   "male"
/     "Padmé Amidala"  185.0 45.0   "brown"   "light"  "brown"      46.0 "female"
/             "Cordé"  157.0  NaN   "brown"   "light"  "brown"       NaN     "NA"
/             "Dormé"  165.0  NaN   "brown"   "light"  "brown"       NaN "female"

/ starwars %>% arrange(height, mass)
rmnan:{(0;..|/nan'x@!p.x)^y} / removes rows with NaNs in columns x from table y
pp (..x@<height)(..x@<mass)rmnan["mass height";t]
/ === Table 59x14 ===
/                    name height mass haircolor     skincolor  eyecolor birthyear    sex
/ ----------------------- ------ ---- --------- ------------- --------- --------- ------
/                  "Yoda"   66.0 17.0   "white"       "green"   "brown"     896.0 "male"
/          "Ratts Tyerel"   79.0 15.0    "none"  "grey, blue" "unknown"       NaN "male"
/ "Wicket Systri Warrick"   88.0 20.0   "brown"       "brown"   "brown"       8.0 "male"
/              "Dud Bolt"   94.0 45.0    "none"  "blue, grey"  "yellow"       NaN "male"
/                 "R2-D2"   96.0 32.0      "NA" "white, blue"     "red"      33.0 "none"

/ starwars %>% arrange(desc(height))
pp (..x@>height)rmnan["height";t]
/ === Table 81x14 ===
/           name height  mass haircolor skincolor eyecolor birthyear    sex
/ -------------- ------ ----- --------- --------- -------- --------- ------
/  "Yarael Poof"  264.0   NaN    "none"   "white" "yellow"       NaN "male"
/      "Tarfful"  234.0 136.0   "brown"   "brown"   "blue"       NaN "male"
/      "Lama Su"  229.0  88.0    "none"    "grey"  "black"       NaN "male"
/    "Chewbacca"  228.0 112.0   "brown" "unknown"   "blue"     200.0 "male"
/ "Roos Tarpals"  224.0  82.0    "none"    "grey" "orange"       NaN "male"

/ starwars %>% slice(5:10)
pp t[4+!5]
/ === Table 5x14 ===
/                 name height  mass     haircolor    skincolor eyecolor birthyear      sex
/ -------------------- ------ ----- ------------- ------------ -------- --------- --------
/        "Leia Organa"  150.0  49.0       "brown"      "light"  "brown"      19.0 "female"
/          "Owen Lars"  178.0 120.0 "brown, grey"      "light"   "blue"      52.0   "male"
/ "Beru Whitesun Lars"  165.0  75.0       "brown"      "light"   "blue"      47.0 "female"
/              "R5-D4"   97.0  32.0          "NA" "white, red"    "red"       NaN   "none"
/  "Biggs Darklighter"  183.0  84.0       "black"      "light"  "brown"      24.0   "male"

/ starwars %>% slice_head(n = 3)
pp t[!3]
/ === Table 3x14 ===
/             name height mass haircolor     skincolor eyecolor birthyear    sex
/ ---------------- ------ ---- --------- ------------- -------- --------- ------
/ "Luke Skywalker"  172.0 77.0   "blond"        "fair"   "blue"      19.0 "male"
/          "C-3PO"  167.0 75.0      "NA"        "gold" "yellow"     112.0 "none"
/          "R2-D2"   96.0 32.0      "NA" "white, blue"    "red"      33.0 "none"

/ starwars %>% slice_sample(n = 5)
pp t[5?nr]
/ === Table 5x14 ===
/               name height mass haircolor       skincolor  eyecolor birthyear      sex
/ ------------------ ------ ---- --------- --------------- --------- --------- --------
/          "Gasgano"  122.0  NaN    "none"   "white, blue"   "black"       NaN   "male"
/      "Nute Gunray"  191.0 90.0    "none" "mottled green"     "red"       NaN   "male"
/    "Padmé Amidala"  185.0 45.0   "brown"         "light"   "brown"      46.0 "female"
/       "Wat Tambor"  193.0 48.0    "none"   "green, grey" "unknown"       NaN   "male"
/ "Lando Calrissian"  177.0 79.0   "black"          "dark"   "brown"      31.0   "male"

/ starwars %>% slice_sample(prop = 0.1)
pp t[(-10!nr)?nr]
/ === Table 8x14 ===
/                name height  mass haircolor      skincolor        eyecolor birthyear    sex
/ ------------------- ------ ----- --------- -------------- --------------- --------- ------
/          "Grievous"  216.0 159.0    "none" "brown, white" "green, yellow"       NaN "male"
/       "Cliegg Lars"  183.0   NaN   "brown"         "fair"          "blue"      82.0 "male"
/          "Plo Koon"  188.0  80.0    "none"       "orange"         "black"      22.0 "male"
/             "Cordé"  157.0   NaN   "brown"        "light"         "brown"       NaN   "NA"
/ "Biggs Darklighter"  183.0  84.0   "black"        "light"         "brown"      24.0 "male"

/ starwars %>% filter(!is.na(height)) %>% slice_max(height, n = 3)
pp 3#'(..x@>height)rmnan["height";t]
/ === Table 3x14 ===
/          name height  mass haircolor skincolor eyecolor birthyear    sex
/ ------------- ------ ----- --------- --------- -------- --------- ------
/ "Yarael Poof"  264.0   NaN    "none"   "white" "yellow"       NaN "male"
/     "Tarfful"  234.0 136.0   "brown"   "brown"   "blue"       NaN "male"
/     "Lama Su"  229.0  88.0    "none"    "grey"  "black"       NaN "male"

/ starwars %>% select(hair_color, skin_color, eye_color)
pp t[;!"haircolor skincolor eyecolor"]
/ === Table 87x3 ===
/ haircolor     skincolor eyecolor
/ --------- ------------- --------
/   "blond"        "fair"   "blue"
/      "NA"        "gold" "yellow"
/      "NA" "white, blue"    "red"
/    "none"       "white" "yellow"
/   "brown"       "light"  "brown"

/ starwars %>% select(hair_color:eye_color)
krng:{[t;x;y](k?x)_(1+k?y)#k:!t} / inclusive key range from x to y
pp krng[t;"haircolor";"eyecolor"]#t
/ === Table 87x3 ===
/ haircolor     skincolor eyecolor
/ --------- ------------- --------
/   "blond"        "fair"   "blue"
/      "NA"        "gold" "yellow"
/      "NA" "white, blue"    "red"
/    "none"       "white" "yellow"
/   "brown"       "light"  "brown"

/ starwars %>% select(!(hair_color:eye_color))
pp(krng[t;"haircolor";"eyecolor"]^(!t))#t
/ === Table 87x11 ===
/             name height  mass birthyear      sex      gender  homeworld species
/ ---------------- ------ ----- --------- -------- ----------- ---------- -------
/ "Luke Skywalker"  172.0  77.0      19.0   "male" "masculine" "Tatooine" "Human"
/          "C-3PO"  167.0  75.0     112.0   "none" "masculine" "Tatooine" "Droid"
/          "R2-D2"   96.0  32.0      33.0   "none" "masculine"    "Naboo" "Droid"
/    "Darth Vader"  202.0 136.0      41.9   "male" "masculine" "Tatooine" "Human"
/    "Leia Organa"  150.0  49.0      19.0 "female"  "feminine" "Alderaan" "Human"

/ starwars %>% select(ends_with("color"))
pp(rx/color$/!:)#t
/ === Table 87x3 ===
/ haircolor     skincolor eyecolor
/ --------- ------------- --------
/   "blond"        "fair"   "blue"
/      "NA"        "gold" "yellow"
/      "NA" "white, blue"    "red"
/    "none"       "white" "yellow"
/   "brown"       "light"  "brown"

/ starwars %>% select(home_world = homeworld)
pp t[;"homeworld"]
/ === Table 87x1 ===
/  homeworld
/ ----------
/ "Tatooine"
/ "Tatooine"
/    "Naboo"
/ "Tatooine"
/ "Alderaan"

/ starwars %>% rename(home_world = homeworld)
pp(,"homeworld")^t..[homeWorld:homeworld] / camelCase instead because already removed _
/ === Table 87x14 ===
/             name height  mass haircolor     skincolor eyecolor birthyear      sex
/ ---------------- ------ ----- --------- ------------- -------- --------- --------
/ "Luke Skywalker"  172.0  77.0   "blond"        "fair"   "blue"      19.0   "male"
/          "C-3PO"  167.0  75.0      "NA"        "gold" "yellow"     112.0   "none"
/          "R2-D2"   96.0  32.0      "NA" "white, blue"    "red"      33.0   "none"
/    "Darth Vader"  202.0 136.0    "none"       "white" "yellow"      41.9   "male"
/    "Leia Organa"  150.0  49.0   "brown"       "light"  "brown"      19.0 "female"

/ starwars %>% mutate(height_m = height / 100)
pp rmnan["height";t]..[heightm:height%100]
/ === Table 81x15 ===
/             name height  mass haircolor     skincolor eyecolor birthyear      sex
/ ---------------- ------ ----- --------- ------------- -------- --------- --------
/ "Luke Skywalker"  172.0  77.0   "blond"        "fair"   "blue"      19.0   "male"
/          "C-3PO"  167.0  75.0      "NA"        "gold" "yellow"     112.0   "none"
/          "R2-D2"   96.0  32.0      "NA" "white, blue"    "red"      33.0   "none"
/    "Darth Vader"  202.0 136.0    "none"       "white" "yellow"      41.9   "male"
/    "Leia Organa"  150.0  49.0   "brown"       "light"  "brown"      19.0 "female"

/ starwars %>% mutate(height_m = height / 100) %>% select(height_m, height, everything())
pp rmnan["height";t]..[heightm:height%100][;"heightm","height",(,"height")^!t]
/ === Table 81x15 ===
/ heightm height             name  mass haircolor     skincolor eyecolor birthyear
/ ------- ------ ---------------- ----- --------- ------------- -------- ---------
/     1.7  172.0 "Luke Skywalker"  77.0   "blond"        "fair"   "blue"      19.0
/     1.7  167.0          "C-3PO"  75.0      "NA"        "gold" "yellow"     112.0
/     1.0   96.0          "R2-D2"  32.0      "NA" "white, blue"    "red"      33.0
/     2.0  202.0    "Darth Vader" 136.0    "none"       "white" "yellow"      41.9
/     1.5  150.0    "Leia Organa"  49.0   "brown"       "light"  "brown"      19.0

/ starwars %>% mutate( height_m = height / 100, BMI = mass / (height_m^2)) %>% select(BMI, everything())
pp rmnan["mass height";t]..[heightm:q.hm:height%100;BMI:mass%(q.hm*q.hm)][;"BMI",!t]
/ === Table 59x15 ===
/  BMI             name height  mass haircolor     skincolor eyecolor birthyear
/ ---- ---------------- ------ ----- --------- ------------- -------- ---------
/ 26.0 "Luke Skywalker"  172.0  77.0   "blond"        "fair"   "blue"      19.0
/ 26.9          "C-3PO"  167.0  75.0      "NA"        "gold" "yellow"     112.0
/ 34.7          "R2-D2"   96.0  32.0      "NA" "white, blue"    "red"      33.0
/ 33.3    "Darth Vader"  202.0 136.0    "none"       "white" "yellow"      41.9
/ 21.8    "Leia Organa"  150.0  49.0   "brown"       "light"  "brown"      19.0

/ starwars %>% mutate( height_m = height / 100, BMI = mass / (height_m^2), .keep = "none")
pp rmnan["mass height";t].. ..[heightm:q.hm:height%100;BMI:mass%(q.hm*q.hm)]
/ === Table 59x2 ===
/ heightm  BMI
/ ------- ----
/     1.7 26.0
/     1.7 26.9
/     1.0 34.7
/     2.0 33.3
/     1.5 21.8

/ starwars %>% summarise(height = mean(height, na.rm = TRUE))
avg:{?[x:(nan)^x;(+/x)%#x;0n]}
pp@..[height:,avg t..height]
/ === Table 1x1 ===
/ height
/ ------
/  174.6

/ starwars %>% group_by(species, sex) %>%
/       select(height, mass) %>%
/       summarise(
/         height = mean(height, na.rm = TRUE),
/         mass = mean(mass, na.rm = TRUE)
/       )
/ rby groups by cols k, summarises with reducing f[t;by] (by contains grouping
/ indices), sorts result by k. Note that ordering the results is not necessary,
/ but we do it for compatibility with dplyr's example.
rby:{[k;f;t]
  by:%?["A"~@g:t k;{(1+|/'x)/x}@%'g;g]
  (t[&¿by;k],f[t;by]){x@<x y}/|k
}
pp rby[!"species sex";{..[height:avg'=x..height!y; mass:avg'=x..mass!y]};t]
/ === Table 41x4 ===
/    species      sex height  mass
/ ---------- -------- ------ -----
/   "Aleena"   "male"   79.0  15.0
/ "Besalisk"   "male"  198.0 102.0
/   "Cerean"   "male"  198.0  82.0
/ "Chagrian"   "male"  196.0   NaN
/ "Clawdite" "female"  168.0  55.0

/ rby2 offers an alternative approach for the typical case where result columns
/ keep the same names as the columns they're computed from using a particular
/ function.
rby2:{[k;r;f;t]
  m:¿by:%?["A"~@g:t k;{(1+|/'x)/x}@%'g;g]
  (t[&¿by;k],f@''(..=x!p.by)'r#t){x@<x y}/|k
}
pp rby2[!"species sex";!"height mass";(avg;avg);t]
pp rby2[!"species sex";!"height mass";avg;t] / same function applied to height & mass

/ select(starwars, name)
pp t[;"name"]
/ === Table 87x1 ===
/             name
/ ----------------
/ "Luke Skywalker"
/          "C-3PO"
/          "R2-D2"
/    "Darth Vader"
/    "Leia Organa"

/ select(starwars, 1)
pp 1#t / same as above

/ name <- "color"; select(starwars, ends_with(name))
name:"color"; pp{~(!x)=(!x)-name}#t
/ === Table 87x3 ===
/ haircolor     skincolor eyecolor
/ --------- ------------- --------
/   "blond"        "fair"   "blue"
/      "NA"        "gold" "yellow"
/      "NA" "white, blue"    "red"
/    "none"       "white" "yellow"
/   "brown"       "light"  "brown"

/ df <- starwars %>% select(name, height, mass)
df:"name""height""mass"#t
/ mutate(df, height + 10)
pp df..["height+10":height+10]
/ === Table 87x4 ===
/             name height  mass height+10
/ ---------------- ------ ----- ---------
/ "Luke Skywalker"  172.0  77.0     182.0
/          "C-3PO"  167.0  75.0     177.0
/          "R2-D2"   96.0  32.0     106.0
/    "Darth Vader"  202.0 136.0     212.0
/    "Leia Organa"  150.0  49.0     160.0

/ var <- seq(1, nrow(df)); mutate(df, new = var)
var:1+!#*df; pp df..[new:q.var]
/ === Table 87x4 ===
/             name height  mass new
/ ---------------- ------ ----- ---
/ "Luke Skywalker"  172.0  77.0   1
/          "C-3PO"  167.0  75.0   2
/          "R2-D2"   96.0  32.0   3
/    "Darth Vader"  202.0 136.0   4
/    "Leia Organa"  150.0  49.0   5

/ starwars %>% filter(species == "Droid")
pp(1;..species="Droid")#t
/ === Table 6x14 ===
/     name height  mass haircolor     skincolor    eyecolor birthyear    sex
/ -------- ------ ----- --------- ------------- ----------- --------- ------
/  "C-3PO"  167.0  75.0      "NA"        "gold"    "yellow"     112.0 "none"
/  "R2-D2"   96.0  32.0      "NA" "white, blue"       "red"      33.0 "none"
/  "R5-D4"   97.0  32.0      "NA"  "white, red"       "red"       NaN "none"
/  "IG-88"  200.0 140.0    "none"       "metal"       "red"      15.0 "none"
/ "R4-P17"   96.0   NaN    "none" "silver, red" "red, blue"       NaN "none"

/ starwars %>% group_by(species) %>% summarise( n = n(), mass = mean(mass, na.rm = TRUE)) %>% filter( n > 1, mass > 50)
pp(1;..n>1;..mass>50)#rby["species";{..[n:=y; mass:avg'=x..mass!y]};t]
/ === Table 9x3 ===
/    species  n mass
/ ---------- -- ----
/    "Droid"  6 69.8
/   "Gungan"  3 74.0
/    "Human" 35 81.3
/ "Kaminoan"  2 88.0
/ "Mirialan"  2 53.1