让我从一个最小的工作示例开始。
import pandas as pd
import numpy as np
import math
test = pd.DataFrame(data=np.array([[45, .25, .25, .25, .25],
[37, .75, .25, 0.0, 0.0],
[29, 1, 0.0, 0.0, 0.0],
[70, .25, 0.0, 0.0, .57]]),
index=[1, 2, 3, 4],
columns=['Unneeded', 'A', 'B', 'C', 'D'])
因此,我们在pandas中有以下数据框:
>>> test
Unneeded A B C D
1 45.0 0.25 0.25 0.25 0.25
2 37.0 0.75 0.25 0.00 0.00
3 29.0 1.00 0.00 0.00 0.00
4 70.0 0.25 0.00 0.00 0.57
变量A
到D
代表某些东西的份额,这就是为什么逐行添加一个。我想计算一个新变量,它保存每行的熵索引。熵指数是以下函数的x = A,B,C,D之和:
lambda x: x * math.log(1.0/x, 2) if x > 0 else 0
我知道我可以通过以下语法在pandas数据框中进行简单的列生成:
test['sum_ab'] = test['A'] + test['B']
我也知道我可以使用lambda函数生成具有更复杂转换的列:
test['dub_a'] = test.A.apply(lambda x: x * 2) # or test['A'].apply(...
我也知道你可以使用带有map()的lambda函数将函数应用于列表中的每个项目。所以我的想法是通过将必要的lambda函数应用于这四列中的每个项来生成一个新变量,然后对结果列表中的项求和。因此我尝试了以下语法:
test['entropy'] = sum(list(map(lambda x: x * math.log(1.0/x, 2) \
if x > 0 else 0, LIST)))
......但是我的麻烦开始了。我刚刚在那里写了LIST
,因为在我的生活中,我无法弄清楚如何从这些中找出一个列表列名,以便此函数可以工作。我知道基本思想本身有效:
>>> list_1 = [.25, .25, .25, .25]
>>> entropy_1 = sum(list(map(lambda x: x * math.log(1.0/x, 2) \
if x > 0 else 0, list_1)))
>>> entropy_1
2.0
我无法弄清楚如何告诉它对pandas数据框中列的元素执行此操作。
到目前为止,我在大熊猫上阅读的所有内容,当涉及到选择列时,似乎都假设您正在对数据框进行子集化。但这不是我想要做的。这种类型的列创建隐式地同时对列中的每一行起作用;因此,当您编写test['sum_ab'] = test['A'] + test['B']
之类的内容时,您不会指定任何(或所有)行。看起来我应该可以在这里执行类似的操作:我应该能够将test[['A':'D']]
或类似内容指定为LIST
。但到目前为止我还是来了鸡蛋。
通常当我接近一个解决方案然后找不到任何相关问题时,这表明我基本上是错误的轨道。这可能是这种情况,但如果有人对如何进行有任何想法,我将不胜感激。
P.S。:我包含了Unneeded
列,以强调我需要指定数据框中的一些列,而不是所有列。
答案 0 :(得分:3)
作为apply
的替代方案,您可以使用矢量化操作。
relevant = test[['A','B','C','D']]
entropy = (relevant * (np.log2(1) - np.log2(relevant))).fillna(0).sum(1)
首先,计算一个框架,其中每个条目的格式为x * np.log2(1/x)
或0
。然后,对各行求和以获得答案。