диктат диктатора списка / pandas-dataframe / numpy-array - PullRequest
0 голосов
/ 15 ноября 2018

Я новичок в пандах и numpy

Я работаю с набором данных, упомянутым в этой статье ,

У меня есть несколько изображений, каждое изображение описывается определенными визуальными дескрипторами, такими как CM, CN, GLRLM (значение этих дескрипторов не важно), и эти визуальные дескрипторы в основном являются списками.

Итак, моя структура данных:

idsDict = {
    12312: {
         "CM": [2, 3, 1, 5, 1],
         "CN" : [1, 4, 5, 1]
    },
    21367: {
         "GLRLM": [9, 4, 1, 4, 5, 12, 67, 12],
         "CM"   : [1, 6, 8, 1, 34]
    }
}

12312 , 21367 - идентификаторы изображений

Я хочу преобразовать это значение в тензорный / числовой массив (3D) / pandas-dataframe (3D), чтобы я мог находить расстояния между изображениями на основе дескрипторов.

В основном структура тензорного / числового массива (3D) / pandas-dataframe (3D) будет кубоидом со строками в качестве идентификаторов изображений, столбцами в качестве дескрипторов и по оси z будут содержать значения дескрипторов

Я прочитал,

Построить панду DataFrame из элементов во вложенном словаре

Pandas dataframe to dict of dict

1 Ответ

0 голосов
/ 15 ноября 2018

С точки зрения скорости вычислений вам, вероятно, лучше всего использовать Numpy:

import numpy as np

idsDict = {
    12312: {
      "CM": [2, 3, 1, 5, 1],
      "CN" : [1, 4, 5, 1]
    },
    21367: {
      "GLRLM": [9, 4, 1, 4, 5, 12, 67, 12],
      "CM"   : [1, 6, 8, 1, 34]
    }
}

# loop through once to figure out size of final data structure
dscr = {}
maxlen = 0
for d in idsDict.values():
    for descName,desc in d.items():
        if descName not in dscr:
            dscr[descName] = np.obj2sctype(desc[0]) if len(desc) else np.int64
        if len(desc) > maxlen:
            maxlen = len(desc)

# allocate a masked structured array of the right shape and dtype
dtype = np.dtype(sorted(dscr.items()))
_data3d = np.empty((len(idsDict), maxlen), dtype=dtype)
data3d = np.ma.array(_data3d, mask=True)

# copy the data over the array
for d,drow in zip(idsDict.values(), data3d):
    for descName,desc in d.items():
        drow[descName][:len(desc)] = desc

print(data3d.dtype.names,'\n')
print(data3d.T)

Который выводит:

('CM', 'CN', 'GLRLM')

[[(2.0, 1.0, --) (1.0, --, 9.0)]
 [(3.0, 4.0, --) (6.0, --, 4.0)]
 [(1.0, 5.0, --) (8.0, --, 1.0)]
 [(5.0, 1.0, --) (1.0, --, 4.0)]
 [(1.0, --, --) (34.0, --, 5.0)]
 [(--, --, --) (--, --, 12.0)]
 [(--, --, --) (--, --, 67.0)]
 [(--, --, --) (--, --, 12.0)]]

К сожалению, нет хорошего способа сохранить идентификаторы изображенийв структурированном массиве Numpy.Если вам это нужно, вместо этого вы можете использовать Панд.Вот как вы можете сжать все свои данные в одном 3D-кадре Pandas:

import pandas as pd

idsDict = {
    12312: {
      "CM": [2, 3, 1, 5, 1],
      "CN" : [1, 4, 5, 1]
    },
    21367: {
      "GLRLM": [9, 4, 1, 4, 5, 12, 67, 12],
      "CM"   : [1, 6, 8, 1, 34]
    }
}

# loop through once to figure out size of final data structure
descNames = set()
maxlen = 0
for d in idsDict.values():
    for descName,desc in d.items():
        descNames.add(descName)
        if len(desc) > maxlen:
            maxlen = len(desc)

# pad data
padDesc = maxlen*[np.nan]
for d in idsDict.values():
    for desc in d.values():
        dlen = len(desc)
        if dlen < maxlen:
            desc.extend((maxlen - dlen)*[np.nan])
    for descName in (n for n in descNames if n not in d):
        d[descName] = padDesc

data3d = pd.concat([pd.DataFrame(d) for id,d in idsDict.items()], keys=idsDict.keys())
print(data3d)

Это выдаст:

           CM   CN  GLRLM
12312 0   2.0  1.0    NaN
      1   3.0  4.0    NaN
      2   1.0  5.0    NaN
      3   5.0  1.0    NaN
      4   1.0  NaN    NaN
      5   NaN  NaN    NaN
      6   NaN  NaN    NaN
      7   NaN  NaN    NaN
21367 0   1.0  NaN    9.0
      1   6.0  NaN    4.0
      2   8.0  NaN    1.0
      3   1.0  NaN    4.0
      4  34.0  NaN    5.0
      5   NaN  NaN   12.0
      6   NaN  NaN   67.0
      7   NaN  NaN   12.0
...