【问题标题】:Is there a python-syntax similar to matlab for selecting rows and columns? [duplicate]是否有类似于 matlab 的 python 语法来选择行和列? [复制]
【发布时间】:2020-01-02 14:22:11
【问题描述】:

如果我有几个列表(浮动)的列表,例如

list = [
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ]

如何在不使用循环的情况下获得第三列?如果它是 matlab 中的矩阵,我会做list(:,3)

【问题讨论】:

  • 用 lst 替换列表(即不要使用内置函数作为变量名)。然后第三列是:list(zip(*lst))[2]
  • @DarrylG 应该是 list(list(zip(*lst))[2])
  • 无论你得到什么答案,请记住它使用循环somewhere。它们是显式的还是用 Python 或 C 编写的,这是另一个问题,我敢肯定 matlab 的 list(:,3) 也在某处使用循环
  • @daveshkumarsingh--是的,在看到您的消息之前通过查看第一个答案就发现了它。
  • @DeveshKumarSingh--list(list(zip(*lst))[2]) 和 list(zip(*lst))[2] 产生相同的结果。我们需要 list(zip(...)) 但为什么需要 list(list(...)))?

标签: python python-3.x list matlab syntax


【解决方案1】:

您当然可以使用 Numpy 来帮助您实现这一目标。

import numpy as np
list = np.array([
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ])
list[:,2]

我不认为你可以在不使用任何循环的情况下使用本机 python 列表来实现这一点。

【讨论】:

  • 没有 explicit 循环是可能的,如 cmets 中发布的问题
  • 对,显式或非显式,它仍然需要一个循环。我认为 OP 会想要完全避免这种情况。
【解决方案2】:

使用 zip 将列转置为行,然后选择第 3 个子列表(行)

lst = [
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ]

第三栏:

list(zip(*lst))[2] 

【讨论】:

  • list(zip(...)) 可能是两个循环,肯定是一个。
  • @Adirio--没有循环通常意味着没有 for 循环。所有这些解决方案都使用在内部使用循环的内置函数。
  • 是的,我同意,只是指出,正如@DeepSpace 在这个问题的几个地方评论的那样,没有明确的循环并不意味着没有循环。
【解决方案3】:

使用库numpy:

import numpy as np


list = [
       [111, 111, 4523.123, 111, 111],
       [111, 111, 4526.15354, 111, 111],
       [111, 111, 4580.112, 111, 111],
       ]

np_list = np.array(list)
third_col = np_list[:,2] # counting starts from 0

【讨论】:

    【解决方案4】:

    Numpy 是一个非常好的解决方案:

    import numpy as np
    
    
    list = [
           [111, 111, 4523.123, 111, 111],
           [111, 111, 4526.15354, 111, 111],
           [111, 111, 4580.112, 111, 111],
           ]
    
    np_list = np.array(list)[:,2]
    
    

    对于更复杂的数据操作,我建议使用pandas.DataFrame (https://pandas.pydata.org/pandas-docs/stable/reference/api/pandas.DataFrame.html)

    如果你必须使用列表,你可以尝试列表推导。这在技术上是一个循环,但使用的语法要短得多,并且是一种使用集合的非常 Pythonic 的方式。它还使您无需使用外部库:

    >>> list = [
    ...        [111, 111, 4523.123, 111, 111],
    ...        [111, 111, 4526.15354, 111, 111],
    ...        [111, 111, 4580.112, 111, 111],
    ...        ]
    >>> l = [ x[2] for x in list ]
    >>> l
    [4523.123, 4526.15354, 4580.112]
    

    【讨论】:

    • pandas 可能是矫枉过正。 numpy 就够了
    • 列表推导是一个循环
    • 尽管从技术上讲是一个循环,但它仍然是一行语句,可能适合作者的需要。不过,我同意 numpy 是最好的选择。
    【解决方案5】:

    没有,但你可以创建一个类来处理它。基本上你需要重写类的__getitem__ 方法,检查传递的值是否是一个元组,在这种情况下相应地返回:

    class MatlabList(list):
        def __init__(self, *args):
            if len(args) > 1:
                return super().__init__(args)
            return super().__init__(*args)
    
        def __getitem__(self, item):
            if isinstance(item, tuple):
                # Remove the non-needed tuple in case it onle has one element
                if len(item) == 1:
                    return self[item[0]]
                if isinstance(item[0], slice):
                    return MatlabList(map(lambda x: x[item[1:]], self[item[0]]))
                return self[item[0]][item[1:]]
            return super().__getitem__(item)
    
    lst = MatlabList(
        MatlabList(111, 111, 4523.123, 111, 111),
        MatlabList(111, 111, 4526.15354, 111, 111),
        MatlabList(111, 111, 4580.112, 111, 111),
    )
    
    lst[1,2]  # cell at 2nd row, 3rd column
    lst[1,:]  # 2nd row
    lst[:,2]  # 3rd column
    

    【讨论】:

    • MatlabList(lst)[2] 返回第三行,而不是第三列
    • @DeepSpace 这也是 Matlab 的行为,如果你想要列,应该是 [:, 2]
    • 我意识到[:, 2] 也不起作用,因为第一个索引将返回一个列表,并且需要将第二个下标应用于每个索引。将尝试修复。
    • 您能否展示使用您的解决方案检索第三列的用法语法?谢谢。
    • @DarrylG 完成,当为行而不是列提供切片时,我必须解决一个问题,所以感谢您的评论。
    猜你喜欢
    • 2017-08-23
    • 1970-01-01
    • 1970-01-01
    • 2018-01-26
    • 1970-01-01
    • 2013-01-03
    • 1970-01-01
    • 2019-04-23
    • 1970-01-01
    相关资源
    最近更新 更多