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

use*_*373 6 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
Run Code Online (Sandbox Code Playgroud)

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

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)
Run Code Online (Sandbox Code Playgroud)

哪个输出,

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
Run Code Online (Sandbox Code Playgroud)

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

import math
entropy = - sum([ p * math.log(p) / math.log(2.0) for p in df ])
Run Code Online (Sandbox Code Playgroud)

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

TypeError: a float is required
Run Code Online (Sandbox Code Playgroud)

任何帮助深表感谢.谢谢你们

J R*_*ape 5

你的问题在于这一行

entropy = - sum([ p * math.log(p) / math.log(2.0) for p in df ])
Run Code Online (Sandbox Code Playgroud)

如果你考虑(或打印出)p for p in df给你的东西(例如跑步print([p for p in df])),你可以看到p它只包含列的标题.所以你将文本标签传递给math期望a 的函数float.因此错误.

apply 在这里可能适合你:

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)
Run Code Online (Sandbox Code Playgroud)

注意

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

df.loc[:,'val1':'val3']
Run Code Online (Sandbox Code Playgroud)

所以您可以使用以下方法导入数据:

df = pd.read_csv(f, sep='\t', header=None, index_col=0, names=['val1', 'val2', 'val3'])
Run Code Online (Sandbox Code Playgroud)

并避免使用繁琐的loc[:,'val1':'val3']语法