【问题标题】:Insert a row to pandas dataframe向熊猫数据框插入一行
【发布时间】:2021-10-06 21:10:25
【问题描述】:

我有一个数据框:

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() 函数,但找不到正确的方法。

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

【问题讨论】:

  • 请注意,最好使用s1.values 而不是list(s1),因为您将使用list(s1) 创建一个全新的列表。
  • 我不明白为什么每个人都那么喜欢熊猫,而本应如此简单的事情却如此令人头疼且如此缓慢。

标签: python pandas dataframe insert


【解决方案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 文档Indexing: Setting with enlargement

【讨论】:

  • 如果你不想设置放大,而是插入数据框,看看stackoverflow.com/questions/15888648/…
  • 移动索引替代:df.sort().reset_index(drop=True)
  • df.sort 已弃用,请使用 df.sort_index()
  • @Piotr - 这很好用,但是当您想从数据框中复制一行(例如df.loc[-1] = df.iloc[[0]])并插入它时会发生什么?该框架带有一个添加的索引列,给出错误ValueError: cannot set a row with mismatched columns(参见stackoverflow.com/questions/47340571/…
  • 我认为 df.loc[-1] = [2, 3, 4] # adding a row 有点误导,因为 -1 不是最后一行/元素,因为它是 Python 数组。
【解决方案2】:

不确定您是如何调用concat() 的,但只要两个对象属于同一类型,它就应该可以工作。也许问题是您需要将第二个向量转换为数据框?使用您定义的 df 对我有用:

df2 = pd.DataFrame([[2,3,4]], columns=['A','B','C'])
pd.concat([df2, df])

【讨论】:

  • 最佳答案 ^ :)
  • 不应该稍微修改一下才能正确完成这项工作吗?我认为@mgilbert 的代码在 0 处插入行,但我们最终得到两行索引为 0。我认为需要修改第二行,使其看起来像 pd.concat([df2, df]).reset_index(drop =真)
【解决方案3】:

实现这一目标的一种方法是

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

【讨论】:

  • 这是一个很好的解决方案,我试图将系列插入数据框。目前对我来说已经足够了。
  • 我最喜欢最后一个选项。这真的符合我真正想做的事情。谢谢@FooBar!
【解决方案4】:

我整理了一个简短的函数,可以在插入行时提供更多的灵活性:

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)

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

【讨论】:

    【解决方案5】:

    在熊猫DataFrame中添加一行非常简单:

    1. 创建一个与Dataframe 具有相同列名的常规 Python 字典;

    2. 使用pandas.append() 方法并传入您的字典名称,其中.append() 是DataFrame 实例上的方法;

    3. 在您的字典名称后添加ignore_index=True

    【讨论】:

    • 这可能是最可取的选择(大约 2020 年)。
    • 这个函数没有inplace参数,所以:df = df.append(your_dict, ignore_index=True)
    【解决方案6】:

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

    比较使用dictlist 的性能,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

    %%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 次循环)

    【讨论】:

      【解决方案7】:

      我们可以使用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))
      
          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 告诉函数您要放置新值的位置/索引。

      【讨论】:

        【解决方案8】:

        这可能看起来过于简单,但令人难以置信的是没有内置简单的插入新行函数。我已经阅读了很多关于将新 df 附加到原始文件的内容,但我想知道这是否会更快。

        df.loc[0] = [row1data, blah...]
        i = len(df) + 1
        df.loc[i] = [row2data, blah...]
        

        【讨论】:

        • 如您的代码所示,您的意思是“附加一个新的 df”还是“附加一个新行”?
        • 对不起,我的句子不清楚。我读过其他人的解决方案,它们只用一行连接/附加一个全新的数据框。但在我的解决方案中,它只是现有数据框中的一行,无需创建额外的数据框
        【解决方案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)
        

        【讨论】:

        • 为什么说这是最好的方法?
        • 那么最好提供证据来支持这种说法,你有时间吗?
        • 可以使用pd.isna来避免导入numpy
        【解决方案10】:

        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 s ± 127 ms 每个循环(平均值 ± 标准偏差,7 次运行,每次 1 个循环)

        【讨论】:

          【解决方案11】:

          您可以简单地将行追加到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)
          

          【讨论】:

            【解决方案12】:

            我突然想到 T 属性 可能是一个有效的选择。 转置,可以摆脱@flow2k提到的有点误导的df.loc[-1] = [2, 3, 4],它适用于更普遍的情况,比如你想在任意行之前插入[2, 3, 4],这对于@来说很难987654323@,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】:

              如下例:

              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
              

              【讨论】:

                【解决方案14】:

                在 pandas 数据框中添加一行的最简单方法是:

                DataFrame.loc[ location of insertion ]= list( )
                

                例子:

                DF.loc[ 9 ] = [ ´Pepe’ , 33, ´Japan’ ]
                

                注意:列表的长度应与数据框的长度相匹配。

                【讨论】:

                  猜你喜欢
                  • 2019-05-01
                  • 2019-01-25
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2021-06-04
                  • 1970-01-01
                  相关资源
                  最近更新 更多