我有一个数据框架:

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

   A  B  C
0  5  6  7
1  7  8  9

[2 rows x 3 columns]

并且我需要添加第一行[2,3,4],得到:

   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

我尝试过append()和concat()函数,但找不到正确的方法。

如何添加/插入系列数据帧?


当前回答

实现这一点的一种方法是

>>> pd.DataFrame(np.array([[2, 3, 4]]), columns=['A', 'B', 'C']).append(df, ignore_index=True)
Out[330]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

通常,添加数据框架是最简单的,而不是序列。在您的例子中,由于您希望新行位于“顶部”(带有起始id),并且没有pd.prepend()函数,因此我首先创建新的数据框架,然后添加旧的数据框架。

Ignore_index将忽略数据帧中旧的正在进行的索引,并确保第一行实际上从索引1开始,而不是从索引0重新开始。

典型免责声明:Cetero censeo…追加行是一种非常低效的操作。如果你关心性能,并且能够以某种方式确保首先创建一个具有正确(更长)索引的数据帧,然后将额外的行插入到数据帧中,那么你一定要这样做。看到的:

>>> index = np.array([0, 1, 2])
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[0:1] = [list(s1), list(s2)]
>>> df2
Out[336]: 
     A    B    C
0    5    6    7
1    7    8    9
2  NaN  NaN  NaN
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[1:] = [list(s1), list(s2)]

到目前为止,我们有你的df:

>>> df2
Out[339]: 
     A    B    C
0  NaN  NaN  NaN
1    5    6    7
2    7    8    9

但是现在您可以像下面那样轻松地插入行。由于空间是预先分配的,因此效率更高。

>>> df2.loc[0] = np.array([2, 3, 4])
>>> df2
Out[341]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

其他回答

我把一个简短的函数放在一起,在插入一行时允许更多的灵活性:

def insert_row(idx, df, df_insert):
    dfA = df.iloc[:idx, ]
    dfB = df.iloc[idx:, ]

    df = dfA.append(df_insert).append(dfB).reset_index(drop = True)

    return df

可以进一步缩写为:

def insert_row(idx, df, df_insert):
    return df.iloc[:idx, ].append(df_insert).append(df.iloc[idx:, ]).reset_index(drop = True)

然后你可以使用如下语句:

df = insert_row(2, df, df_new)

其中2是df中要插入df_new的索引位置。

只需将row赋值给一个特定的索引,使用loc:

 df.loc[-1] = [2, 3, 4]  # adding a row
 df.index = df.index + 1  # shifting index
 df = df.sort_index()  # sorting by index

你会得到:

    A  B  C
 0  2  3  4
 1  5  6  7
 2  7  8  9

参见Pandas文档索引:放大设置。

测试了几个答案,很明显使用pd.concat()对于大数据帧更有效。

比较使用dict和list的性能,list的效率更高,但对于小数据帧,使用dict应该没有问题,而且可读性更好。


1st - pd.concat() +列表

%%timeit
df = pd.DataFrame(columns=['a', 'b'])
for i in range(10000):
    df = pd.concat([pd.DataFrame([[1,2]], columns=df.columns), df], ignore_index=True)

每循环4.88 s±47.1 ms(平均±标准值7次运行,每循环1次)

2nd - pd.append() + dict

%%timeit

df = pd.DataFrame(columns=['a', 'b'])
for i in range(10000):
    df = df.append({'a': 1, 'b': 2}, ignore_index=True)

每循环10.2 s±41.4 ms(平均±标准值7次运行,每循环1次)

第三- pd.DataFrame()。Loc +索引操作

%%timeit
df = pd.DataFrame(columns=['a','b'])
for i in range(10000):
    df.loc[-1] = [1,2]
    df.index = df.index + 1
    df = df.sort_index()

每循环17.5 s±37.3 ms(平均±标准值7次运行,每循环1次)

实现这一点的一种方法是

>>> pd.DataFrame(np.array([[2, 3, 4]]), columns=['A', 'B', 'C']).append(df, ignore_index=True)
Out[330]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

通常,添加数据框架是最简单的,而不是序列。在您的例子中,由于您希望新行位于“顶部”(带有起始id),并且没有pd.prepend()函数,因此我首先创建新的数据框架,然后添加旧的数据框架。

Ignore_index将忽略数据帧中旧的正在进行的索引,并确保第一行实际上从索引1开始,而不是从索引0重新开始。

典型免责声明:Cetero censeo…追加行是一种非常低效的操作。如果你关心性能,并且能够以某种方式确保首先创建一个具有正确(更长)索引的数据帧,然后将额外的行插入到数据帧中,那么你一定要这样做。看到的:

>>> index = np.array([0, 1, 2])
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[0:1] = [list(s1), list(s2)]
>>> df2
Out[336]: 
     A    B    C
0    5    6    7
1    7    8    9
2  NaN  NaN  NaN
>>> df2 = pd.DataFrame(columns=['A', 'B', 'C'], index=index)
>>> df2.loc[1:] = [list(s1), list(s2)]

到目前为止,我们有你的df:

>>> df2
Out[339]: 
     A    B    C
0  NaN  NaN  NaN
1    5    6    7
2    7    8    9

但是现在您可以像下面那样轻松地插入行。由于空间是预先分配的,因此效率更高。

>>> df2.loc[0] = np.array([2, 3, 4])
>>> df2
Out[341]: 
   A  B  C
0  2  3  4
1  5  6  7
2  7  8  9

对于那些想要连接前一个数据帧的行,使用双括号([[…]])作为iloc。

s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])

df = pd.DataFrame([list(s1), list(s2)],  columns =  ["A", "B", "C"])

#   A   B   C
# 0 5   6   7
# 1 7   8   9

pd.concat((df.iloc[[0]],  # [[...]] used to slice DataFrame as DataFrame
           df), ignore_index=True)

#   A   B   C
# 0 5   6   7
# 1 5   6   7
# 2 7   8   9

若要复制或复制任意时间,请与星号组合。

pd.concat((df.iloc[[0]],
           df,
           *[df.iloc[[1]]] * 4), ignore_index=True)

#   A   B   C
# 0 5   6   7
# 1 7   8   9
# 2 7   8   9
# 3 7   8   9
# 4 7   8   9