我在更新数据结构时遇到了一些问题,无法找出原因。
我有这个数据结构:
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
谢谢!
答案 0 :(得分:0)
(先看)
如果您对eupm
之后的row_stack
感到满意,那么该部分代码就不是问题所在。您没有向我们展示关键部分 - 您如何尝试更改值。
然后,稍后,我想修改特定用户对的值(user_id和dated_id的组合)。但是,当我这样做时,它不会更改数组中的值。
此代码丢失。
您是否尝试同时修改两个字段,例如
eupm[['user_id','dated_id']][row_select] = ('new','value')
索引多个字段尚未完全开发。您可以阅读这些值,但无法对其进行修改。您必须一次更改一个字段,或更改整个记录。
你的代码不完整,所以我只是做了一个有根据的猜测。
===================================
(第2次详细介绍)
您的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
第3场。我会使用字段名称:
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)形状吗? 2D?您的复杂dtype
已经提供了伪二维结构。
我意识到我的答案很长而且有点散漫,但那是现实生活调试的本质。
====================
您还可以先按字段索引(这会创建一个视图):
eupm['preference_value'][mask]=3000
但您仍然无法为此额外申请[0]
。