如何在Pandas中有效地替换行值和索引标签?

时间:2016-11-23 13:44:48

标签: pandas

我正在寻找一种有效的方法来重复更新DataFrame中的行。我的意思是更改行值及其索引标签。我特别需要帮助后者。我能找到的最好的是How to change Pandas dataframe index value?但是,这会更新整个索引,而我关心的是单个索引标签。

不支持直接分配到index [n]:

>>> df.index[1] = 'new_label'
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/local/lib/python2.7/dist-packages/pandas/indexes/base.py", line 1374, in __setitem__
    raise TypeError("Index does not support mutable operations")

是否可以修改(赋值)索引下的numpy数组?

>>> df.index._values[1] = 'new_label'

更新不会破坏索引排序。

更多背景信息:

我有一个由timestamps(DatetimeIndex)索引的DataFrame,我需要实时有效地追加新行(每秒多次)。我使用NaT / NaN预先分配一个大的固定大小的DataFrame,然后通过写入下一个空行来追加行。

2 个答案:

答案 0 :(得分:1)

每秒多次更新dataframe效率不高。您应该附加一个列表,然后将列表转换为数据帧。

这样有:

log=list()
for i in range(1,10):   # here is your loop every minutes where log is updated
    log.append([date, value1, value2])

df = pd.DataFrame(log) # now you create the dataframe after being done updating the list.

答案 1 :(得分:1)

作为Steven G pointed,此更新效率非常低。

最好是创建DataFrames列表,然后使用concat

df1 = pd.DataFrame({'a': [1,2,3]}, index=pd.date_range('2015-01-01', periods=3))
print (df1)
            a
2015-01-01  1
2015-01-02  2
2015-01-03  3

df2 = pd.DataFrame({'a': [7,8,9]}, index=pd.date_range('2016-01-01', periods=3))
print (df2)
            a
2016-01-01  7
2016-01-02  8
2016-01-03  9

dfs = [df1,df2]

df = pd.concat(dfs)
print (df)
            a
2015-01-01  1
2015-01-02  2
2015-01-03  3
2016-01-01  7
2016-01-02  8
2016-01-03  9

然后您可以concat另一个DataFrame

df3 = pd.DataFrame({'a': [3,2,5]}, index=pd.date_range('2017-01-01', periods=3))
print (df3)
            a
2017-01-01  3
2017-01-02  2
2017-01-03  5

df = pd.concat([df, df3])
print (df)
            a
2015-01-01  1
2015-01-02  2
2015-01-03  3
2016-01-01  7
2016-01-02  8
2016-01-03  9
2017-01-01  3
2017-01-02  2
2017-01-03  5

或使用DataFrame.append

df4 = pd.DataFrame({'a': [3,2,4]}, index=pd.date_range('2018-01-01', periods=3))
print (df4)
            a
2018-01-01  3
2018-01-02  2
2018-01-03  4

df = df.append(df4)
print (df)
            a
2015-01-01  1
2015-01-02  2
2015-01-03  3
2016-01-01  7
2016-01-02  8
2016-01-03  9
2017-01-01  3
2017-01-02  2
2017-01-03  5
2018-01-01  3
2018-01-02  2
2018-01-03  4

替换索引中的值的解决方案:

你可以使用与df.index._values[1] = 'new_label'非常相似的只删除_而另一个解决方案是Index.set_value

df = pd.DataFrame({'a': [1,2,3]}, index=pd.date_range('2016-01-01', periods=3))
print (df)
            a
2016-01-01  1
2016-01-02  2
2016-01-03  3

df.index.values[0] = pd.Timestamp(2016,11,23,1,0,0)
df.index.set_value(df.index, df.index[1], pd.Timestamp(2016,11,22,1,0,0))

print (df)
                     a
2016-11-23 01:00:00  1
2016-11-22 01:00:00  2
2016-01-03 00:00:00  3