Каков наилучший способ хранения элементов с несколькими записями (фиксированной длины) в столбце pandas
DataFrame
? Я думаю о чем-то вроде трехмерного вектора положения. Например, если мой DataFrame
хранит данные о группе физических объектов, это может выглядеть так:
df = pandas.DataFrame({
'type': [1, 2, 1, 1, 3],
'mass': [1.1, 2.2, 3.3, 4.4, 5.5],
'pos': [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]],
'vel': [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, 11, 12], [13, 14, 15]]
})
# mass pos type vel
# 0 1.1 [1, 2, 3] 1 [1, 2, 3]
# 1 2.2 [4, 5, 6] 2 [4, 5, 6]
# 2 3.3 [7, 8, 9] 1 [7, 8, 9]
# 3 4.4 [10, 11, 12] 1 [10, 11, 12]
# 4 5.5 [13, 14, 15] 3 [13, 14, 15]
Здесь столбцы 'pos'
и 'vel'
являются позициями и скоростями объектов в трехмерном пространстве.
Я подумал о нескольких вариантах, ни один из которых не кажется идеальным или даже не работает:
Сохранение списков Python в виде значений в столбце. Это в основном то, что я показал в примере выше. К сожалению, это очень неэффективно.
Разделение столбца на несколько разных:
df = pandas.DataFrame({
'type': [1, 2, 1, 1, 3],
'mass': [1.1, 2.2, 3.3, 4.4, 5.5],
'x': [1, 4, 7, 10, 13],
'y': [2, 5, 8, 11, 14],
'z': [3, 6, 8, 12, 15],
'vx': [1, 4, 7, 10, 13],
'vy': [2, 5, 8, 11, 14],
'vz': [3, 6, 8, 12, 15]
})
# mass type vx vy vz x y z
# 0 1.1 1 1 2 3 1 2 3
# 1 2.2 2 4 5 6 4 5 6
# 2 3.3 1 7 8 8 7 8 8
# 3 4.4 1 10 11 12 10 11 12
# 4 5.5 3 13 14 15 13 14 15
Похоже, это станет громоздким для больших атрибутов. Но по крайней мере, это эффективно?
Я также пытался присвоить многомерный массив numpy
столбцу, но, к сожалению, pandas
отказывается:
pos = numpy.array([[11, 12, 13],
[22, 23, 24],
[33, 34, 35],
[44, 45, 46],
[55, 56, 57]])
df.loc[:, 'pos'] = pos
# ---------------------------------------------------------------------------
# ValueError Traceback (most recent call last)
# <ipython-input-228-2ee95dd5aa19> in <module>()
# ----> 1 df.loc[:, 'pos'] = pos
#
# /opt/anaconda-3/anaconda3/lib/python3.6/site-packages/pandas/core/indexing.py in __setitem__(self, key, value)
# 177 key = com._apply_if_callable(key, self.obj)
# 178 indexer = self._get_setitem_indexer(key)
# --> 179 self._setitem_with_indexer(indexer, value)
# 180
# 181 def _has_valid_type(self, k, axis):
#
# /opt/anaconda-3/anaconda3/lib/python3.6/site-packages/pandas/core/indexing.py in _setitem_with_indexer(self, indexer, value)
# 561 value = np.array(value, dtype=object)
# 562 if len(labels) != value.shape[1]:
# --> 563 raise ValueError('Must have equal len keys and value '
# 564 'when setting with an ndarray')
# 565
#
# ValueError: Must have equal len keys and value when setting with an ndarray