创建一个空的 Pandas DataFrame,然后填充它?

新手上路,请多包涵

我从这里的熊猫 DataFrame 文档开始: http ://pandas.pydata.org/pandas-docs/stable/dsintro.html

我想用时间序列计算中的值迭代地填充 DataFrame。所以基本上,我想用列 A、B 和时间戳行来初始化 DataFrame,全为 0 或全为 NaN。

然后我会添加初始值并检查这些数据,从前一行计算新行,比如 row[A][t] = row[A][t-1]+1 左右。

我目前正在使用下面的代码,但我觉得它有点难看,必须有一种方法可以直接使用 DataFrame 来做到这一点,或者一般来说只是一种更好的方法。注意:我使用的是 Python 2.7。

 import datetime as dt
import pandas as pd
import scipy as s

if __name__ == '__main__':
    base = dt.datetime.today().date()
    dates = [ base - dt.timedelta(days=x) for x in range(0,10) ]
    dates.sort()

    valdict = {}
    symbols = ['A','B', 'C']
    for symb in symbols:
        valdict[symb] = pd.Series( s.zeros( len(dates)), dates )

    for thedate in dates:
        if thedate > dates[0]:
            for symb in valdict:
                valdict[symb][thedate] = 1+valdict[symb][thedate - dt.timedelta(days=1)]

    print valdict

原文由 Matthias Kauer 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 1.2k
2 个回答

这里有几个建议:

使用 date_range 作为索引:

 import datetime
import pandas as pd
import numpy as np

todays_date = datetime.datetime.now().date()
index = pd.date_range(todays_date-datetime.timedelta(10), periods=10, freq='D')

columns = ['A','B', 'C']

注意:我们可以创建一个空的 DataFrame(带有 NaN s),只需编写:

 df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs

要对数据进行这些类型的计算,请使用 numpy 数组:

 data = np.array([np.arange(10)]*3).T

因此我们可以创建 DataFrame:

 In [10]: df = pd.DataFrame(data, index=index, columns=columns)

In [11]: df
Out[11]:
            A  B  C
2012-11-29  0  0  0
2012-11-30  1  1  1
2012-12-01  2  2  2
2012-12-02  3  3  3
2012-12-03  4  4  4
2012-12-04  5  5  5
2012-12-05  6  6  6
2012-12-06  7  7  7
2012-12-07  8  8  8
2012-12-08  9  9  9

原文由 Andy Hayden 发布,翻译遵循 CC BY-SA 3.0 许可协议

永远不要按行增长 DataFrame!

TLDR; (只需阅读粗体文字)

这里的大多数答案都会告诉您如何创建一个空的 DataFrame 并填充它,但没有人会告诉您这是一件坏事。

这是我的建议: 在列表而不是 DataFrame 中累积数据。

使用列表来收集数据,然后在准备好后初始化 DataFrame。列表列表或字典列表格式都可以, pd.DataFrame 两者都接受。

 data = []
for row in some_function_that_yields_data():
    data.append(row)

df = pd.DataFrame(data)

pd.DataFrame 将行列表(每行是一个标量值)转换为 DataFrame。如果您的函数改为生成数据帧,请调用 pd.concat

这种方法的优点:

  1. 与创建一个空的 DataFrame(或其中一个 NaN)并一遍又一遍地附加到它相比 ,附加到列表并一次性创建 DataFrame 总是更便宜

  2. 列表占用的内存也更少,并且是一种更轻便的数据结构,可以使用、追加和删除(如果需要)。

  3. dtypes 是自动推断的(而不是将 object 分配给所有这些)。

  4. A RangeIndex 会自动为您的数据创建,而您不必在每次迭代时注意将正确的索引分配给要追加的行。

如果您还不相信, 文档 中也提到了这一点:

与单个连接相比,迭代地将行附加到 DataFrame 的计算量更大。更好的解决方案是将这些行附加到列表中,然后将列表与原始 DataFrame 一起连接起来。

\*\*\* pandas >= 1.4 的更新: append 现已弃用! ***

从 pandas 1.4 开始, append 现已弃用!使用 pd.concat 代替。查看 发行说明



这些选项很可怕

appendconcat 循环内

这是我从初学者那里看到的最大错误:

 df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
    df = df.append({'A': i, 'B': b, 'C': c}, ignore_index=True) # yuck
    # or similarly,
    # df = pd.concat([df, pd.Series({'A': i, 'B': b, 'C': c})], ignore_index=True)

为每个 appendconcat 操作重新分配内存。将其与循环结合起来,您将获得 二次复杂度运算

df.append 相关的另一个错误是用户往往会忘记 append 不是 in-place function ,因此必须将结果赋值回来。您还必须担心数据类型:

 df = pd.DataFrame(columns=['A', 'B', 'C'])
df = df.append({'A': 1, 'B': 12.3, 'C': 'xyz'}, ignore_index=True)

df.dtypes
A     object   # yuck!
B    float64
C     object
dtype: object

处理对象列从来都不是一件好事,因为 pandas 无法向量化这些列上的操作。您将需要执行此操作来修复它:

 df.infer_objects().dtypes
A      int64
B    float64
C     object
dtype: object

loc 循环内

我还看到 loc 用于附加到创建为空的 DataFrame:

 df = pd.DataFrame(columns=['A', 'B', 'C'])
for a, b, c in some_function_that_yields_data():
    df.loc[len(df)] = [a, b, c]

和以前一样,您没有每次都预先分配所需的内存量,因此 每次创建新行时都会重新增长内存。它和 append 一样糟糕,甚至更丑陋。

NaN 的空 DataFrame

然后,创建一个 NaN 的 DataFrame,以及与之相关的所有注意事项。

 df = pd.DataFrame(columns=['A', 'B', 'C'], index=range(5))
df
     A    B    C
0  NaN  NaN  NaN
1  NaN  NaN  NaN
2  NaN  NaN  NaN
3  NaN  NaN  NaN
4  NaN  NaN  NaN

它创建一个对象列的 DataFrame,就像其他的一样。

 df.dtypes
A    object  # you DON'T want this
B    object
C    object
dtype: object

Appending 仍然存在上述方法的所有问题。

 for i, (a, b, c) in enumerate(some_function_that_yields_data()):
    df.iloc[i] = [a, b, c]



证据就在布丁里

对这些方法进行计时是查看它们在内存和实用程序方面有多大差异的最快方法。

在此处输入图像描述

基准代码供参考。

原文由 cs95 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题