python pandas使用iloc更改数据帧单元格

时间:2017-07-22 05:31:21

标签: python pandas

我正在尝试修改数据框的单行中的两个值。但是,我得到一个例外,我无法解释原因。

In [1]: import numpy as np

In [2]: import pandas as pd

In [3]: df = pd.DataFrame(np.random.rand(2,3), index=['one', 'two'],
                          columns=list('ABC'))

In [4]: df['Z'] = list(range(len(df.index)))

In [5]: df.head(1)
Out[5]: 
            A         B         C  Z
one  0.977917  0.734311  0.069476  0

In [6]: df.iloc[0] = dict(B=3.5, Z=10)
  

/home/rajatgirotra/tools/miniconda2/envs/shriram/lib/python2.7/site-packages/pandas/core/indexing.pyc   in _setitem_with_indexer(self,indexer,value)       525       526如果len(标签)!= len(值):    - > 527引发ValueError('必须具有相等的len键和值'       528'设置为可迭代时')       529

     

ValueError:设置时必须具有相等的len键和值   可迭代

这种方式不正确吗?如何轻松修改同一行中的一个或多个单元格值?

2 个答案:

答案 0 :(得分:3)

我认为您需要按lociloc的dict键选择仅列,否则获取NaN s:

d = dict(B=3.5, Z=10)
df.loc[df.index[0], d.keys()] = pd.Series(d)
print (df)
            A         B         C     Z
one  0.062352  3.500000  0.225811  10.0
two  0.655920  0.386443  0.063906   1.0
df.iloc[0, df.columns.get_indexer(d.keys())] = pd.Series(d)
print (df)
            A         B         C     Z
one  0.422479  3.500000  0.951087  10.0
two  0.097426  0.702746  0.257591   1.0
df.loc[df.index[0]] = pd.Series(d)
print (df)
            A         B         C     Z
one       NaN  3.500000       NaN  10.0
two  0.050399  0.917007  0.951725   1.0
df.iloc[0] = pd.Series(d)
print (df)
          A         B         C     Z
one     NaN  3.500000       NaN  10.0
two  0.5356  0.844221  0.023227   1.0

答案 1 :(得分:3)

@ jezrael的df.iloc[0] = pd.Series(d)是我的偏好。

但您也可以使用pd.DataFrame.update并将字典包装在pd.DataFrame

df.update(pd.DataFrame(dict(B=3.5, Z=10), ['one']))

df

            A         B         C     Z
one  0.339970  3.500000  0.528206  10.0
two  0.553827  0.117207  0.784605   1.0

虽然我在这里,但这是一种使用pd.DataFrame.set_value和列表理解的创造性方式。这样做的好处是不需要构建数据帧的开销,并注意dtype列上保留'Z'

[df.set_value('one', k, v) for k, v in dict(B=3.5, Z=10).items()];

df

            A         B         C   Z
one  0.099669  3.500000  0.248170  10
two  0.604340  0.305114  0.897305   1

这并不重要,但这是微小数据样本的时间

%timeit [df.set_value('one', k, v) for k, v in dict(B=3.5, Z=10).items()];
%timeit df.update(pd.DataFrame(dict(B=3.5, Z=10), ['one']))
%timeit df.iloc[0] = pd.Series(dict(B=3.5, Z=10))

100000 loops, best of 3: 5.29 µs per loop
1000 loops, best of 3: 1.51 ms per loop
1000 loops, best of 3: 402 µs per loop