关于统计图形的一个很难但非常容易拿分的问题!(200分)

  • 主题发起人 主题发起人 一个过客
  • 开始时间 开始时间

一个过客

Unregistered / Unconfirmed
GUEST, unregistred user!
我有一系列数字,准备做成统计图形折线图,但是我的这些数字
其中有那么一两个数字很离谱,不是太大就是太小,比如下面一组数字:
1
2
3
4
1000000
5
6
8
-200000
9
...
结果出来的图形很难看,比例严重失调,相信大家能够想象得出来,
其中1,2,3...等等小数字的差别根本看不出来!
请问如果遇到这种情况,你们一般怎么办?
 
1000000=20
-2000000=-40
改显示的字内容。
(瞎说的,不过以前确实用过,具体怎么把客户蒙过去的忘了)[:)]
 
1。能不能想办法控制CHART控件的显示范围
2。没有了
 
to 一个过客:
你做图表的时候,不能只考虑高度的比例,还应该加入宽度的比例,
这样出来的图就好的多。
 
oldppp: 你说得我没看懂。
卷起千堆雪tyn:能说清楚一点吗?宽度比例好像没什么用啊?我这里主要是高度严重失调。
To All: 我想了老半天,觉得既要显示出异常数字的“异常”,又不要太失调,是不是可以
这样?对每个数字进行加权,小数字比较多,权数大,显示的就比实际大小大一些,
异常数字出现次树少,权数就小,显示的就比实际尺寸小一点。这样一边大一点,
一边小一点,显示比例就会好看一些,同时也能够突出异常数字。
但是我不知道具体应该怎样做,大家觉得怎么样?[:8D]
 
to 一个过客:
你应该用一个个的面积不等的方形来表示;
大数值,宽度大,高度大;小数值,宽度小,高度小!
▏▎▌▋▊
上面只是宽度的变化,你相应的让高度也变化就可以了。
 
卷起千堆雪:你的方法同样存在上述问题,试想一个宽500pixel的统计图形,上面
一个100000就将占据大部分幅面,其他比如1的图形会小的几乎看不见。[?]
 
如果可能的话,应该使用对数坐标...等等,怎么还有负数?——开三次方?
还有一种方法:如果数字太大,可以将其截断至某一最大长度,然后以颜色表示该数字的大体范围
(如:<20为正常显示,>20为对数显示,并且使用截断功能(如有必要,可以标明实际值))

表一:(绝对值范围: 蓝色:0-20 绿色:20-1000 红色:1000-1000000 ...)
88 -
88 |
--截断 } 对数显示区
88 -
88 -
88 88 |
88 88 88 } 正常显示区
88 88 88 88 88 88 |
88 88 |
88 88 |
88 -
88 -
88 |
|
88 } 对数显示区
88 |
88 _
符合要求否?
 
creation-zy:想法很有新意!不过不太懂“对数坐标”,说明白一点。
 
比如:正常的坐标为等差数列: 1, 2, 3,...
而对数座标为等比数列:0.01, 0.1, 1, 10, 100, 1000, ...
对数坐标图一般用于数据的数量级跨度很大,但对于小数据又不能忽略的情况。
(我在大学时做流体的雷诺数实验时使用的就是对数坐标纸)
(对数轴)
| *
100 | *
|
| *
10 | *
| *
| *
1 |
|
| *
0.1 |________________________________________________
0 10 20 30 40 50 60 70 (普通轴)
对于你所描述的情况,可以采用纯粹的对数坐标系,也可以采用我在上面提到的两种相结合的方式:
| -
10000 | |
| } 对数区
1000 | |
| _|
10 | -
| |
5 | |
| } 正常区
0 |____________________ _|
1 2 3 4
 
我在大学学习传感器时也是用对数座标,但是这里面不能有负数啊,所以
只能用两种形式结合起来了。而且还要自己定义如log(-100)=-2的形式,
尽管数学上来说这是不对的,但是正常情况下log0.01=-2,这个0.01已经
用正常的坐标表示了,所以这么定义是可行的。
 
function MakeLog(f:Single;const NormalValue,LogValue:Single):Single;
//实现两种显示方法的无缝衔接(带符号)!
var //NormalValue为常数显示范围,LogValue为对数的底数,请注意:NormalValue must>1 !!!
Head:Integer;
begin
if f<0 then
Head:=-1
else
Head:=1;
f:=abs(f);
if f<=NormalValue then
Result:=f
else
Result:=NormalValue+(Ln(f)-Ln(NormalValue))/Ln(LogValue);
//注意这个减号,是它实现了无缝衔接
Result:=Result*Head;
end;
procedure TForm1.Button3Click(Sender: TObject);
var
i:Integer;
begin
with Memo1.Linesdo
for i:=-10 to 10do
Add(FloatToStr(MakeLog(i*10,30,10)));
//正常显示范围为 -30..+30 对数部分的底数为10
end;

怎么样?只要设定适当的NormalValue和LogValue就搞定了![:)]
 
我试了一下你的代码,似乎并没有表现出小数字的波动(几乎是水平线),
这样吧,为了你测试方便,我给你提供一组数字:
ary[0]:=1;
ary[1]:=2;
ary[2]:=3;
ary[3]:=4;
ary[4]:=50;
ary[5]:=42;
ary[6]:=1000;
ary[7]:=3000;
ary[8]:=20000;
ary[9]:=25000;
ary[10]:=100000;
ary[11]:=-1000;
ary[12]:=-200010;
ary[13]:=10000;
ary[14]:=120000;
ary[15]:=130;
ary[16]:=500;
ary[17]:=8;
ary[18]:=-10;
ary[19]:=-100000;
ary[20]:=-150000;
ary[21]:=-2300;
ary[22]:=29000;
ary[23]:=150000;
ary[24]:=1;
ary[25]:=2;
ary[26]:=3;
ary[27]:=4;
ary[28]:=7;
ary[29]:=8;
ary[30]:=5;
ary[31]:=7;
我用你的函数设置了各种NormalValue和LogValue,效果都不理想。
而且困难的是,我的这些数字是从数据库里面取出来的,运行的时候
总不能让我手工去尝试合适的NormalValue吧?
 
NormalValue=20;
LogValue:=1.2;
绘图的时候将再纵坐标的值*2,非常清晰呀。
>我手工去尝试合适的NormalValue
可以统计+分析嘛(我知难而退),实在不行,可以在浏览的时候让用户自己去调整嘛。(别打我)
 
20,1.2效果果然不错。
不过“统计+分析”很头疼,有线索吗?说实话我根本不明白20这个数字和我的那些
数字有什么关系。
 
好家伙!耗上了。[:)]
必要数据:
显示图象的大小(指高度)
用户可以接受的清晰程度(可以看出明显高度不同所需要的象素差异,一般为2)
数据中绝对值最大的(用于反算出LogValue的大体值)
我刚才发现:NormalValue其实并不重要,你把上面的NormalValue改为2再试一试看?
因此,只要算出LogValue就可以了。
 
是得耗上啊!不然我搞不懂啊!
那么你这个1.2是试出来的还是算出来的?如果算出来,有什么规律可循?
比如你说的:
显示图象的大小(指高度)
用户可以接受的清晰程度(可以看出明显高度不同所需要的象素差异,一般为2)
数据中绝对值最大的(用于反算出LogValue的大体值)
如果根据上面的条件得到1。2这个数字?你告诉我大致线索就可以。多谢!
 
图像高度400,正负半轴各分得200,再除以象素差异2(最终的显示结果要乘以它),得:100,
当然,将整个图像占满不太美观,算80%吧——100*80%=80
——即MakeLog计算出来的可能最大值(指绝对值)。
将NormalValue估计为10(差几倍没有多大影响的),下面就简单了:
10+(Ln(200010)-Ln(10))/Ln(LogValue)=80
解法你自己搞定吧:P,将LogValue=1.15代入,算出来是80.xxx...效果很好。
 
多谢!我先试一试吧!
这份你拿定了。
 
就这样吧!虽然这个对数坐标方案我们感觉不错,但是客户不接受,说不真实。。。靠!
谢谢creation-zy!
 

Similar threads

S
回复
0
查看
3K
SUNSTONE的Delphi笔记
S
S
回复
0
查看
2K
SUNSTONE的Delphi笔记
S
D
回复
0
查看
2K
DelphiTeacher的专栏
D
D
回复
0
查看
1K
DelphiTeacher的专栏
D
后退
顶部