【问题标题】:Pandas: efficiently inserting a large number of rowsPandas:有效地插入大量行
【发布时间】:2021-10-06 02:45:51
【问题描述】:

我有一个这种格式的大数据框,调用它df

index val1 val2
0 0.2 0.1
1 0.5 0.7
2 0.3 0.4

我要插入一行,请致电myrow

index val1 val2
-1 0.9 0.9

我希望在原始数据框中的每一行之后插入此行 3 次,即:

index val1 val2
0 0.2 0.1
-1 0.9 0.9
-1 0.9 0.9
-1 0.9 0.9
1 0.5 0.7
-1 0.9 0.9
-1 0.9 0.9
-1 0.9 0.9
2 0.3 0.4
-1 0.9 0.9
-1 0.9 0.9
-1 0.9 0.9

这很简单,有一点循环。 TLDR:如何更有效地做到这一点?

让我们创建一个重复行函数,并创建我们的一组 3 个重复:

import pandas as pd
import numpy as np

def repeat_rows(df, n):
    newdf = pd.DataFrame(np.repeat(df.values, n, axis=0))
    newdf.columns = df.columns
    return newdf

repeats = repeat_rows(myrow.to_frame().T, 3)

现在我们有了 3 次重复:

index val1 val2
-1 0.9 0.9
-1 0.9 0.9
-1 0.9 0.9

最后,我们可以遍历原来的df 的行,并将repeats 连接到该行,并将所有这些的结果连接在一起:

blocks = []
for _, row in df.iterrows():
    blocks.append(pd.concat([row.to_frame().T, repeats]))
result = pd.concat(blocks)

我们现在得到了想要的结果!

问题是,这很慢,我正在寻找更快的解决方案。

我猜一个更好的解决方案会遵循这种模式:

result = repeat_rows(df, 4)
result.loc[LAST_3_ROWS_IN_EACH_BLOCK_OF_4] = myrow

但是,我不确定如何进行这样的 loc 分配。 如何让我的解决方案更高效?

【问题讨论】:

  • 'index' 是您的实际数据帧索引,还是标有“索引”的列?
  • @ALollz 是一栏
  • 对于它的价值,在循环中使用df.locpd.concatdf.append 非常慢。您应该先尝试收集所有数据,然后再将其转换为 DataFrame。查看this answer 了解更多讨论和示例。

标签: python pandas dataframe performance numpy


【解决方案1】:

reset_index 这样df 就有一个简单的 RangeIndex。然后我们可以用平铺和重复进行数学运算,以创建一个索引,在排序时将在 DataFrame 的每一行之间放置 3 个myrow 行。最后删除这个Index 并恢复到正常的RangeIndex

样本数据

import pandas as pd
import numpy as np

myrow = pd.DataFrame({'index': [-1], 'val1': [0.9], 'val2': [0.9]})
df = pd.DataFrame({'index': [0,1,2],
                   'val1': [0.2, 0.5, 0.3],
                   'val2': [0.1, 0.7, 0.4]})

代码

# Ensure starting from a RangeIndex
df = df.reset_index(drop=True)

NR = 3  # Number of repeats

mr = pd.concat([myrow]*len(df)*NR, ignore_index=True)
mr.index = df.index.repeat(NR) + np.tile(np.arange(0, 1, 1/NR), len(df))

# `mr` second in the `concat` so rows go below
df = pd.concat([df, mr]).sort_index().reset_index(drop=True)

    index  val1  val2
0       0   0.2   0.1
1      -1   0.9   0.9
2      -1   0.9   0.9
3      -1   0.9   0.9
4       1   0.5   0.7
5      -1   0.9   0.9
6      -1   0.9   0.9
7      -1   0.9   0.9
8       2   0.3   0.4
9      -1   0.9   0.9
10     -1   0.9   0.9
11     -1   0.9   0.9

【讨论】:

    【解决方案2】:

    在我看来,您可能没有解决正确的问题。如果您告诉我们您这样做的实际目的可能会有所帮助!

    尽管如此 - 循环总是一个坏主意!

    这里有一些建议:Pandas - Interleave / Zip two DataFrames by row

    基本想法是创建一个包含额外行的表,然后将其与原始表连接:

    extra = pd.DataFrame(ROW.values.repeat(df.size), columns=ROW.columns)
    df = pd.concat(df, extra)
    

    最后排序以将所有内容按正确的顺序排列。为了使排序工作,您需要为每个表添加一个索引列 - 但这不应该 /too/ 棘手。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-08-17
      • 2013-03-25
      • 1970-01-01
      • 1970-01-01
      • 2012-04-15
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多