【问题标题】:Updating numpy array datastructure in Python在 Python 中更新 numpy 数组数据结构
【发布时间】:2016-03-07 02:33:05
【问题描述】:

我在更新数据结构时遇到了一些问题,不知道为什么。

我有这个数据结构:

USER_EVENT_PAIR_NUMPY_DATA_TYPE = numpy.dtype([('user_id', numpy.int64, 1), ('dated_id', numpy.int64, 1),
                                          ('preference_value', numpy.float64, 1),
                                          ('weighted_preference_value', numpy.float64, 1),
                                          ('date_type', numpy.int8, 1),
                                          ('user_rating', numpy.int8, 1),
                                          ('pair_met_at_event_round_num', numpy.int16, 1),
                                          ('match_type', numpy.int8, 1)])

我创建了一个数组:

arr = numpy.empty([0,1],dtype=USER_EVENT_PAIR_NUMPY_DATA_TYPE)

我会定期向其中添加行:

row = numpy.array([(dater1.get_user_key,    #User1ID
                            dater2.get_user_key,    #User2ID
                            Dater1PreferenceVal,    #Initial preference value
                            0.0,                    #Weighted preference value
                            DateType,               # Date type
                            0,                      # User rating
                            -1,                     # Pair met at event round
                            0)],                    # Match type
                          dtype=USER_EVENT_PAIR_NUMPY_DATA_TYPE)

eupm = numpy.row_stack((eupm, row))

然后,稍后,我想修改特定用户对的值(user_id 和 dated_id 的组合)。但是,当我这样做时,它不会更改数组中的值。如果我在这个 set 语句之前和之后打印数组中的值,它是相同的。它正在成功地从数组中读取现有值。我错过了什么?

eupm[(eupm[:]['user_id'] == user1.get_user_key) & (eupm[:]['dated_id'] == user2.get_user_key)][0][2] = PreferenceVal

谢谢!

【问题讨论】:

  • 能否提供代码也可能是您的代码有问题?
  • 代码在那里,但很难阅读,也很难剪切和粘贴。

标签: arrays python-2.7 numpy data-structures


【解决方案1】:

(第一眼)

如果您对row_stack 之后的eupm 感到满意,那么这部分代码就不是问题所在。您没有向我们展示关键部分 - 您如何尝试更改价值观。

然后,稍后,我想修改特定用户对的值(user_id 和 dated_id 的组合)。但是,当我这样做时,它不会更改数组中的值。

此代码丢失。

您是否有机会尝试一次修改两个字段,例如

eupm[['user_id','dated_id']][row_select] = ('new','value')

索引多个字段尚未完全开发。您可以读取这些值,但不能修改它们。您必须一次更改一个字段,或更改整条记录。

您的代码不完整,所以我只是做出有根据的猜测。

====================================

(第二次详细查看)

您的row 定义包含对未知值的引用。所以我必须插入我自己的价值观来做一个剪切粘贴。那是不好的形式。如果您想轻松复制您的结果。

在您的测试中,[:] 是多余的:

In [163]: eupm[:]['user_id']
Out[163]: array([[123]], dtype=int64)

eupm['user_id'] 就足够了。

现在我实际上是在尝试复制您的结果,我看到最后一个表达式实际上是赋值,而不是测试。像这样长的表达式很难阅读。

eupm[(eupm[:]['user_id'] == user1.get_user_key) & (eupm[:]['dated_id'] == user2.get_user_key)][0][2] = PreferenceVal

这里有一些内容,希望更具可读性:

In [167]: mask=(eupm['user_id'] == 123) & (eupm['dated_id'] == 123)

In [168]: mask
Out[168]: array([[ True]], dtype=bool)

In [169]: eupm[mask]
Out[169]: 
array([(123L, 123L, 123.0, 0.0, 123, 0, -1, 0)], 
      dtype=[('user_id', '<i8'), ('dated_id', '<i8'), ('preference_value', '<f8'), ('weighted_preference_value', '<f8'), ('date_type', 'i1'), ('user_rating', 'i1'), ('pair_met_at_event_round_num', '<i2'), ('match_type', 'i1')])

所以我找到了一个满足 2 id 条件的元素。

In [170]: eupm[mask][0]
Out[170]: (123L, 123L, 123.0, 0.0, 123, 0, -1, 0)

所以这拉出了第一条记录

In [171]: eupm[mask][0][2]
Out[171]: 123.0

还有第三场。我会使用字段名称:

In [174]: eupm[mask][0]['preference_value']
Out[174]: 123.0

最后你尝试了一个作业:

In [172]: eupm[mask][0][2]=1000

没有变化:

In [173]: eupm
Out[173]: 
array([[(123L, 123L, 123.0, 0.0, 123, 0, -1, 0)]], 
      dtype=[('user_id', '<i8'), ('dated_id', '<i8'), ('preference_value', '<f8'), ('weighted_preference_value', '<f8'), ('date_type', 'i1'), ('user_rating', 'i1'), ('pair_met_at_event_round_num', '<i2'), ('match_type', 'i1')])

这里的问题是eupm[mask] 是副本,而不是视图。

使用视图的例子是:

In [176]: eupm[:1][0]['preference_value']=1000

In [177]: eupm
Out[177]: 
array([[(123L, 123L, 1000.0, 0.0, 123, 0, -1, 0)]], ...)

任何时候你用布尔掩码索引一个数组,你都会得到一个副本,并且你必须非常小心地使用第二个索引。

arr[mask][0] = ...   # does not work

我认为你需要做的是获取行号,并以此为索引:

In [180]: idx=numpy.where(mask)    
In [181]: idx
Out[181]: (array([0]), array([0]))  # eupm is (1,1) (2d)
In [182]: idx=idx[0][0]  # 2d makes selecting the index more complicated

正确的索引:

In [187]: eupm[idx,0]['preference_value']=2000

你真的需要将arr 初始化为 (0,1) 形状吗?二维?您的复杂 dtype 已经提供了伪二维结构。

我意识到我的回答很长而且有点漫无边际,但这是现实生活中调试的本质。

=====================

您也可以先按字段索引(这会创建一个视图):

eupm['preference_value'][mask]=3000

但您仍然不能对此应用额外的[0]。

【讨论】:

    猜你喜欢
    • 2021-05-05
    • 2013-03-12
    • 1970-01-01
    • 2018-08-09
    • 1970-01-01
    • 2021-10-26
    • 1970-01-01
    • 2021-05-30
    • 1970-01-01
    相关资源
    最近更新 更多