这是之前问题的一个分支,开始滚雪球。如果我有一个矩阵A并且我想使用每行[1:]值的平均值/平均值来创建另一个矩阵B,但保持行标题不变,则此列表理解可以正常工作。
from operator import mul,len
# matrix A with row headings and values
A = [('Apple',0.95,0.99,0.89,0.87,0.93),
('Bear',0.33,0.25.0.85,0.44,0.33),
('Crab',0.55,0.55,0.10,0.43,0.22)]
#List Comprehension
def average(lst):
return sum(lst) / len(lst)
B = [(a[0], average(a[1:])) for a in A]
预期结果
B = [('Apple', 0.926), ('Bear', 0.44), ('Crab', 0.37)]
但是,如果数据集中有空洞(用'x'表示),分析就不会运行,即
# matrix A with row headings and values
A = [('Apple',0.95,x,0.89,0.87,0.93),
('Bear',0.33,0.25.0.85,0.44,0.33),
('Crab',x,0.55,0.10,x,0.22)]
在矩阵中,每个行和列的相对位置意味着什么,我不能只删除“空白”条目,那么我怎样才能填写或跳过它们并使其再次工作?回想起来,我的数据比旧床单有更多的洞。
另外,我如何将下面建议的过滤器引入以下定义(当它们击中不是数字的东西时会阻塞),这样点击'X'值会返回另一个'X'值?
def plus(matrix, i):
return [row[i] for row in matrix]
def minus(matrix, i):
return [1.00-row[i] for row in matrix]
答案 0 :(得分:0)
这不起作用,因为x
不一定是数字(你不告诉我们它是什么)。
所以你可能需要编写自己的求和函数来检查项目是x
还是其他东西(也许你必须使用isinstance(element, int) or isinstance(element, float)
)。
答案 1 :(得分:0)
在average()
中,在计算平均值之前,使用循环从x
列表中删除所有lst.remove(x)
值(您必须捕获错误remove()
当它找不到它想要的东西时生成。
我建议使用像""
之类的东西来代表洞,除非你已经有了一些东西。
答案 2 :(得分:0)
试试这个:
B = [(a[0], average(filter(lambda elt: elt != x, a[1:]))) for a in A]
使用ifilter
中的itertools
可以提高效果,尤其是对于大型矩阵。这可以在不更改average
函数或修改A
的情况下为您提供预期结果。
修改强>
如果矩阵稀疏,您可能需要考虑以不同方式实现矩阵。如果要保留当前的实现,则应使用值None
来表示缺失值。这是与null
相当的Python,您可能熟悉其他语言。
如何实现矩阵会大大改变您实现所需函数的方式,并且我将尝试覆盖您的方式以及可能对稀疏矩阵更有效的替代方法。
对于这两个我将使用带孔的示例矩阵:
# matrix A with row headings and values
A = [('Apple',0.95, x, 0.89, 0.87, 0.93),
('Bear', 0.33, 0.25, 0.85, 0.44, 0.33),
('Crab', x, 0.55, 0.10, x, 0.22)]
就像我之前说的那样,使用None
作为空值:
A = [('Apple', 0.95, None, 0.89, 0.87, 0.93),
('Bear', 0.33, 0.25, 0.85, 0.44, 0.33),
('Crab', None, 0.55, 0.10, None, 0.22)]
B
与我之前发布的内容类似:
B = [(a[0], average(filter(lambda x: x is not None, a[1:]))) for a in A]
将column
定义为仅返回填充值的生成器(iterable):
def column(M, i):
i += 1 # this will allow you to use zero-based indices if you want
return (row[i] for row in M if row[i] is not None)
然后,您可以更轻松有效地实施minus
:
from operator import sub
from itertools import imap, repeat
def minus(M, i):
return list(imap(sub, repeat(1.0), column(M, i)))
表示矩阵的另一种方法是使用Python dict
。这里有一些优点,特别是如果矩阵中有很多孔,你不会浪费存储空间。这种方法的一个缺点是,根据你的构造方式创建矩阵可能会更加痛苦。
你的例子可能会变成(为了清晰起见空白):
A = [('Apple', dict([(0, 0.95), (2, 0.89), (3, 0.87), (4, 0.93)])),
('Bear', dict([(0, 0.33), (1, 0.25), (2, 0.85), (3, 0.44), (4, 0.33)])),
('Crab', dict([ (1, 0.55), (2, 0.10), (4, 0.22)]))]
这是构建它的一种丑陋的方式,但是如果你用循环从其他数据构造矩阵它可以更好。
现在,
B = [(a[0], sum(a[1].itervalues())/len(a[1])) for a in A2]
这比应该的更糟糕但是我不擅长Python而且我不能让它完全按照我的意愿去做...
你可以定义一个column
函数,它返回一个比列表理解更有效的生成器:
def column(M, i):
return (row[1][i] for row in M if i in row[1])
minus
完全按照其他示例完成。
我觉得有些东西我没有得到你想要的东西,所以请随时告诉我需要解决的问题。此外,我缺乏Python codez可能没有做字典版本正义,但它对稀疏矩阵可能是有效的。如果您创建了一个矩阵类,那么整个示例会更容易,然后您可以切换实现并查看哪个更适合您。祝你好运。