向 pandas 数据框中插入一行
- 2025-01-21 09:01:00
- admin 原创
- 77
问题描述:
我有一个数据框:
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()
这些功能,但找不到正确的方法。
如何向数据框添加/插入系列?
解决方案 1:
只需将行分配给特定索引,使用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 文档索引:放大设置。
解决方案 2:
测试几个答案后发现,pd.concat()
对于大型数据框来说,使用更有效。
dict
比较使用和的性能list
,list
效率更高,但对于小型数据框,使用dict
应该没有问题,而且可读性更强。
第一名pd.concat() + list
%%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 秒± 47.1 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)
第二 - pd.append() + dict
[从v2.0.0开始删除]
%%timeit
df = pd.DataFrame(columns=['a', 'b'])
for i in range(10000):
df = df.append({'a': 1, 'b': 2}, ignore_index=True)
每循环10.2 秒± 41.4 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)
第三名pd.DataFrame().loc + index operations
%%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 秒± 37.3 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)
解决方案 3:
不确定您是如何调用的concat()
,但只要两个对象属于同一类型,它就应该有效。也许问题是您需要将第二个向量转换为数据框?使用您定义的 df 对我来说有效:
df2 = pd.DataFrame([[2,3,4]], columns=['A','B','C'])
pd.concat([df2, df])
解决方案 4:
实现此目的的一种方法是
>>> 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
解决方案 5:
我整理了一个简短的函数,使得插入行时更加灵活:
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`
解决方案 6:
我们可以使用numpy.insert
。这样做的好处是灵活。你只需要指定要插入到的索引即可。
s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])
df = pd.DataFrame([list(s1), list(s2)], columns = ["A", "B", "C"])
pd.DataFrame(np.insert(df.values, 0, values=[2, 3, 4], axis=0), columns=df.columns)
0 1 2
0 2 3 4
1 5 6 7
2 7 8 9
对于np.insert(df.values, 0, values=[2, 3, 4], axis=0)
,0 告诉函数您想要放置新值的位置/索引。
解决方案 7:
在 pandas 中添加一行非常简单DataFrame
:
创建一个常规 Python 字典,其列名与您的相同
Dataframe
;使用
pandas.append()
方法并传入你的字典名称,其中.append()
是 DataFrame 实例上的方法;ignore_index=True
在词典名称后立即添加。
解决方案 8:
这可能看起来过于简单,但令人难以置信的是,一个简单的插入新行功能没有内置。我已经阅读了很多关于将新的 df 附加到原始内容的文章,但我想知道这是否会更快。
df.loc[0] = [row1data, blah...]
i = len(df) + 1
df.loc[i] = [row2data, blah...]
解决方案 9:
以下是在不进行排序和重新设置索引的情况下将行插入到 pandas 数据框中的最佳方法:
import pandas as pd
df = pd.DataFrame(columns=['a','b','c'])
def insert(df, row):
insert_loc = df.index.max()
if pd.isna(insert_loc):
df.loc[0] = row
else:
df.loc[insert_loc + 1] = row
insert(df,[2,3,4])
insert(df,[8,9,0])
print(df)
解决方案 10:
创建具有列名的空 df:
df = pd.DataFrame(columns = ["A", "B", "C"])
插入新行:
df.loc[len(df.index)] = [2, 3, 4]
df.loc[len(df.index)] = [5, 6, 7]
df.loc[len(df.index)] = [7, 8, 9]
解决方案 11:
concat()
似乎比最后一行插入和重新索引要快一点。如果有人想知道两种顶级方法的速度:
In [x]: %%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.1 秒 ± 705 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)
In [y]: %%timeit
...: df = pd.DataFrame(columns=['a', 'b'])
...: for i in range(10000):
...: df = pd.concat([pd.DataFrame([[1,2]], columns=df.columns), df])
每循环6.53秒 ± 127 毫秒(7 次运行的平均值 ± 标准差,每次 1 个循环)
解决方案 12:
我突然想到,也许T 属性是一个有效的选择。Transpose可以摆脱 @flow2k 提到的有些误导,df.loc[-1] = [2, 3, 4]
并且它适用于更通用的情况,例如您想要 [2, 3, 4]
在任意行之前插入,这对于 来说很难concat()
实现append()
。而且没有必要费心定义和调试函数。
a = df.T
a.insert(0,'anyName',value=[2,3,4])
# just give insert() any column name you want, we'll rename it.
a.rename(columns=dict(zip(a.columns,[i for i in range(a.shape[1])])),inplace=True)
# set inplace to a Boolean as you need.
df=a.T
df
A B C
0 2 3 4
1 5 6 7
2 7 8 9
我想这可以部分解释@MattCochrane 关于为什么 pandas 没有像 insert() 那样插入行的方法的抱怨。
解决方案 13:
对于那些想要从前一个数据框中连接一行的人,请使用双括号([[...]]
)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
解决方案 14:
假设索引是一个默认索引,其整数值从 0 开始:
import pandas as pd
data = [[5, 6, 7], [7, 8, 9]]
df = pd.DataFrame(data, columns=list('ABC'))
row = [2, 3, 4]
# Inset new row
df.loc[-1] = row
df = df.sort_index()
df.index = range(len(df))
print(df)
调整df.loc[-1]
原始索引中的任意位置。
A B C
0 2 3 4
1 5 6 7
2 7 8 9
解决方案 15:
您可以简单地将行附加到 DataFrame 的末尾,然后调整索引。
例如:
df = df.append(pd.DataFrame([[2,3,4]],columns=df.columns),ignore_index=True)
df.index = (df.index + 1) % len(df)
df = df.sort_index()
或者使用concat
如下方式:
df = pd.concat([pd.DataFrame([[1,2,3,4,5,6]],columns=df.columns),df],ignore_index=True)
解决方案 16:
按照下面的例子操作:
a_row = pd.Series([1, 2])
df = pd.DataFrame([[3, 4], [5, 6]])
row_df = pd.DataFrame([a_row])
df = pd.concat([row_df, df], ignore_index=True)
结果是:
0 1
0 1 2
1 3 4
2 5 6
解决方案 17:
s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])
df = pd.DataFrame([list(s1), list(s2)], columns = ["A", "B", "C"])
要在任意位置插入新行,您可以指定行位置:row_pos = -1 表示插入在顶部,或者 row_pos = 0.5 表示插入在第 0 行和第 1 行之间。
row_pos = -1
insert_row = [2,3,4]
df.loc[row_pos] = insert_row
df = df.sort_index()
df = df.reset_index(drop = True)
row_pos = -1
The outcome is:
A B C
0 2 3 4
1 5 6 7
2 7 8 9
row_pos = 0.5
The outcome is:
A B C
0 5 6 7
1 2 3 4
2 7 8 9
解决方案 18:
鉴于 pandas 的数据框的数据结构是一系列系列(每个系列是一列),因此可以方便地在任何位置插入一列。所以我想到的一个想法是先转置你的数据框,插入一列,然后再转置回去。你可能还需要重命名索引(行名),如下所示:
s1 = pd.Series([5, 6, 7])
s2 = pd.Series([7, 8, 9])
df = pd.DataFrame([list(s1), list(s2)], columns = ["A", "B", "C"])
df = df.transpose()
df.insert(0, 2, [2,3,4])
df = df.transpose()
df.index = [i for i in range(3)]
df
A B C
0 2 3 4
1 5 6 7
2 7 8 9
解决方案 19:
在 Pandas 数据框中添加一行的最简单方法是:
DataFrame.loc[ location of insertion ]= list( )
例子 :
DF.loc[ 9 ] = [ ´Pepe’ , 33, ´Japan’ ]
注意:列表的长度应该与数据框的长度相匹配。