我有一个包含以下列的数据框:
'价值'| 'x'| 'y'| 'z'|
x,y,z是整数,值是浮点数。
我想使用数据框中的值填充具有给定形状(与x,y和z的范围兼容)的numpy 3D矩阵 mat 。当坐标指向 mat 中的相同位置时,我只想添加值。
我可以使用for循环“手动”执行此操作但是有没有办法使用pandas / numpy函数执行此操作?
例如:
mat[0,0,0] = -2
mat[0,1,2] = 8.6
应该使用以下值导致 mat :
SELECT user_id, MAX(session_date) as date_session, value FROM user_extra GROUP BY user_id
答案 0 :(得分:2)
我可能会这样做:
In [185]: target = np.zeros(df.iloc[:, 1:].max() + 1)
In [186]: np.add.at(target, df.iloc[:, 1:].T.values.tolist(), df["value"])
In [187]: target
Out[187]:
array([[[-2. , 0. , 0. ],
[ 0. , 0. , 8.6]]])
In [188]: target.shape
Out[188]: (1, 2, 3)
In [189]: target[0, 0, 0]
Out[189]: -2.0
In [190]: target[0, 1, 2]
Out[190]: 8.5999999999999996
从值中构建适当大小的目标,然后使用np.add.at
添加到目标并相应地处理重复项。唯一棘手的一点是我们需要转置(将X坐标放在一起等)并制作一个列表,以便正确解释索引。
答案 1 :(得分:1)
我看到至少有两个基于NumPy的。其中一个是np.add.at
,已在@DSM's post
中讨论,另一个在np.bincount
中讨论过。使用np.bincount
的实现看起来像这样 -
def dataframe_to_array(df, out_shp):
ids = np.ravel_multi_index(df[['x','y','z']].values.T, out_shp)
val = df['value'].values
return np.bincount(ids, val, minlength=np.prod(out_shp)).reshape(out_shp)
示例运行 -
In [115]: df
Out[115]:
value x y z
0 5.6 0 1 2
1 -2.0 0 0 0
2 3.0 0 1 2
In [116]: out = dataframe_to_array(df, (3,3,3))
In [117]: out[0,0,0]
Out[117]: -2.0
In [118]: out[0,1,2]
Out[118]: 8.5999999999999996
np.add.at
基于@ DSM的解决方案 -
def dataframe_to_array_addat(df, out_shp):
target = np.zeros(out_shp)
np.add.at(target, df[['x','y','z']].T.values.tolist(), df["value"])
return target
计时 -
In [182]: N = 200 # dataset size/array shape decider
In [183]: df = pd.DataFrame(np.random.randint(0,N,(100000,3)),
columns=[['x','y','z']])
In [184]: df['value'] = np.random.rand(df.shape[0])
In [185]: %timeit dataframe_to_array_addat(df, (N,N,N))
10 loops, best of 3: 36.1 ms per loop
In [186]: %timeit dataframe_to_array(df, (N,N,N))
100 loops, best of 3: 8.22 ms per loop
答案 2 :(得分:0)
听起来你需要多索引
df1=df.set_index(['x','y','z'])
df1.loc[(0,1,2)].sum()
Out[273]:
value 8.6
答案 3 :(得分:0)
您可以像大熊猫loc_indexer
:
df=pd.DataFrame({'value': {0: 5.6, 1: -2.0, 2: 3.0},
'x': {0: 0, 1: 0, 2: 0},
'y': {0: 1, 1: 0, 2: 1},
'z': {0: 2, 1: 0, 2: 2}})
fields = list('xyz')
mat = df.groupby(fields).sum().loc
In [9]: mat[0,0,0]
Out[9]:
value -2.0
Name: (0, 0, 0), dtype: float64
In [10]: mat[0,1,2]
Out[10]:
value 8.6
Name: (0, 1, 2), dtype: float64
或构建真正的矩阵:
mat2=np.full(df[fields].max()+1,np.nan)
for (x,y,z),v in mat.obj.iterrows(): mat2[x,y,z]=v