2

Via SQL query I produce a list

dblist = {{"ID", "One", "Two"}, {"C1", 10.24, 1.1123456*^10}, {"C2", 
20.23, 1.9123456*^10}, {"C3", 3., 2.01123456*^10}, {"C4", 20.12, 
17123456.}, {"C5", Null, 25123456.}, {"C6", 20., Null}};

like this and convert it into a dataset:

ds = Dataset[AssociationThread[First @ dblist, #] & /@ Rest@dblist]

enter image description here

Now, I'm rounding the values of "One" and produce a new dataset:

dblist[[All, 2]] = Round[dblist[[All, 2]], 1];
dblist[[1, 2]] = "One";
dsround = Dataset[AssociationThread[First @ dblist, #] & /@ Rest@dblist]

enter image description here

About the trouble with the Null I care later on. But now comes the part I don't understand. I'd like to write the values of "Two" in ScientificForm and ony one digit after the point. Hence, I apply the same procedure as before with the rounding:

dblist[[All, 3]] = ScientificForm[dblist[[All, 3]], 2];
dblist[[1, 3]] = "Two";
dsscform = Dataset[AssociationThread[First @ dblist, #] & /@ Rest@dblist]

But this does not work as expected:

enter image description here

Any ideas where my error in reasoning lies? Why do I get in every row the whole list?

I appreciate all hints and ideas.

Lea
  • 942
  • 4
  • 12
  • You have written below, that you want to continue to work with the data. Why then use Dataset which is infering types for presentation purposes. I would suggest to work with Association and use Dataset when you are going for presentation -- here you can build yourself a constructor to produce a dataset with scientific form output. I would also suggest to replace Null with something like Missing[] which can be handled more easily. – gwr Jan 24 '19 at 12:02
  • @gwr: that's an intresting comment, I should think about my concept with the Datasets But only after my talk about the analysis next week... – Lea Jan 24 '19 at 12:11
  • If you have not done so, yet, have a look at: (87360) and also (146171). – gwr Jan 24 '19 at 12:13
  • Regarding the formatting of numbers take a look at (8923). – gwr Jan 24 '19 at 12:43

3 Answers3

2

The output of foo=ScientificForm[dblist[[All, 3]], 2] looks like a list but if you run Dimension[foo] you do not get 7, but 2: because ScientificForm is a wrapper (think of it as a display mode, e.g. if x= ScientificForm[1] you cannot do the calculation such as x+1). More apparent if you run FullForm[foo]. Therefore,

nf = (#1 <> "*10^(" <> #3 <> ")" &);
dblist[[All, 3]] = 
  Map[ToString@ScientificForm[#, 2, NumberFormat -> nf] &, 
   dblist[[All, 3]]];
dblist[[1, 3]] = "Two";
dsscform = 
 Dataset[AssociationThread[First@dblist, #] & /@ Rest@dblist]

enter image description here

ref: export table with number written in scientific notation

And, for the "One" column, you may try something like this to deal with the null:

dblist[[All, 2]] = 
  If[NumericQ[#], Round[#, 1], 
     If[# === Null, "doSomething", If[# == "One", "One"]]] & /@ 
   dblist[[All, 2]];

or just replace them in dblist first.

egwene sedai
  • 2,355
  • 16
  • 24
  • nice idea, but this only helps for presentation issues. I want to work further with those datasets, e.g via using cuts like this one: test = ds[Select[#"Two" >= 1.9*^10 &]]. This doesn't work with the ds = dsscform as proposed by you, while it still works when I use ds = dsround. – Lea Jan 24 '19 at 08:04
2

By testing the attributes of Round and ScientificForm, ScientificForm is not Listable, so it shall not work on a list directly. try Map or /@.

Attributes[Round]

{Listable, NumericFunction, Protected}

Attributes[ScientificForm]

{NHoldRest, Protected}

then, the upper codes could become like

dblist[[All, 3]] = ScientificForm[#, 2] & /@ dblist[[All, 3]];
(*dblist[[All,3]] = Map[ScientificForm[#,2]&,dblist[[All,3]]];*)
dblist[[1, 3]] = "Two";
dsscform = Dataset[AssociationThread[First@dblist, #] & /@ Rest@dblist]

enter image description here

Or, I suggest make the best of operations on Dataset instead.

dblist = {{"ID", "One", "Two"}, {"C1", 10.24, 1.1123456*^10}, {"C2", 
20.23, 1.9123456*^10}, {"C3", 3., 2.01123456*^10}, {"C4", 20.12, 
17123456.}, {"C5", Null, 25123456.}, {"C6", 20., Null}};

(*dblist = dblist/. Null -> 0 *) (* replace Null values*)

ds = Dataset[AssociationThread[First @ dblist, #] & /@ Rest@dblist]

enter image description here

firstly define operations

fRound[num_] := Round[num, 1]
fSciForm[num_] := ScientificForm[num, 2]

then appy them on columns of the dataset ds

ds[All, {"One" -> fRound, "Two" -> fSciForm}]

enter image description here

Jerry
  • 2,459
  • 9
  • 15
  • The operations suggestion is very nice, this represents what I was searching for. And I think it is a very elegant solution in addition. – Lea Jan 24 '19 at 09:42
  • (+1) I would suggest to work with Missing[] instead of Null for obvious reasons: ds // Query[All, { "One" -> ( Switch[#, Null, Missing[], _, Round[#]] &) , "Two" -> ( Switch[#, Null, Missing[], _, ScientificForm[#, 2]] &) } ] – gwr Jan 24 '19 at 11:39
  • @gwr I already use Missing[] I just haven't described it above, should have avoided the Null in my example ;) – Lea Jan 24 '19 at 12:08
  • other question: at the moment I don't understand were the double quotes in the ScientificForm come from. – Lea Jan 24 '19 at 12:12
  • @Lea Because the result is merely a Form, made of strings. Try inputting ScientificForm[10000.0,2], then select the output and from the Menu select [Cell]->[Show Cell Expression] you can get the essense. – Jerry Jan 24 '19 at 12:27
2

In extension to my comments and to make the output a bit prettier:

ds // Query[All,
    {
        "One" -> ( Switch[#, Null, Missing[], _, Round[#]] &)
        , "Two" -> ( Switch[#, Null, Missing[], _, NumberForm[#, {2, 1}] ] &)
    }
]

dataset

gwr
  • 13,452
  • 2
  • 47
  • 78