当前位置: 首页 > 面试题库 >

我能在熊猫身上表演动态累加吗?

商冠玉
2023-03-14
问题内容

如果我有以下数据帧,派生如下:df=pd.数据帧(np.随机.随机(0,10,大小=(10,1)))

    0
0   0
1   2
2   8
3   1
4   0
5   0
6   7
7   0
8   2
9   2

有没有一种有效的方法“cumsum”行有限制并且每次都有这个限制
已到达,开始新的“cumsum”。在达到每个极限后(不管有多少
rows),则创建一个包含总累计和的行。
下面我创建了一个这样做的函数的例子,但是它非常
速度很慢,尤其是当数据帧变得非常大时。我不喜欢这样,我的朋友
函数是循环的,我正在寻找一种方法使它更快(我猜
没有环路)。

def foo(df, max_value):
    last_value = 0
    storage = []
    for index, row in df.iterrows():
        this_value = np.nansum([row[0], last_value])
        if this_value >= max_value:
            storage.append((index, this_value))
            this_value = 0
        last_value = this_value
    return storage

If you rum my function like so: foo(df, 5) In in the above context, it
returns:

   0
2  10
6  8

问题答案:

循环无法避免,但可以使用“numba”的“njit”并行化:

from numba import njit, prange

@njit
def dynamic_cumsum(seq, index, max_value):
    cumsum = []
    running = 0
    for i in prange(len(seq)):
        if running > max_value:
            cumsum.append([index[i], running])
            running = 0
        running += seq[i] 
    cumsum.append([index[-1], running])

    return cumsum

The index is required here, assuming your index is not numeric/monotonically
increasing.

%timeit foo(df, 5)
1.24 ms ± 41.4 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit dynamic_cumsum(df.iloc(axis=1)[0].values, df.index.values, 5)
77.2 µs ± 4.01 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

If the index is of Int64Index type, you can shorten this to:

@njit
def dynamic_cumsum2(seq, max_value):
    cumsum = []
    running = 0
    for i in prange(len(seq)):
        if running > max_value:
            cumsum.append([i, running])
            running = 0
        running += seq[i] 
    cumsum.append([i, running])

    return cumsum

lst = dynamic_cumsum2(df.iloc(axis=1)[0].values, 5)
pd.DataFrame(lst, columns=['A', 'B']).set_index('A')

    B
A    
3  10
7   8
9   4



%timeit foo(df, 5)
1.23 ms ± 30.6 µs per loop (mean ± std. dev. of 7 runs, 1000 loops each)

%timeit dynamic_cumsum2(df.iloc(axis=1)[0].values, 5)
71.4 µs ± 1.4 µs per loop (mean ± std. dev. of 7 runs, 10000 loops each)

njit Functions Performance

perfplot.show(
    setup=lambda n: pd.DataFrame(np.random.randint(0, 10, size=(n, 1))),
    kernels=[
        lambda df: list(cumsum_limit_nb(df.iloc[:, 0].values, 5)),
        lambda df: dynamic_cumsum2(df.iloc[:, 0].values, 5)
    ],
    labels=['cumsum_limit_nb', 'dynamic_cumsum2'],
    n_range=[2**k for k in range(0, 17)],
    xlabel='N',
    logx=True,
    logy=True,
    equality_check=None # TODO - update when @jpp adds in the final `yield`
)

log-log图显示,生成器函数越大,速度越快输入:
一种可能的解释是,随着N的增加,附加到
“dynamic_cumsum2”中不断增长的列表变得突出。Whilecumsum\u limit\u nb
只需要“屈服”。



 类似资料:
  • 我今天观察到,选择两列或更多列的数据帧可能比只选择一列慢得多。 如果我使用loc或iloc选择多个列,并且我使用list传递列名或索引,那么与使用iloc的单个列或多个列选择相比,性能会下降100倍(但没有传递列表) 示例: 单列选择: 两列选择: 只有此选择的工作方式与预期相同:[编辑] 机制上的差异是什么?为什么差异如此之大? [编辑]:正如@run-out指出的,pd。系列似乎比pd处理得快

  • ...使用进行编码。使用的原因是我想要自动化许多工作流,因此动态地创建它们对我会很有用。 我的两个输入数据流是: 我试图更好地理解的和参数,以确定如何最好地解决我的问题。我已经看过了文件,但我并不清楚其中的区别。 应使用哪些参数来确保代码以最大性能工作? 是否有方法将表达式的结果赋回到? 另外,为了使事情更加复杂,如何将作为字符串表达式中的参数传递?

  • 处理后的文件不干净。csv 有了密码 我把输出弄干净了。csv 在引用所有内容的地方,尽管我特别将列的类型设置为浮动,并将其作为参数设置为,但我要求仅引用非数字字段。 如何引用字符串并保持数字不被引用? 许多讨论(例如:1、2、3、4)建议应该可以。 使用和,均来自。 议论 瓦伦蒂诺的回答指出了问题所在,但我知道除了 避免引入少量的和。

  • 问题内容: Pandas确实很棒,但令我惊讶的是,从Pandas.DataFrame检索值的效率低下。在下面的玩具示例中,即使DataFrame.iloc方法也比字典慢100倍以上。 问题:这里的教训仅仅是字典是查找价值的更好方法吗?是的,我知道那正是他们的目的。但是我只是想知道是否缺少有关DataFrame查找性能的信息。 我意识到这个问题比“提问”更“有趣”,但是我会接受一个提供洞察力或观点的

  • 问题内容: 给定两个数据框 我想使用对一列或多列进行算术运算pd.eval。具体来说,我想移植以下代码: …使用进行编码eval。使用的原因eval是我想自动执行许多工作流程,因此动态创建它们对我很有用。 我试图更好地理解和参数,以确定如何最好地解决我的问题。我已经浏览了文档,但是对我而言,区别并不明显。 应该使用什么参数来确保我的代码以最高性能工作? 有没有一种方法可以将表达式的结果赋值给df2

  • 问题内容: 我的pandas df包含一个包含逗号分隔特征的列,如下所示: 我想将此列拆分为多个虚拟变量列,但无法弄清楚如何启动此过程。我正在尝试像这样拆分列: 但是,这不起作用,因为描述中间有逗号。取而代之的是,我需要根据逗号的正则表达式匹配,后跟一个空格和一个大写字母进行拆分。str.split可以使用正则表达式吗?如果是这样,这是怎么做的? 我认为正则表达式可以满足我的需求: 问题答案: 是