【问题标题】:Iterate over multiple arrays to perform tasks?迭代多个数组来执行任务?
【发布时间】:2015-09-18 08:58:34
【问题描述】:

我有 9 个数组,每个数组包含 19 个值。

假设它们是a1,a2,a3,a4,a5,a6,a7,a8,a9(每个 a1、a2...a9 包含 19 个值),我们称它们为 a 数组。

我还有 9 个数组,每个数组包含 19 个值。

假设它们是b1,b2,b3,b4,b5,b6,b7,b8,b9(每个 b1、b2...b9 包含 19 个值),我们称它们为 b 数组。

我现在想获取每个 a数组第一个值和每个第一个值的 b 数组,将它们划分为(a/b),这将给我一个新数组,假设a/b 有19 个值。然后我使用numpy.std 计算这 19 个值的标准差。

然后我想再次遍历这些数组,但是这次是每个数组的第二个值,依此类推,直到最后一个(第 19 个)值并执行上述操作。

如果我只有 2 个数组(比如 a1b1),我可以使用 zip,例如:

div_array = [] # The empty array that will have the divided values
for a,b in zip(a1,b1):
    div = a/b
    div_array.append(div)

std = np.std(div_array)

如何在我的冗长案例中重复上述内容?

编辑:

我最终需要 19 个不同的标准差, 即我为第一个值计算它,然后是第二个值,依此类推..

【问题讨论】:

  • 你不喜欢for i in range(0, length(a)): do a[i] 语法。你呢?
  • @deathangel908:所以这里的a指的是一个包含我所有a1,a2...a9的数组?
  • 是的,我只会使用当前元素索引。 a[i], b[i], c[i] 等。但也许有更好的方法。
  • 但是我需要创建 9 个空数组,其中包含我的划分值,然后像示例中所示那样计算每个值的 stddev?
  • 您指定您已经有数组。为什么需要创建新的?

标签: python arrays numpy iteration


【解决方案1】:

如果你用std除法,为什么不使用numpy的力量呢?

>>> # You can create these array in a loop if you want
>>> a = np.array([a1, a2, a3, ..., a9])
>>> b = np.array([b1, b2, b3, ..., b9]) 
>>> c = np.std(a / b, 0)

示例(包含有关np.std 的详细信息):

>>> a1 = np.array([1, 2, 3])
>>> a2 = np.array([2, 3, 4])
>>> a  = np.array([a1, a2])
>>> a
array([[1, 2, 3],
       [2, 3, 4]])
>>> b1 = np.array([10, 100, 1000])
>>> b2 = np.array([20, 200, 2000])
>>> b  = np.array([b1, b2])
>>> b
array([[10, 100, 1000], 
       [20, 200, 2000]])
>>> a/b
array([[0.1,  0.02, 0.003],
       [0.1, 0.015, 0.002]])
>>> np.std(a/b)             # The standard deviation of the whole matrix
0.04289... 
>>> np.std(a/b, 0)          # The standard deviation of each column
array([0, 0.0025, 0.0005])
>>> np.std(a/b, 1)          # The standard deviation of each row
array([0.04229263, 0.04345879])

【讨论】:

  • 我最终需要 19 个不同的标准偏差,即我为第一个值计算它,然后是第二个值等等。上面似乎给了我 1 个标准偏差。你能解释一下0c = np.std(a / b, 0) 中的含义吗?
  • 这是计算标准差的轴。轴是为一维以上的数组定义的。一个二维数组有两个对应的轴:第一个垂直向下穿过行(轴 0),第二个垂直向下穿过列(轴 1)。
  • @ThePredator 上面给你19不同的标准差,查看c的形状。
  • @Holt,我相信你是对的!所以这 19 个标准差是 a/b 的标准差,对吗?但我想知道np.std(a/b,0) 如何迭代获取第一个值,然后是第二个值等等?
  • @ThePredator ab9x19 矩阵,其值为 a_ijb_ija/b 为您提供一个矩阵 t,其中每个 ij t_ij = a_ij / b_ij。这是划分两个矩阵中每个元素的 numpy 方式。一旦你有了 t 矩阵 (9x19),std 函数就会为你提供每列的标准差(正如 Matt 解释的那样)。
【解决方案2】:

所以不久前,我写了一个基本上可以满足您要求的课程。唯一的技巧是你必须向类传递每个数组的迭代器列表。

column_iter_traversal.py

"""
This code will take in a iterator of iterators. You can view the first
iterator as the rows of a graph (a matrix being a specific case of graphs)
and each iterable giving you the columns (or nodes) of that graph.

so if you have a graph
[[1, 2],
[3],
[4, 5]]

we'd expect the iterator to return [1, 3, 4, 2, 5]
"""

class ColumnTraversalIter():
    """
    This is a class which is used to contain the currently travered state.
    This is the class which defines the returned object for
    column_traversal_iter. The iter that function returns is an instance of
    this class.
    """
    def __init__(self, iter_of_iters):
        # Build a list of iterators
        self.iter_list = []
        for it in iter_of_iters:
            self.iter_list.append(it)
        self.current_iter_index = 0

    def __iter__(self):
        return self

    def __next__(self):
        # Get the next value from the current iterator
        try:
            return_val = next(self.iter_list[self.current_iter_index])
            self.current_iter_index = self._increment_index(
                self.current_iter_index,
                len(self.iter_list))
            return return_val
        except StopIteration:
            # When we run into a stop iteration we know that the current
            # iterator is out of values. Remove the current iterator from
            # the iterator list.
            del self.iter_list[self.current_iter_index]
            # If we are out of iterators it's time to raise StopIteration
            if len(self.iter_list) == 0:
                raise StopIteration
            else:
                # Otherwise, set the current_iter_index and recall next
                self.current_iter_index = self._increment_index(
                    self.current_iter_index,
                    len(self.iter_list))
                return self.__next__()
        except IndexError:
            # Someone called __next__ when there aren't any iterators left in
            # the iter_list.
            raise StopIteration

    @staticmethod
    def _increment_index(iter_index, wrap_length):
        if iter_index + 1 > wrap_length:
            print("returning 0")
            return 0
        else:
            print("returning {}".format(iter_index + 1))
            return iter_index + 1

def column_traversal_iter(iter_of_iters):
    """

    args:
        iterator: a iterator of iterators. If there aren't any iterators or
                  there are non iterator elements this will explode.
    returns a COlumnTraversalIter
    """
    return ColumnTraversalIter(iter_of_iters)

tests.py

import unittest
from column_traversal import column_traversal_iter

class TestBruteforceImplemetation(unittest.TestCase):

    def test_no_iters(self):
        test_iter = iter([])
        column_iter = column_traversal_iter(test_iter)
        with self.assertRaises(StopIteration):
            next(column_iter)

    def test_iter_of_one_empty_iter(self):
        """
        One empty iter and many empty iters should hit one stop iteration.
        """
        test_iter = iter([iter([])])
        column_iter = column_traversal_iter(test_iter)
        with self.assertRaises(StopIteration):
            next(column_iter)

    def test_iter_of_many_empty_iter(self):
        """
        One empty iter and many empty iters should hit one stop iteration.
        """
        test_iter = iter([iter([]), iter([]), iter([])])
        column_iter = column_traversal_iter(test_iter)
        with self.assertRaises(StopIteration):
            next(column_iter)

    def test_iter_simple_one_by_one_matrix(self):
        """
        One empty iter and many empty iters should hit one stop iteration.
        """
        test_iter = iter([iter([1]), iter([2]), iter([3])])
        column_iter = column_traversal_iter(test_iter)
        expected_traversal = [1, 2, 3]
        for actual_value, expected_value in zip(column_iter, expected_traversal):
            self.assertEqual(actual_value, expected_value)

        # Check to make sure there's a stop iteration.
        with self.assertRaises(StopIteration):
            next(column_iter)

    def test_iter_simple_jagged_graph(self):
        """
        One empty iter and many empty iters should hit one stop iteration.
        """
        test_iter = iter([iter([1]), iter([2, 4]), iter([3])])
        column_iter = column_traversal_iter(test_iter)
        expected_traversal = [1, 2, 3, 4]
        for actual_value, expected_value in zip(column_iter, expected_traversal):
            self.assertEqual(actual_value, expected_value)

        # Check to make sure there's a stop iteration.
        with self.assertRaises(StopIteration):
            next(column_iter)

    def test_iter_simple_two_by_two_matrix(self):
        """
        One empty iter and many empty iters should hit one stop iteration.
        """
        test_iter = iter([iter([1, 4]), iter([2, 5]), iter([3, 6])])
        column_iter = column_traversal_iter(test_iter)
        expected_traversal = [1, 2, 3, 4, 5, 6]
        for actual_value, expected_value in zip(column_iter, expected_traversal):
            self.assertEqual(actual_value, expected_value)

        # Check to make sure there's a stop iteration.
        with self.assertRaises(StopIteration):
            next(column_iter)

    def test_iter_one_iter_is_blank(self):
        """
        One empty iter and many empty iters should hit one stop iteration.
        """
        test_iter = iter([iter([1, 3]), iter([2, 4]), iter([])])
        column_iter = column_traversal_iter(test_iter)
        expected_traversal = [1, 2, 3, 4]
        for actual_value, expected_value in zip(column_iter, expected_traversal):
            self.assertEqual(actual_value, expected_value)

        # Check to make sure there's a stop iteration.
        with self.assertRaises(StopIteration):
            next(column_iter)

你会使用这个代码

divisor_iter_list = []
for a_list in a_lists:
    divisor_iter_list.append(iter(a_list))

dividend_iter_list = []
for b_list in b_lists:
    divident_iter_list.append(iter(b_list))


divisor_iter = ColumnTraversalIter(divisor_iter_list)
dividend_iter = ColumnTraversalIter(divident_iter_list)
for divisor, dividend in zip(divisor_iter, dividend_iter):
    # Do calculations.

【讨论】:

    【解决方案3】:

    您可以将每个 ab 数组放在另一个数组中。所以会是

    a[0] = a1a[1] = a2b 也是如此

    然后是这样的:

    for i in range(length(a)):
        div_array = []
        for j in range(length(a[i])):
            div = a[i][j]/b[i][j]
            div_array.append(div)
    
        std.append(np.std(div_array))
    

    然后你有一个数组std,其中包含你想要的所有值。

    当然,如果ab 的长度相同,并且a[0]b[0] 等的长度也相同,这将起作用。你的情况是这样。

    【讨论】:

    • 我想分别获得 19 个值的标准偏差。上面的可以吗?我可以看到我们将所有`div_array`添加到一个列表中std
    • 是的,这是一个错误,你必须清空div_array 我刚刚修复了它。我没测试过,你可以试试,应该很快就能查到了吧?
    • 好吧,它仍然不能满足我的需求!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-13
    • 2020-06-30
    • 2016-05-15
    • 1970-01-01
    相关资源
    最近更新 更多