我如何创建一个空DataFrame,然后添加行,一个接一个?

我创建了一个空DataFrame:

df = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))

然后我可以在最后添加一个新行,并填充一个字段:

df = df._set_value(index=len(df), col='qty1', value=10.0)

它一次只适用于一个领域。向df中添加新行有什么更好的方法?


当前回答

initial_data = {'lib': np.array([1,2,3,4]), 'qty1': [1,2,3,4], 'qty2': [1,2,3,4]}

df = pd.DataFrame(initial_data)

df

lib    qty1    qty2
0    1    1    1
1    2    2    2
2    3    3    3
3    4    4    4

val_1 = [10]
val_2 = [14]
val_3 = [20]

df.append(pd.DataFrame({'lib': val_1, 'qty1': val_2, 'qty2': val_3}))

lib    qty1    qty2
0    1    1    1
1    2    2    2
2    3    3    3
3    4    4    4
0    10    14    20

可以使用for循环遍历值,也可以添加值数组。

val_1 = [10, 11, 12, 13]
val_2 = [14, 15, 16, 17]
val_3 = [20, 21, 22, 43]

df.append(pd.DataFrame({'lib': val_1, 'qty1': val_2, 'qty2': val_3}))

lib    qty1    qty2
0    1    1    1
1    2    2    2
2    3    3    3
3    4    4    4
0    10    14    20
1    11    15    21
2    12    16    22
3    13    17    43

其他回答

与ShikharDua的答案(基于行)中的字典列表不同,我们也可以将我们的表表示为一个列表字典(基于列),其中每个列表按行顺序存储一列,前提是我们事先知道我们的列。最后,我们构造一次DataFrame。

在这两种情况下,字典键始终是列名。行顺序隐式存储为列表中的order。对于c列和n行,它使用一个c个字典列表,而不是一个n个字典列表。字典列表方法让每个字典冗余地存储所有键,并且需要为每一行创建一个新字典。这里我们只追加到列表中,这总体上是相同的时间复杂度(向列表和字典中添加条目都是平摊常数时间),但由于操作简单,开销可能更小。

# Current data
data = {"Animal":["cow", "horse"], "Color":["blue", "red"]}

# Adding a new row (be careful to ensure every column gets another value)
data["Animal"].append("mouse")
data["Color"].append("black")

# At the end, construct our DataFrame
df = pd.DataFrame(data)
#   Animal  Color
# 0    cow   blue
# 1  horse    red
# 2  mouse  black

如果你的Dataframe中的所有数据都有相同的dtype,你可以使用NumPy数组。您可以直接将行写入预定义数组,并在最后将其转换为数据框架。 它似乎比转换字典列表还要快。

import pandas as pd
import numpy as np
from string import ascii_uppercase

startTime = time.perf_counter()
numcols, numrows = 5, 10000
npdf = np.ones((numrows, numcols))
for row in range(numrows):
    npdf[row, 0:] = np.random.randint(0, 100, (1, numcols))
df5 = pd.DataFrame(npdf, columns=list(ascii_uppercase[:numcols]))
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df5.shape)

你可以使用pandas.concat()。有关详细信息和示例,请参见合并、连接和连接。

例如:

def append_row(df, row):
    return pd.concat([
                df, 
                pd.DataFrame([row], columns=row.index)]
           ).reset_index(drop=True)

df = pd.DataFrame(columns=('lib', 'qty1', 'qty2'))
new_row = pd.Series({'lib':'A', 'qty1':1, 'qty2': 2})

df = append_row(df, new_row)

在向dataframe添加大量行的情况下,我对性能感兴趣。所以我尝试了四种最流行的方法,并检查了它们的速度。

性能

使用.append (NPE的答案) 使用。loc (fred的回答) 使用.loc预分配(FooBar的答案) 使用dict并最终创建DataFrame (ShikharDua的回答)

运行时结果(秒):

Approach 1000 rows 5000 rows 10 000 rows
.append 0.69 3.39 6.78
.loc without prealloc 0.74 3.90 8.35
.loc with prealloc 0.24 2.58 8.70
dict 0.012 0.046 0.084

所以我自己用了加法法。


代码:

import pandas as pd
import numpy as np
import time

del df1, df2, df3, df4
numOfRows = 1000
# append
startTime = time.perf_counter()
df1 = pd.DataFrame(np.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
for i in range( 1,numOfRows-4):
    df1 = df1.append( dict( (a,np.random.randint(100)) for a in ['A','B','C','D','E']), ignore_index=True)
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df1.shape)

# .loc w/o prealloc
startTime = time.perf_counter()
df2 = pd.DataFrame(np.random.randint(100, size=(5,5)), columns=['A', 'B', 'C', 'D', 'E'])
for i in range( 1,numOfRows):
    df2.loc[i]  = np.random.randint(100, size=(1,5))[0]
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df2.shape)

# .loc with prealloc
df3 = pd.DataFrame(index=np.arange(0, numOfRows), columns=['A', 'B', 'C', 'D', 'E'] )
startTime = time.perf_counter()
for i in range( 1,numOfRows):
    df3.loc[i]  = np.random.randint(100, size=(1,5))[0]
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df3.shape)

# dict
startTime = time.perf_counter()
row_list = []
for i in range (0,5):
    row_list.append(dict( (a,np.random.randint(100)) for a in ['A','B','C','D','E']))
for i in range( 1,numOfRows-4):
    dict1 = dict( (a,np.random.randint(100)) for a in ['A','B','C','D','E'])
    row_list.append(dict1)

df4 = pd.DataFrame(row_list, columns=['A','B','C','D','E'])
print('Elapsed time: {:6.3f} seconds for {:d} rows'.format(time.perf_counter() - startTime, numOfRows))
print(df4.shape)

附注:我相信我的实现并不完美,也许还有一些优化可以做。

你只需要loc[df]。形状[0]]或loc[len(df)]


# Assuming your df has 4 columns (str, int, str, bool)
df.loc[df.shape[0]] = ['col1Value', 100, 'col3Value', False] 

or

df.loc[len(df)] = ['col1Value', 100, 'col3Value', False]