7
$\begingroup$

In my dataset of (x,y) values I have a lot of points with the exact same values on x and y: {{1,2},{3,4},{3,4},{3,4},{4,5}}

So when I plot them with ListPlot it looks like I have only one point for {3,4}, which doesn't help me assess the real distribution of my data.

What would be the best way to get a better sense of the distribution visually, to know that behind a single point are in fact hidden lots of other points?

$\endgroup$
0

8 Answers 8

8
$\begingroup$

try this also:

t = {{1, 2}, {3, 4}, {3, 4}, {3, 4}, {4, 5}, {3, 4}, {1, 2}, {6, 7}};

ListPlot[Labeled[Style[#1, PointSize[#2/50], Hue[#2/10]], 
    Style[#2, Bold, 12]] & @@@ (Tally[t])]

enter image description here

$\endgroup$
2
  • 2
    $\begingroup$ If you make it PointSize[Sqrt[#2]/50] then the area of the dots will be proportional to the tally, which seems more appropriate. $\endgroup$
    – user484
    Sep 22, 2014 at 4:30
  • $\begingroup$ @RahulNarain Ok. Thanks. $\endgroup$ Sep 22, 2014 at 12:59
8
$\begingroup$

I suggest two more approaches in addition to the ones proposed in other answers:

Arrange duplicates on a circle:

Inspired by Rahul's jittering idea, you can also arrange the duplicates in a more regular fashion -- e.g., on a circle around their common center:

ClearAll[coordsF];
coordsF[sc_:.2] := Table[# + If[#2 === 1, 0, sc {Sin[2 Pi k /#2], Cos[2 Pi k /#2]}], 
  {k, #2}] &;

t = {{1, 2}, {3, 4}, {3, 4}, {3, 4}, {4, 5}};
tb = RandomInteger[{1, 7}, {50, 2}];


ListPlot[coordsF[] @@@ Tally[t], 
 BaseStyle -> PointSize[.03], Frame -> True, PlotStyle -> "SolarColors",
 Prolog -> {Opacity[.5], Blue, Thick, Line[t],
   EdgeForm[{Opacity[.5], Blue, Thick}],
   FaceForm[{Opacity[1], LightBlue}], Disk[#, .35] & /@ t},
 AxesOrigin -> {0, 0}, PlotRange -> {{0, 6}, {0, 6}}, AspectRatio -> 1]

enter image description here

ListPlot[coordsF[] @@@ Tally[tb], 
 BaseStyle -> PointSize[.03], Frame -> True, PlotStyle -> "SolarColors", 
 Prolog -> {Blue, Opacity[.5], Line@tb, Yellow, Opacity[.5],  Disk[#, .3] & /@ tb}, 
 AspectRatio -> 1, PlotRangePadding -> .5,  AxesOrigin -> {0, 0}]

enter image description here

BubbleChart:

BubbleChart with its many features and options is a natural tool for this kind of data. You can use Prolog or Epilog to add a line if you need to join the points.

BubbleChart[Append @@@ Tally[t], ChartStyle -> 63,
 ChartLabels -> (Style[#, # 10, Bold] & /@ Tally[t][[All, -1]]),
 Prolog -> {Thick, Blue, Line[t]}, PlotRange -> {{0, 6}, {0, 6}}]

enter image description here

BubbleChart with a custom ChartElementFunction:

The following custom ChartElementFunction produces a PieChart with equal divisions.

ceF[sc_: .03, style_: 24][c : {{xmin_, xmax_}, {ymin_, ymax_}}, y_, ___] :=
  With[{pc = PieChart[ConstantArray[1, {y[[-1]]}], ChartStyle->style], 
   cntr = Mean@Transpose@c}, 
   First[Replace[pc, DiskBox[x_, r_, z_] :> DiskBox[cntr, Scaled[sc], z], {0, Infinity}]]];

BubbleChart[List /@ (Append @@@ Tally[t]),
  Prolog -> {Thick, Blue, Line[t]}, 
  ChartElementFunction -> ceF[.05, 64], 
  PlotRange -> {{0, 6}, {0, 6}}] // Deploy

enter image description here

BubbleChart[List /@ (Append @@@ Tally[tb]),
  Prolog -> {Thick, Opacity[.5], Blue, Line[tb]}, 
  ChartElementFunction -> ceF[.04, "Rainbow"]] // Deploy

enter image description here

$\endgroup$
6
$\begingroup$

Jittering is a popular way to handle overplotting of discrete data.

data = {{1, 2}, {3, 4}, {3, 4}, {3, 4}, {4, 5}};
jitter = 0.5;
ListPlot[data + RandomReal[{-jitter/2, jitter/2}, Dimensions[data]]]

enter image description here

$\endgroup$
2
$\begingroup$

Sort the points, just in case, Split into lists of identical elements and then create a Graphics containing a list of Disk at the appropriate position with size proportional to the number of identical elements.

points = {{1, 2}, {3, 4}, {3, 4}, {3, 4}, {4, 5}};
splitpoints = Split[Sort[points]];
Graphics[Map[Disk[First[#], Length[#]/10] &, splitpoints]]
$\endgroup$
2
  • $\begingroup$ This works great, except when you have a LOT of points with the same value, in this case the dots are so big that they hide smaller dots and fill almost the whole figure. $\endgroup$
    – Sulli
    Sep 21, 2014 at 17:15
  • $\begingroup$ Which was exactly why I wrote "with size proportional to the number of identical elements." You could replace my /10 scale factor with /100 or /10^29 or even Log[Log[Log[Log[Length[#]]]]] if you have a very large range of different numbers of repetitions. Graphics seems to be all about spending at least several times as much time as it took you to get the calculations correct now fiddling over and over and over trying to get it to look almost like what you think it has to look like to be acceptable. $\endgroup$
    – Bill
    Sep 21, 2014 at 17:54
2
$\begingroup$

One idea would be to take the PlotMarker equal to the number of repetitions.

Let's take your example data first:

t = {{1, 2}, {3, 4}, {3, 4}, {3, 4}, {4, 5}};

The first step would be to count the repetitions

ft = Tally[t]

(* {{{1, 2}, 1}, {{3, 4}, 3}, {{4, 5}, 1}} *)

ftlg = Length[ft];
Table[p[i] = ListPlot[{ft[[i]][[1]]}, PlotMarkers -> {ft[[i]][[2]]}, PlotRange -> {{0, 10}, {0, 10}}], {i, 1, ftlg}];

Show[Table[p[i], {i, 1, ftlg}]]

enter image description here

The code is independent of the sample data. So you can try it with more complex data. Of course you could also use other rules to define the PlotMarker.

Regards, Wolfgang

$\endgroup$
1
  • $\begingroup$ (at) eldo. Sure, thanks, and sorry for my laziness ... $\endgroup$ Sep 21, 2014 at 17:33
1
$\begingroup$

I would probably use Histogram3D

data = {{1, 2}, {3, 4}, {3, 4}, {3, 4}, {4, 5}};

Histogram3D @ data

enter image description here

$\endgroup$
1
$\begingroup$

You can use colors to distinguish them. Automatically:

lst = {{1, 2}, {3, 4}, {3, 4}, {3, 4}, {4, 5}}
tlst = Counts[lst]
bycounts = Map[DeleteDuplicates, GroupBy[lst, tlst[#] &]]
ListPlot[Values[bycounts]]

Or you can set your own markers with the ListPlot options. For example, you could label each point with its count as follows:

ListPlot[Values[bycounts],
 PlotMarkers -> ToString /@ Keys[bycounts]]

using counts as markers

$\endgroup$
3
  • $\begingroup$ This colors the points but I still can't distinguish them as they are stacked $\endgroup$
    – Sulli
    Sep 21, 2014 at 17:13
  • $\begingroup$ The colors are the distinction between them: they are not "stacked", rather the colors indicate how many there are. But see the new edit for labeling with the counts. $\endgroup$
    – Alan
    Sep 21, 2014 at 17:21
  • $\begingroup$ Oh I see I just need a legend for the colors. $\endgroup$
    – Sulli
    Sep 21, 2014 at 17:29
0
$\begingroup$

TDIL from integr8or'a comment in this Q/A about the new-in-version-12.2 function PointValuePlot which, among other things, provides a more convenient way to visualize data sets with repeated values:

t = {{1, 2}, {3, 4}, {3, 4}, {3, 4}, {4, 5}, {3, 4}, {1, 2}, {6, 7}};


PointValuePlot[Counts[t], PieChart[Table[1, #]]&]

enter image description here

Alternatively,

PointValuePlot[GroupBy[t,Identity, Map[1&]], All -> PieChart]

enter image description here

A cleaner version PointValuePlot[GroupBy[t, Identity, Map[1.&]] should give the same picture, but I could not get an output on Wolfram Cloud.

Use All -> (BarChart[#, Axes -> False]&) to get:

enter image description here

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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