13
$\begingroup$

In R, there is a package "dplyr" that works on data.frame objects, which is one of the origins of the Mathematica Dataset construct. One of the things dplyr can do is "mutate" the columns of a data.frame. Here is an example that I hope will be self explanatory. Consider a data.frame df with columns a, b and c. I want to change column b so that it is a^2 and I then want to change column c so that it is 2*b, where b is the new value of b. (Yes, I know there is a computational shortcut).

 df %>% mutate(b = a^2,c=2b)

Here is how we could do the equivalent thing in Mathematica.

 mutate[df_,rules_]:=Fold[{s, r} \[Function] Query[All, ReplacePart[#, r]  &]@s, df, rules]

Example

 mutate[dataset,{"b" -> #a^2, "c" -> 2*#b}]

Does anyone have any better ideas or ways to generalize this? And, yes one can use RLink to actually use dplyr directly, but for the moment I want to stick with pure Mathematica.

$\endgroup$
  • 1
    $\begingroup$ Generalize towards what? $\endgroup$ – alancalvitti Oct 6 '15 at 1:14
  • $\begingroup$ Yes, if you had only two rules for altering the contents of the columns, your way might work. But I do not think it is practical for altering, say, 20 columns. As for whether the function is needed, I think if you talk to the R community, you would find that mutate from the dplyr package is one of the most heavily used functions in data analysis and that the convenience of being able to write a single mutate in which subsequent transformations can use prior transformations is extremely useful. $\endgroup$ – Seth Chandler Oct 7 '15 at 16:07
  • $\begingroup$ I deleted my earlier comment as it did not work as expected, but also took a stab at a composable operator, below. $\endgroup$ – alancalvitti Oct 7 '15 at 18:02
  • $\begingroup$ @SethChandler +1 Your solution looks quite good, I have something very very similar (still using Fold) but there are some other approaches also. Could you develop what you mean by "... generalize this" ? $\endgroup$ – SquareOne Oct 31 '15 at 1:58
2
$\begingroup$

Partial workaround, in operator form:

mutate[k_ -> f_][a_Association] := Insert[a, k -> f[a], Key[k]];

Eg,

ds = {<|"a" -> 1, "b" -> 3, "c" -> 5|>, <|"a" -> 2, "b" -> 4, 
    "c" -> 6|>} // Dataset

enter image description here

ds[All, mutate["b" -> (#a^2 &)] /* mutate["c" -> (2 #b &)]]

enter image description here

Those skilled in pattern matching can define mutate to take a list of rules and wrap RightComposition around them.

$\endgroup$
1
$\begingroup$

Similar to the answer above:

ds = {<|"a" -> 1, "b" -> 3, "c" -> 5|>, <|"a" -> 2, "b" -> 4, 
"c" -> 6|>} // Dataset

ds // Map[<|#, "b" -> #a^2, "c" -> 2*#b|> &]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.