读取文本文件并计算概率和香农熵

时间:2015-06-26 14:28:24

标签: python math numpy pandas

我有一个文本文件(制表符分隔),我需要计算文本文件中每列的概率和熵。这是我的文本文件:

aaa 0.0520852296    0.1648703511    0.1648703511
bbb 0.1062639955    0.1632039268    0.1632039268
ccc 1.4112745088    4.3654577641    4.3654577641
ddd 0.4992644913    0.1648703511    0.1648703511
eeee    0.169058175 0.1632039268    0.1632039268

所以我可以使用以下代码计算概率:

import pandas as pd
f=open(mydata,'r')
df = pd.DataFrame(pd.read_csv(f, sep='\t', header=None, names=['val1', 'val2', 'val3']))
print(df)
df.loc[:,"val1":"val3"] = df.loc[:,"val1":"val3"].div(df.sum(axis=0), axis=1)
print(df)

输出,

aaa 0.0232736716    0.0328321936    0.0328321936
bbb 0.0474828153    0.0325003428    0.0325003428
ccc 0.6306113983    0.8693349271    0.8693349271
ddd 0.2230904597    0.0328321936    0.0328321936
eeee    0.0755416551    0.0325003428    0.0325003428

在那个输出上我想计算熵并给我结果作为输出文件,所以我有以下代码

import math
entropy = - sum([ p * math.log(p) / math.log(2.0) for p in df ])

但是我收到以下错误消息:

TypeError: a float is required

非常感谢任何帮助。 谢谢大家

3 个答案:

答案 0 :(得分:5)

你的问题在于这一行

entropy = - sum([ p * math.log(p) / math.log(2.0) for p in df ])

如果您考虑(或打印出)p for p in df给您的内容(例如,运行print([p for p in df])),您会发现p仅包含列的标题。因此,您要将文本标签传递到期望math的{​​{1}}函数中。因此错误。

apply可能适合您:

float

注意

正如其他人所指出的那样,您可能希望通过将第0列作为索引来整理数据框 - 然后您不必使用

import math

def shannon(col):
    entropy = - sum([ p * math.log(p) / math.log(2.0) for p in col])
    return entropy

sh_df = df.loc[:,'val1':'val3'].apply(shannon,axis=0)

print(sh_df)

因此您可以使用以下方式导入数据:

df.loc[:,'val1':'val3']

并且避免使用繁琐的df = pd.read_csv(f, sep='\t', header=None, index_col=0, names=['val1', 'val2', 'val3']) 语法

答案 1 :(得分:1)

为什么不修复数据文件而不是尝试在python代码中执行此操作并降低可读性。它就像

一样简单
sed 's/ \+/,/g' mydata > my_fixed_data

如果你使用linux,只需在命令行上运行它。它将用,替换所有空格。

MYDATA

aaa 0.0520852296    0.1648703511    0.1648703511
bbb 0.1062639955    0.1632039268    0.1632039268
ccc 1.4112745088    4.3654577641    4.3654577641
ddd 0.4992644913    0.1648703511    0.1648703511
eeee    0.169058175 0.1632039268    0.1632039268

my_fixed_data

aaa,0.0520852296,0.1648703511,0.1648703511
bbb,0.1062639955,0.1632039268,0.1632039268
ccc,1.4112745088,4.3654577641,4.3654577641
ddd,0.4992644913,0.1648703511,0.1648703511
eeee,0.169058175,0.1632039268,0.1632039268

然后您可以简单地使用read_csv功能,如

df = pd.read_csv('my_fixed_data', header=None, index_col=0, names=['val1', 'val2', 'val3'])

以下是数据框现在的样子:

          val1      val2      val3
aaa   0.052085  0.164870  0.164870
bbb   0.106264  0.163204  0.163204
ccc   1.411275  4.365458  4.365458
ddd   0.499264  0.164870  0.164870
eeee  0.169058  0.163204  0.163204

我确信Windows也必须有等价物。只是谷歌吧。

您收到TypeError: a float is required错误,因为for p in df为您提供了列名而不是某些浮点值。您可能需要相应地修复它。

>>> for p in df:
...     print p
...
val1
val2
val3
>>>

答案 2 :(得分:0)

尝试

entropy = - sum([ p * math.log(p) / math.log(2.0) for p in df.loc[:,"val1":"val3"] ])

PS:使用此功能将文件读入数据框:

df = pd.read_csv(f, sep='\t', header=None, names=['val1', 'val2', 'val3'])