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

时间:2012-12-09 02:50:38

标签: 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

6 个答案:

答案 0 :(得分:252)

以下是一些建议:

使用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

答案 1 :(得分:119)

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

在此示例中,我使用this pandas doc创建新数据框,然后使用append使用oldDF中的数据写入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 
  • 如果我不得不继续将新数据添加到此newDF中 一个oldDF,我只是使用for循环来迭代 pandas.DataFrame.append()

答案 2 :(得分:87)

如果您想从头开始使用列名,请使用以下方法:

import pandas as pd

col_names =  ['A', 'B', 'C']
my_df  = pd.DataFrame(columns = col_names)
my_df

如果您想向数据框添加记录,最好使用:

my_df.loc[len(my_df)] = [2, 4, 5]

您也可能想要传递字典:

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

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

col_names =  ['A', 'B', 'C']
my_df2  = pd.DataFrame(columns = col_names)
my_df = my_df.append(my_df2)

如果要在循环中添加行,请考虑性能问题:
对于前1000个记录,“my_df.loc”性能更好,但通过增加循环中的记录数逐渐变慢。

如果你打算在一个大循环中做这些事情(比如10M记录左右): 你最好混合使用这两个; 使用iloc填充数据帧,直到大小达到1000,然后将其附加到原始数据帧,并清空临时数据帧。 这会使你的表现提高大约10倍。

答案 3 :(得分:10)

创建数据框架的正确方法

这里的大多数答案将告诉您如何创建一个空的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'])

与创建一个空的DataFrame(或NaN之一)并一遍又一遍地添加到列表中相比,一次性添加到列表中并始终创建一个DataFrame总是更便宜。 列表还占用较少的内存,并且是用于处理,添加和删除(如果需要)的轻得多的数据结构。

此方法的另一个优势是可以自动推断 dtypes (而不是为所有变量分配object)。

最后一个优点是系统会自动为您的数据创建一个RangeIndex ,因此您不必担心(查看较差的append和下面的loc方法中,您会在两种方法中看到需要适当处理索引的元素。


你不应该做的事

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操作重新分配内存。再加上一个循环,您将具有二次复杂度运算。如果您不相信我,请阅读其他答案下的一些评论。

  

以我的经验,创建一个填充了必要大小的数据框   使用NaN,然后​​填充值比   创建一个数据框[..]并   在循环的每一圈附加一列。我的意思是循环遍历列名的df[col_name] = pandas.Series([...])。在里面   前一种情况,不仅内存分配需要时间,而且需要更换   具有新值的NaN似乎非常慢。 – deeenes

  

请注意,append(和类似的concat)复制了完整的数据集   每次都将其复制到新对象,因此可以迭代和附加   将对性能造成重大影响。 – MoustafaAAtta

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

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

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的空数据框

然后,创建一个NaN的数据框,以及与此相关的所有警告。

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

追加仍然具有上述方法中的所有问题。

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

证明在布丁中

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

enter image description here

Benchmarking code for reference.

答案 4 :(得分:0)

这是我用循环从多个列表制作动态数据框的方法

x = [1,2,3,4,5,6,7,8]
y = [22,12,34,22,65,24,12,11]
z = ['as','ss','wa', 'ss','er','fd','ga','mf']
names = ['Bob', 'Liz', 'chop']

一个循环

def dataF(x,y,z,names):
    res = []

    for t in zip(x,y,z):
        res.append(t)

    return pd.DataFrame(res,columns=names)

结果

dataF(x,y,z,names)

enter image description here

答案 5 :(得分:-1)

假设一个数据帧有19行

index=range(0,19)
index

columns=['A']
test = pd.DataFrame(index=index, columns=columns)

将A列保留为常量

test['A']=10

将第b列保留为循环给出的变量

for x in range(0,19):
    test.loc[[x], 'b'] = pd.Series([x], index = [x])

您可以将pd.Series([x], index = [x])中的第一个x替换为任何值