3
$\begingroup$

I have a list of {x, y} integer pairs representing single events in pixel coordinates in the {x, y} plane, with occasional duplicates. I'd like to convert that list into an image. There are only a few thousand {x,y} pairs, but the x y space is large, 1k x 1k, so Histogram3D[XYlist, {xpixels, ypixels}] is very slow. Is there a simple command to convert this list into a 2d array (or an image)? For example, with only 4 points:

coords = {{1, 4}, {2, 5}, {1000, 300}, {250, 300}}
Histogram3D[coords, {1000, 1000}]

This returns a graphical histogram after some time. I'd like a 2d array or image. Maybe use HistogramList somehow?

I'm hoping there's a better way than defining a 2d constant array and looping through the list of points to populate it, incrementing the pixel value for each hit.

$\endgroup$
3
  • $\begingroup$ You want a 2D array representing the number of events at a certain pixel {x, y}? $\endgroup$
    – march
    Commented Nov 14, 2015 at 0:18
  • $\begingroup$ @march thank you, yes a 2D array, in this case 1000 x 1000, the value of each element representing the number of events at that pixel. (so in this case most values would be 0). $\endgroup$
    – DrBubbles
    Commented Nov 14, 2015 at 0:26
  • $\begingroup$ I've got an answer for you, I think, that will be very fast. Hold on a sec. $\endgroup$
    – march
    Commented Nov 14, 2015 at 0:26

2 Answers 2

2
$\begingroup$

Try this. We'll use as a sample list

list = RandomInteger[{1, 100}, {1000, 2}];

This is a list of 1000 pixels positions, where x and y go from 1 to 100. We first Tally, which counts the repeats, turn each tally into a Rule that we feed to SparseArray to generate the array, then use ArrayPlot. You will need to tell SparseArray the number of pixels in each direction. In this case, the image is 100 by 100 pixels. In your case, replace 100 by 1000 pixels.

ArrayPlot[SparseArray[Rule @@@ Tally@list, {100,100}]]

enter image description here

Could also use MatrixPlot:

MatrixPlot[SparseArray[Rule @@@ Tally@list, {100,100}]]

enter image description here

$\endgroup$
1
  • $\begingroup$ This works very efficiently! Excellent solution @march It also preserves the absolute coordinates (I was worried it might shift everything so the first event moved to 0,0 ) Great! $\endgroup$
    – DrBubbles
    Commented Nov 14, 2015 at 0:39
2
$\begingroup$

You can use SparseArray directly with the option "TreatRepeatedEntries" -> 1 (ref):

list = RandomInteger[{1, 1000}, {10000, 2}];

SetSystemOptions["SparseArrayOptions" -> {"TreatRepeatedEntries" -> 1}];

s = SparseArray[
    list -> ConstantArray[1, Length@list], {1000, 1000}]; // AbsoluteTiming
(* {0.001821, Null} *)

s // ArrayPlot

enter image description here

It is the most efficient approach to obtain histogram (and weighted histogram as well) on sparse data.

$\endgroup$
1
  • $\begingroup$ Yes this is even faster and gets the intended result. (Without TreatRepeatedEntries->1 it gives a binary image; I would certainly never have stumbled across this solution!) The Stackexchange community is wonderful! $\endgroup$
    – DrBubbles
    Commented Nov 16, 2015 at 18:36

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.