My goal is to achieve simplified access to the various json files, with recarrays in a global recarray to achieve simplified end access like: parms.logic.myVarA.
Desired structure
parms (recarray)
[
logic (recarray)
- myVarA (int)
tool (recarray)
- myVarA (int)
]
Example:
parms.logic.myVarA
parms.tool.myVarA
I'm having a little trouble understanding numpy.recarray, I'm looking for help with a little piece of code. I have a class to test what I want to achieve:
import numpy as np
import simplejson, pathlib
# Loaders
class Loaders(np.recarray):
def __new__(_, targets):
content = [[],[]]
for k, v in targets.items():
# Load child
load = None
if(pathlib.Path(v).suffix == '.json'):
with open(v, 'r', encoding='utf-8') as file:
child = [[],[]]
for k_, v_ in simplejson.load(file).items():
child[0].append(v_)
child[1].append((k_, type(v_)))
load = np.array(tuple(child[0]), dtype=np.dtype(child[1])).view(np.recarray)
print(f'CHILD {k} {type(load)}')
print(f'Brute {child}')
print(f'Check {k}.myVarA{load.myVarA}\n')
if(load):
# Add child
content[0].append(load)
content[1].append((k, type(load)))
print('------ Loaded ------')
print(f'Brute {content}')
return np.array(tuple(content[0]), dtype=np.dtype(content[1])).view(np.recarray)
if __name__ == '__main__':
try:
# FAILURE
print('\n------ Loading ------')
parms = Loaders({
'logic' : './test/logic/parms.json',
'tool' : './test/tool/parms.json'
})
print('\n------ Final check ------')
print(f'parms dtypes {parms.dtype.names}')
print(f'parms.logic {parms.logic} {type(parms.logic)}')
print(f'Check parms.logic.myVarA{parms.logic.myVarA}')
except Exception as e:
print(f'Test failure {e}')
Output
CHILD logic <class 'numpy.recarray'>
Brute [[12, 44], [('myVarA', <class 'int'>), ('valB', <class 'int'>)]]
Check logic.myVarA12
CHILD tool <class 'numpy.recarray'>
Brute [[45], [('myVarA', <class 'int'>)]]
Check tool.myVarA45
------ Loaded ------
Brute [[rec.array((12, 44),
dtype=[('myVarA', '<i8'), ('valB', '<i8')]), rec.array((45,),
dtype=[('myVarA', '<i8')])], [('logic', <class 'numpy.recarray'>), ('tool', <class 'numpy.recarray'>)]]
------ Final check ------
parms dtypes ('logic', 'tool')
parms.logic (12, 44) <class 'numpy.ndarray'>
Test failure 'numpy.ndarray' object has no attribute 'myVarA'
I can see that the type of 'logic' change once the call is made but I don't understand why...
A check of 'parms' recarray dtype shows the presence of 'logic' and 'tool' but with an ndarray type. Yet higher their type is well recarray:
CHILD logic <class 'numpy.recarray'>
parms dtypes ('logic', 'tool')
print(f'Check parms.logic.valA {parms.logic.valA}')
Test failure 'numpy.ndarray' object has no attribute 'valA'
if any of you have an idea of my problem or a way to do this more simply I'm interested, thank you in advance
With this dtype:
I can make a recarray (with "random" values):
And access by attribute:
or field names (as structured array):
Another way of nesting recarrays is to use object dtypes:
The only way I can fill this with recarrays is:
which allows this access:
This may be too detailed for your purposes, but
recarrayis essentially just a numpy array subclass with a custom method for fetching a field. If the attribute isn't one of the standard array methods or attributes, it checks thedtype.namesfor a matching names: