【问题标题】:Select certain rows (condition met), but only some columns in Python/Numpy选择某些行(满足条件),但只选择 Python/Numpy 中的某些列
【发布时间】:2014-07-17 16:36:10
【问题描述】:

我有一个 4 列的 numpy 数组,想要选择第 1、3 和 4 列,其中第二列的值满足特定条件(即固定值)。我尝试首先只选择行,但通过以下方式选择所有 4 列:

I = A[A[:,1] == i]

有效。然后我进一步尝试(类似于我非常熟悉的matlab):

I = A[A[:,1] == i, [0,2,3]]

这是行不通的。怎么做?


示例数据:

 >>> A = np.array([[1,2,3,4],[6,1,3,4],[3,2,5,6]])
 >>> print A
 [[1 2 3 4]
  [6 1 3 4]
  [3 2 5 6]]
 >>> i = 2
     
 # I want to get the columns 1, 3 and 4 
 # for every row which has the value i in the second column. 
 # In this case, this would be row 1 and 3 with columns 1, 3 and 4:
 [[1 3 4]
  [3 5 6]]
 

我现在正在使用这个:

I = A[A[:,1] == i]
I = I[:, [0,2,3]]

但我认为必须有更好的方法来做到这一点......(我习惯了 MATLAB)

【问题讨论】:

  • A[A[:,1] == i][0,2,3] 也不起作用?
  • I = A[A[:,1] == i][0,2,3] --> IndexError: too many indices
  • 除此之外,我必须承认我也不会真正理解索引,这与 matlab 非常不同......
  • @tim:能否请您发布数组以及您期望的输出?
  • @Ankur Ankan:编辑成问题。

标签: python numpy


【解决方案1】:
>>> a = np.array([[1,2,3,4],[5,6,7,8],[9,10,11,12]])
>>> a
array([[ 1,  2,  3,  4],
       [ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

>>> a[a[:,0] > 3] # select rows where first column is greater than 3
array([[ 5,  6,  7,  8],
       [ 9, 10, 11, 12]])

>>> a[a[:,0] > 3][:,np.array([True, True, False, True])] # select columns
array([[ 5,  6,  8],
       [ 9, 10, 12]])

# fancier equivalent of the previous
>>> a[np.ix_(a[:,0] > 3, np.array([True, True, False, True]))]
array([[ 5,  6,  8],
       [ 9, 10, 12]])

有关晦涩的np.ix_() 的解释,请参阅https://stackoverflow.com/a/13599843/4323

最后,我们可以通过给出列号列表而不是繁琐的布尔掩码来简化:

>>> a[np.ix_(a[:,0] > 3, (0,1,3))]
array([[ 5,  6,  8],
       [ 9, 10, 12]])

【讨论】:

  • 真的需要连续选择两次吗?
  • 如果你希望你可以做a[x][y],其中 x 和 y 是布尔掩码,是的,我也希望这样,但它不起作用。这似乎是一个已知问题,我不知道为什么,但这在这里并不重要。
  • 不仅如此,我希望能够像这样在一个单一语句中选择行和列:A[row_indices_to_select, colum_indices_to_select],而row_indices_to_select 将来自我想要应用的条件。 :(
  • 我添加了更多解决方案——我喜欢最后一个使用 ix_() 和元组的解决方案。
【解决方案2】:

如果你不想使用布尔位置而是索引,你可以这样写:

A[:, [0, 2, 3]][A[:, 1] == i]

回到你的例子:

>>> A = np.array([[1,2,3,4],[6,1,3,4],[3,2,5,6]])
>>> print A
[[1 2 3 4]
 [6 1 3 4]
 [3 2 5 6]]
>>> i = 2
>>> print A[:, [0, 2, 3]][A[:, 1] == i]
[[1 3 4]
 [3 5 6]]

说真的,

【讨论】:

  • 布尔位置实际上对我来说没问题,我只想在一个步骤中进行选择,而不是在两个连续的选择中进行选择(您的解决方案正在这样做,不是吗?)因为性能原因。
【解决方案3】:
>>> a=np.array([[1,2,3], [1,3,4], [2,2,5]])
>>> a[a[:,0]==1][:,[0,1]]
array([[1, 2],
       [1, 3]])
>>> 

【讨论】:

    【解决方案4】:

    这也有效。

    I = np.array([row[[x for x in range(A.shape[1]) if x != i-1]] for row in A if row[i-1] == i])
    print I
    

    编辑:由于索引从0开始,所以

    i-1
    

    应该使用。

    【讨论】:

    • 算法一定是对的,但不是很pythonic。
    • @Taha 可能不是,但它可以节省您的双重选择。这个想法其实很简单,首先选择 cols 然后遍历行。
    • @genclik27 我明白你做了什么。但最近,我正在对大型矩阵进行一些数值计算。我一直需要矢量化计算。您提出的问题是您创建了一个新列表。您不能以这种方式直接更改矩阵中的值。如果您不需要更改 A 的值,它确实很有用。
    【解决方案5】:

    我希望这能回答你的问题,但我使用 pandas 实现的一段脚本是:

    df_targetrows = df.loc[df[col2filter]*somecondition*, [col1,col2,...,coln]]
    

    例如,

    targets = stockdf.loc[stockdf['rtns'] > .04, ['symbol','date','rtns']]
    

    这将返回一个数据框,其中仅包含来自stockdf 的列['symbol','date','rtns'],其中rtns 的行值满足stockdf['rtns'] > .04

    希望对你有帮助

    【讨论】:

      猜你喜欢
      • 2021-08-08
      • 2013-04-13
      • 1970-01-01
      • 2020-08-17
      • 2014-07-10
      • 2012-03-29
      • 1970-01-01
      • 2019-09-02
      相关资源
      最近更新 更多