Objective-C: Smooth NSArray of NSNumber objects
I have an NSArray which contains a large number of NSNumber objects (thousands). I use these numbers to build a nice line graph. The problem is, the graph uses every value, which makes the graph very sharp. It gets even worse the more values I have:
I want to be able to make this into a smoother graph, possibly throwing out those numbers that make it jagged looking. I want it to look like this:
Maybe it is late, but I am not thinking of a way to do this. Possibly looping through my values and throwing some of them out? The graph doesn't need to be 100% accurate, it just needs to be a decent representation of the values.
EDIT:
Here is the method that I came up with using jrturton's answer:
- (NSArray *)smoothedArray:(NSArray *)items {
int average = 0;
int开发者_Python百科 i = 0;
int numberToAverageBy = 10;
NSMutableArray *newItems = [[[NSMutableArray alloc] init] autorelease];
// Loop
for (NSNumber *elevation in items) {
average += [elevation intValue];
i++;
if (i == numberToAverageBy) {
[newItems addObject:[NSNumber numberWithInt:average/numberToAverageBy]];
i = 0;
average = 0;
}//end
}//end for
return [NSArray arrayWithArray:newItems];
}//end
It worked perfectly!
You could take the average value of every 10 (or whatever you choose) elements in the array and use that to determine the points to plot. This would make the drawing quicker as well.
Look at moving averages.
The shorter the moving average, the closer it hugs the curve but it smooths it out.
For example, check out the 10 day exponential moving average here:
http://stockcharts.com/school/doku.php?id=chart_school:technical_indicators:moving_averages
I've never had to do anything like this before, so I'm sure that others can come up with more elegant solutions, but here's what I would try off the top of my head:
Prior to displaying the graph, instead of throwing out some of the elements, why don't you set each element to the average of some of the elements around it? For example, if your array contains (2, 1, 3, 5, 4, 3, 8), that would turn into (2, 2, 3, 4, 4, 5, 8). To get those values, I took the average of each element and its immediate neighbors to get the new element (except for the endcaps, which I left as is). Playing around with the number of elements you're averaging together at each step would make your graph look as smooth as you want it.
http://en.wikipedia.org/wiki/Gaussian_filter
精彩评论