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

Mat*_*uer 381 python dataframe pandas

我从这里的pandas 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
Run Code Online (Sandbox Code Playgroud)

And*_*den 281

以下是一些建议:

使用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']
Run Code Online (Sandbox Code Playgroud)

注意:我们可以NaN简单地通过编写来创建一个空的DataFrame(带有s):

df_ = pd.DataFrame(index=index, columns=columns)
df_ = df_.fillna(0) # with 0s rather than NaNs
Run Code Online (Sandbox Code Playgroud)

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

data = np.array([np.arange(10)]*3).T
Run Code Online (Sandbox Code Playgroud)

因此我们可以创建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
Run Code Online (Sandbox Code Playgroud)

  • 根据我的经验,创建一个填充了NaNs的必要大小的数据框,然后填充值比创建一个带有`index` x` 0`维度(`columns = []`)的数据框要慢得多,并在循环的每一圈中附加一列.我的意思是`df [col_name] = pandas.Series([...])`在循环遍历列名的循环中.在前一种情况下,不仅内存分配需要时间,而且用新值替换NaN似乎非常慢. (25认同)
  • 绝对是@deeenes.这个答案应该更清楚 - 你很少(如果有的话)想要创建一个空的Dataframe(NaNs). (5认同)
  • pd.date_range()对我不起作用.我尝试使用DateRange(来自eclipse的自动完成),但是使用字符串作为日期格式,对吧?虽然整体方法有效(我将索引更改为其他内容). (2认同)
  • date_range是用于创建日期时间索引的工厂函数,并且是[0.8.0中的新功能](http://pandas.pydata.org/pandas-docs/version/0.8.0/whatsnew.html?highlight=date_range),我肯定会建议升级到最新的稳定版本(0.9.1),有很多错误修复和新功能.:) (2认同)

gee*_*rsh 136

如果您只是想创建一个空数据框并稍后用一些传入数据框填充它,请尝试以下方法:

在这个例子中,我使用这个pandas doc创建一个新的数据框,然后使用append用newDF中的数据写入newDF.


看看这个

newDF = pd.DataFrame() #creates a new dataframe that's empty
newDF = newDF.append(oldDF, ignore_index = True) # ignoring index is optional
# try printing some data from newDF
print newDF.head() #again optional 
Run Code Online (Sandbox Code Playgroud)

  • 请注意,`append`(以及类似的`concat`)每次都会将完整数据集复制到一个新对象,因此,迭代和追加可以并且将导致重大性能损失.有关更多信息,请参阅:http://pandas.pydata.org/pandas-docs/stable/merging.html (13认同)
  • @MoustafaAAtta将迭代数据附加到数据帧的替代方法是什么? (2认同)
  • @MoustafaAAtta弗雷德在这篇文章中回答吗:/sf/ask/750117581/在这种观点上更好吗? (2认同)

Afs*_*iri 106

如果您想从一开始就拥有列名,请使用以下方法:

import pandas as pd

col_names =  ['A', 'B', 'C']
my_df  = pd.DataFrame(columns = col_names)
my_df
Run Code Online (Sandbox Code Playgroud)

如果要向数据帧添加记录,最好使用:

my_df.loc[len(my_df)] = [2, 4, 5]
Run Code Online (Sandbox Code Playgroud)

您可能还想传递字典:

my_dic = {'A':2, 'B':4, 'C':5}
my_df.loc[len(my_df)] = my_dic 
Run Code Online (Sandbox Code Playgroud)

但是,如果要将另一个数据帧添加到my_df,请执行以下操作:

col_names =  ['A', 'B', 'C']
my_df2  = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)
Run Code Online (Sandbox Code Playgroud)

如果要在循环内添加行,请考虑性能问题;
对于大约前1000条记录,"my_df.loc"性能更好,并且通过增加循环中的记录数逐渐变慢.

如果你计划在一个大循环内(比如10M记录左右)
那么你最好使用这两者的混合物; 使用iloc填充数据帧,直到大小达到1000,然后将其附加到原始数据帧,并清空临时数据帧.这会使你的表现提高大约10倍


cs9*_*s95 68

创建数据框的正确方法

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

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

这是我的建议:等待直到您确定拥有所有需要使用的数据。使用列表收集数据,然后在准备好时初始化DataFrame。

data = []
for a, b, c in some_function_that_yields_data():
    data.append([a, b, c])

df = pd.DataFrame(data, columns=['A', 'B', 'C'])
Run Code Online (Sandbox Code Playgroud)

一次添加到列表并创建一个DataFrame总是比创建一个空的DataFrame(或NaN之一)便宜,一次又一次地添加到列表中总是便宜的列表还占用较少的内存,并且是用于,附加和删除(如果需要)的较轻的数据结构

此方法的另一个优点是dtypes可以自动推断(而不是分配object给所有对象)。

最后一个优点是为您的数据自动创建了aRangeIndex,因此不必担心(只需查看下面的劣势appendloc方法,您将在两种方法中看到需要正确处理索引的元素)。


你不应该做的事情

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)
Run Code Online (Sandbox Code Playgroud)

内存重新分配给每一个appendconcat你有操作。再加上一个循环,就可以进行二次复杂度运算。从df.append文档页面

迭代地将行添加到DataFrame可能比单个连接更多地占用大量计算资源。更好的解决方案是将这些行添加到列表中,然后一次将列表与原始DataFrame连接起来。

与之相关的另一个错误df.append是用户倾向于忘记append不是就地函数,因此必须将结果分配回去。您还必须担心dtypes:

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
Run Code Online (Sandbox Code Playgroud)

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

df.infer_objects().dtypes
A      int64
B    float64
C     object
dtype: object
Run Code Online (Sandbox Code Playgroud)

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]
Run Code Online (Sandbox Code Playgroud)

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

NaN的空数据框

然后,创建一个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
Run Code Online (Sandbox Code Playgroud)

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

df.dtypes
A    object  # you DON'T want this
B    object
C    object
dtype: object
Run Code Online (Sandbox Code Playgroud)

如上所述,追加仍然存在所有问题。

for i, (a, b, c) in enumerate(some_function_that_yields_data()):
    df.iloc[i] = [a, b, c]
Run Code Online (Sandbox Code Playgroud)

证明在布丁里

对这些方法进行计时是最快的方法,以了解它们在内存和实用性方面的差异。

在此处输入图片说明

基准测试代码供参考。

  • 这在文档中是字面意思。“迭代地将行追加到 DataFrame 中可能比单个连接的计算密集度更高。更好的解决方案是将这些行追加到列表中,然后将该列表与原始 DataFrame 一次性连接起来。” https://pandas.pydata.org/pandas-docs/version/0.21/ generated/pandas.DataFrame.append.html (15认同)
  • 需要提高一百万倍。永远不要增加数据框! (7认同)
  • 列表附加应该是此类问题的最佳方法 (5认同)
  • @ user3293236太可惜了,每次您回答一个旧问题时,您都必须从头开始;) (3认同)
  • @Confounded这是一个与此处提出的问题不同的问题,但一次将一列分配给空数据框应该可以。连续追加行时会出现问题。 (3认同)
  • 惊人的答案! (3认同)
  • 这是我最讨厌的事情之一。很多次,您看到的只是票数很少而从未被接受的情况。我想念带有=。([])的代码来创建一个空的熊猫数据框。赞成这个答案。很好的解释,@ cs95! (2认同)
  • 另外“注意值得注意的是,concat()(因此append())会生成数据的完整副本,并且不断重用此函数可能会造成显着的性能影响。如果您需要在多个数据集上使用该操作,使用列表理解。” https://pandas.pydata.org/pandas-docs/stable/user_guide/merging.html#concatenating-objects (2认同)
  • 那么,当我的数据“进来”时,1d 一次列出一个数据,每个数据代表数据框中的一列,我该怎么办?在转换为数据框之前如何将它们附加在一起?似乎“list1.apped(list2)”将一个列表插入另一个列表中,而不是添加一列。谢谢 (2认同)