数据压缩

问题描述:

我有一个任务来压缩股票市场数据......数据是在一个文件中,每天的股票价值在一行中给出,等等......所以这是一个非常大的文件。数据压缩

例如,
123.45
234.75
345.678
889.56
.....

现在的问题是如何对数据进行压缩(又名减少冗余)使用标准算法,如霍夫曼或算术编码或LZ编码...哪种编码是最适合这种数据...

我已经注意到,如果我把第一个数据,然后考虑到每个连续数据之间的差异,差异值有很多重复......这让我想知道是否首先考虑这些差异,找到它们的频率和因此可能性,然后使用霍夫曼编码将是一种方法......

我是对不对?任何人都可以给我一些建议。

+0

你为什么不做比较? – jldupont 2009-11-30 01:41:50

+0

http://mathoverflow.com/ – jldupont 2009-11-30 01:43:28

我认为你的问题比仅仅减去股票价格更复杂。您还需要存储日期(除非您具有可以从文件名中推断出的一致时间跨度)。

虽然数据量并不是很大。即使你在过去的30年中每一天每一天都有300个stockd的每一天都有数据,你仍然可以设法将所有这些数据存储在高端家用计算机(例如MAC Pro)中,因为这相当于5Tb UNCOMPRESSED 。

我写了一个快速而肮脏的脚本,它会每天在雅虎追逐IBM股票,并将其“正常”(仅调整后的关闭)并使用您提及的“差异方法”进行存储,然后使用gzip 。您可以节省成本:16K vs 10K。问题是我没有存储日期,我不知道什么值对应于哪个日期,当然,你将不得不包括这个。

祝你好运。

import urllib as ul 
import binascii as ba 

# root URL 
url = 'http://ichart.finance.yahoo.com/table.csv?%s' 

# dictionary of options appended to URL (encoded) 
opt = ul.urlencode({ 
    's':'IBM',  # Stock symbol or ticker; IBM 
    'a':'00',  # Month January; index starts at zero 
    'b':'2',   # Day 2 
    'c':'1978',  # Year 2009 
    'd':'10',  # Month November; index starts at zero 
    'e':'30',  # Day 30 
    'f':'2009',  # Year 2009 
    'g':'d',   # Get daily prices 
    'ignore':'.csv', # CSV format 
    }) 

# get the data 
data = ul.urlopen(url % opt) 

# get only the "Adjusted Close" (last column of every row; the 7th) 

close = [] 

for entry in data: 
    close.append(entry.strip().split(',')[6]) 

# get rid of the first element (it is only the string 'Adj Close') 
close.pop(0) 

# write to file 
f1 = open('raw.dat','w') 
for element in close: 
    f1.write(element+'\n') 
f1.close() 

# simple function to convert string to scaled number 
def scale(x): 
    return int(float(x)*100) 

# apply the previously defined function to the list 
close = map(scale,close) 

# it is important to store the first element (it is the base scale) 
base = close[0] 

# normalize all data (difference from nom) 
close = [ close[k+1] - close[k] for k in range(len(close)-1)] 

# introduce the base to the data 
close.insert(0,base) 



# define a simple function to convert the list to a single string 
def l2str(list): 
    out = '' 
    for item in list: 
     if item>=0: 
      out += '+'+str(item) 
     else: 
      out += str(item) 
    return out 

# convert the list to a string 
close = l2str(close) 

f2 = open('comp.dat','w') 
f2.write(close) 
f2.close() 

现在比较“原始数据”(raw.dat)与“压缩格式”你提议(comp.dat)

:sandbox jarrieta$ ls -lh 
total 152 
-rw-r--r-- 1 jarrieta staff 23K Nov 30 09:28 comp.dat 
-rw-r--r-- 1 jarrieta staff 47K Nov 30 09:28 raw.dat 
-rw-r--r-- 1 jarrieta staff 1.7K Nov 30 09:13 stock.py 
:sandbox jarrieta$ gzip --best *.dat 
:sandbox jarrieta$ ls -lh 
total 64 
-rw-r--r-- 1 jarrieta staff 10K Nov 30 09:28 comp.dat.gz 
-rw-r--r-- 1 jarrieta staff 16K Nov 30 09:28 raw.dat.gz 
-rw-r--r-- 1 jarrieta staff 1.7K Nov 30 09:13 stock.py 
+0

请注意,我对股票词典的评论说起始日期是“2009”,实际上它是1978年......所以我正在为IBM追逐30年的每日股票数据。 – Escualo 2009-11-30 17:33:36

+0

嗨thanx很多这是真的很有帮助...以及现在的日期实际上并不重要...我的主要重点是只是尽可能压缩股指数据...我必须开发(代码)我自己的压缩代码不能使用预编译的软件......我只会使用一种算法...所以我的问题将是获得霍夫曼编码的“差异”值的概率分布,现在解释然后解码​​(解压缩) 它也是。 – sfactor 2009-11-30 23:03:54

现在许多压缩工具都使用这些技术的组合来给各种数据提供良好的比率。可能值得从一些相当普遍和现代的东西开始,例如bzip2,它使用霍夫曼编码和各种技巧混合数据以产生各种冗余(页面包含进一步向下的各种实现的链接)。

运行长度编码可能适合?看看here。为了让它是如何工作的极端简单的例子,这里的数据的ASCII码线... 30个字节长

 
HHHHHHHHEEEEEEELLLLLLLLOOOOOO 

应用RLE它,你会得到这8个字节:

 
9H7E8L6O 
  • 九H公司
  • 七E公司
  • 八L的
  • 六O公司

的约27%的减少,结果(压缩比为例如线8/30)

你觉得呢?

希望这会有所帮助, 最好的问候, 汤姆。

计算连续数据的差异,然后使用运行长度编码(RLE)

而且您还需要将数据转换为整数,然后计算差异。

这将是最好的将是一个自适应差分压缩(我忘记了正确的名字)。你不仅可以每天分析差异,还可以计算出预测值,并实际做出差异。通常优于正常的线性预测器。

如果你想要看到你可以做的是交叉adapative,其中股市整体有它自己的趋势,甘蔗被用来挑选更好的预测压缩。

我建议你将主文件分解为分段的阻塞格式,然后分别压缩各个段;这应该导致最大程度的优化压缩。 在解压缩端,您将不得不分别解压缩这些单独的段,然后重新构建原始文本文件。