Как транслировать и назначить серию значений по всем столбцам в кадре данных Pandas? - PullRequest
0 голосов
/ 06 сентября 2018

Я знаю, что это должно быть легко, но я не могу понять это или найти существующий ответ на это ...

Скажите, у меня есть этот фрейм данных ...

>>> import pandas as pd
>>> import numpy as np
>>> dates = pd.date_range('20130101', periods=6)
>>> df = pd.DataFrame(np.nan, index=dates, columns=list('ABCD'))
>>> df
             A   B   C   D
2013-01-01 NaN NaN NaN NaN
2013-01-02 NaN NaN NaN NaN
2013-01-03 NaN NaN NaN NaN
2013-01-04 NaN NaN NaN NaN
2013-01-05 NaN NaN NaN NaN
2013-01-06 NaN NaN NaN NaN

Легко установить значения одной серии ...

>>> df.loc[:, 'A'] = pd.Series([1,2,3,4,5,6], index=dates)
>>> df
            A   B   C   D
2013-01-01  1 NaN NaN NaN
2013-01-02  2 NaN NaN NaN
2013-01-03  3 NaN NaN NaN
2013-01-04  4 NaN NaN NaN
2013-01-05  5 NaN NaN NaN
2013-01-06  6 NaN NaN NaN

Но как мне установить значения всех столбцов с помощью широковещания?

>>> default_values = pd.Series([1,2,3,4,5,6], index=dates)
>>> df.loc[:, :] = default_values
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/billtubbs/anaconda/envs/py36/lib/python3.6/site-packages/pandas/core/indexing.py", line 189, in __setitem__
    self._setitem_with_indexer(indexer, value)
  File "/Users/billtubbs/anaconda/envs/py36/lib/python3.6/site-packages/pandas/core/indexing.py", line 651, in _setitem_with_indexer
    value=value)
  File "/Users/billtubbs/anaconda/envs/py36/lib/python3.6/site-packages/pandas/core/internals.py", line 3693, in setitem
    return self.apply('setitem', **kwargs)
  File "/Users/billtubbs/anaconda/envs/py36/lib/python3.6/site-packages/pandas/core/internals.py", line 3581, in apply
    applied = getattr(b, f)(**kwargs)
  File "/Users/billtubbs/anaconda/envs/py36/lib/python3.6/site-packages/pandas/core/internals.py", line 940, in setitem
    values[indexer] = value
ValueError: could not broadcast input array from shape (6) into shape (6,4)

Кроме этих способов:

>>> for s in df:
...     df.loc[:, s] = default_values
... 

Или:

>>> df.loc[:, :] = np.vstack([default_values]*4).T

UPDATE:

Или:

>>> df.loc[:, :] = default_values.values.reshape(6,1)

Ответы [ 3 ]

0 голосов
/ 06 сентября 2018

Использовать NumPy broadcasting

s =  pd.Series([1,2,3,4,5,6], index=dates)
df.loc[:,:] = s.values[:,None]

Использование индекса соответствия

df.loc[:] = pd.concat([s]*df.columns.size, axis=1)
0 голосов
/ 06 сентября 2018

Самый простой способ уже предоставлен в Pandas: вызов метода .add и указание, в каком направлении (оси) вы хотите добавить новые значения.

In [7]: df.fillna(0).add(default_values, axis=0)
Out[7]:
              A    B    C    D
2013-01-01  1.0  1.0  1.0  1.0
2013-01-02  2.0  2.0  2.0  2.0
2013-01-03  3.0  3.0  3.0  3.0
2013-01-04  4.0  4.0  4.0  4.0
2013-01-05  5.0  5.0  5.0  5.0
2013-01-06  6.0  6.0  6.0  6.0

Примечание: в более новых версиях панд вы можете просто сделать df.add(default_values, axis=0, fill_value=0), в основном улучшение синтаксиса, чтобы избежать цепных методов.

Обратите внимание, что если здесь применима идея выравнивания индекса панд: учитывая этот случай, когда новые значения охватывают только 4 из 5 строк целевого кадра данных

In [37]: default_values = pd.Series([1,2,3,4], index=['a', 'b', 'c', 'd'])

In [38]: df = pd.DataFrame(np.ones(shape=(5,5)) + np.nan, index=['a', 'b', 'c', 'd', 'e'])

In [39]: df.fillna(0).add(default_values, axis=0)
Out[39]:
     0    1    2    3    4
a  1.0  1.0  1.0  1.0  1.0
b  2.0  2.0  2.0  2.0  2.0
c  3.0  3.0  3.0  3.0  3.0
d  4.0  4.0  4.0  4.0  4.0
e  NaN  NaN  NaN  NaN  NaN

Строка e, которая не найдена в новом значении Series, становится NaN

0 голосов
/ 06 сентября 2018

Вы можете решить эту проблему с помощью NumPy:

nvalues = 6
ncolumns = 4
default_values = np.repeat(np.arange(nvalues), ncolumns).reshape(nvalues, ncolumns)

df.loc[:, :] = default_values

Однако это не соответствует вашей надежде на трансляцию на стороне Панд. Я не знаю каких-либо хитростей для этого.

...