Python中二维数组的对数

时间:2019-02-15 10:51:43

标签: python

我有一个名为矩阵的二维数组。其中的每个矩阵的尺寸为1000 x 1000,并由正值组成。现在,我想记录所有矩阵中所有值的日志(0除外)。
如何在python中轻松地做到这一点?
我有以下代码可以满足我的要求,但是知道Python可以变得更简短:

newMatrices = []
for matrix in matrices:
    newMaxtrix = []
    for row in matrix:
        newRow = []
        for value in row:
            if value > 0:
                newRow.append(np.log(value))
            else:
                newRow.append(value)
        newMaxtrix.append(newRow)
    newMatrices.append(newMaxtrix)

5 个答案:

答案 0 :(得分:5)

您可以将其转换为numpy数组,并使用numpy.log来计算值。

对于0值,结果将为-Inf。之后,您可以将其转换回列表,并将-Inf替换为0

或者您可以在numpy中使用where

示例:

res = where(arr!= 0, log2(arr), 0)

它将忽略所有零元素。

答案 1 :(得分:3)

虽然@Amadan的答案肯定是正确的(且简短得多/很优雅),但在您的情况下它可能不是最有效的(当然,这取决于输入),因为np.where()会生成每个匹配值的整数索引。一种更有效的方法是生成布尔掩码。这有两个优点:(1)它通常具有更高的内存效率(2)[]运算符在掩码上通常比在整数列表上更快。

为了说明这一点,我在玩具输入(但尺寸正确)上重新实现了基于np.where()和基于掩码的解决方案。 我还包括了一个基于np.log.at()的解决方案,该解决方案的效率也很低。

import numpy as np


def log_matrices_where(matrices):
    return [np.where(matrix > 0, np.log(matrix), 0) for matrix in matrices]


def log_matrices_mask(matrices):
    arr = np.array(matrices, dtype=float)
    mask = arr > 0
    arr[mask] = np.log(arr[mask])
    arr[~mask] = 0  # if the values are always positive this is not needed
    return [x for x in arr]


def log_matrices_at(matrices):
    arr = np.array(matrices, dtype=float)
    np.log.at(arr, arr > 0)
    arr[~(arr > 0)] = 0  # if the values are always positive this is not needed
    return [x for x in arr]


N = 1000
matrices = [
    np.arange((N * N)).reshape((N, N)) - N
    for _ in range(2)]

(进行一些健全性检查以确保我们正在做同一件事)

# check that the result is the same
print(all(np.all(np.isclose(x, y)) for x, y in zip(log_matrices_where(matrices), log_matrices_mask(matrices))))
# True
print(all(np.all(np.isclose(x, y)) for x, y in zip(log_matrices_where(matrices), log_matrices_at(matrices))))
# True

以及我机器上的计时:

%timeit log_matrices_where(matrices)
# 33.8 ms ± 1.13 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

%timeit log_matrices_mask(matrices)
# 11.9 ms ± 97 µs per loop (mean ± std. dev. of 7 runs, 100 loops each)

%timeit log_matrices_at(matrices)
# 153 ms ± 831 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)

编辑:还包括np.log.at()解决方案和关于将未定义log的值归零的注释

答案 2 :(得分:2)

使用numpy的另一种选择:

arr = np.ndarray((1000,1000))
np.log.at(arr, np.nonzero(arr))

答案 3 :(得分:1)

简单到...

import numpy as np
newMatrices = [np.where(matrix != 0, np.log(matrix), 0) for matrix in matrices]

无需担心行和列,numpy会照顾它。当理解足够容易理解时,无需在for循环中显式遍历矩阵。

编辑:我只是注意到OP具有log,而不是log2。对于解决方案的形状不是很重要(尽管对于得到一个错误的答案很重要:P)

答案 4 :(得分:0)

由@ R.yan推荐 您可以尝试这样的事情。

import numpy as np

newMatrices = []
for matrix in matrices:
    newMaxtrix = []
    for row in matrix:
        newRow = []
        for value in row:
            if value > 0:
                newRow.append(np.log(value))
            else:
                newRow.append(value)
        newMaxtrix.append(newRow)
    newMatrices.append(newMaxtrix)

newArray = np.asarray(newMatrices)
logVal = np.log(newArray)