将每列中的值分配为该列的总和

Posted

技术标签:

【中文标题】将每列中的值分配为该列的总和【英文标题】:assigning values in each column to be the sum of that column 【发布时间】:2016-12-19 14:28:39 【问题描述】:

我有 DataFrame,我正在尝试将每列中的所有值分配为该列的总和。

x = pd.DataFrame(data = [[1,2],[3,4],[5,6],[7,8],[9,10]],index=[1,2,3,4,5],columns=['a','b'])
x 
   a   b
1  1   2
2  3   4
3  5   6
4  7   8
5  9  10

输出应该是

   a    b
1  25   30
2  25   30
3  25   30
4  25   30
5  25   30

我想使用 x.apply(f, axis=0),但我不知道如何定义一个函数,将列转换为 lambda 函数中所有列值的总和。以下行引发 SyntaxError: can't assign to lambda

f = lambda x : x[:]= x.sum()

【问题讨论】:

你能分享一下你的数据框的小sn-p吗? “我不能如下定义 lambda 函数”:你为什么这么说? df.sum() 不会只做你想做的事 - 还是你真的想用总和覆盖所有列? (我正在努力思考你为什么要这样做......) 我认为你需要df['col'] = df.col.sum() 或更好的df['new_col'] = df.col.sum() 【参考方案1】:
for col in df:
    df[col] = df[col].sum()

或不使用循环的较慢解决方案...

df = pd.DataFrame([df.sum()] * len(df))

时间

@jezrael 感谢您的时间安排。这会在更大的数据帧上执行它们,并且还包括 for 循环。大部分时间都花在创建数据框而不是计算总和上,因此最有效的方法似乎是来自@ayhan 的方法,它直接将总和分配给值:

from string import ascii_letters

df = pd.DataFrame(np.random.randn(10000, 52), columns=list(ascii_letters))

# A baseline timing figure to determine sum of each column.
%timeit df.sum()
1000 loops, best of 3: 1.47 ms per loop

# Solution 1 from @Alexander
%%timeit
for col in df:
    df[col] = df[col].sum()
100 loops, best of 3: 21.3 ms per loop

# Solution 2 from @Alexander (without `for loop`, but much slower)
%timeit df2 = pd.DataFrame([df.sum()] * len(df))
1 loops, best of 3: 270 ms per loop

# Solution from @PiRSquared
%timeit df.stack().groupby(level=1).transform('sum').unstack()
10 loops, best of 3: 159 ms per loop

# Solution 1 from @Jezrael
%timeit (pd.DataFrame(np.tile(df.sum().values, (len(df.index),1)), columns=df.columns, index=df.index))
100 loops, best of 3: 2.32 ms per loop

# Solution 2 from @Jezrael
%%timeit
df2 = pd.DataFrame(df.sum().values[np.newaxis,:].repeat(len(df.index), axis=0),
                 columns=df.columns,
                 index=df.index)
100 loops, best of 3: 2.3 ms per loop

# Solution from @ayhan
%time df.values[:] = df.values.sum(0)
CPU times: user 1.54 ms, sys: 485 µs, total: 2.02 ms
Wall time: 1.36 ms  # <<<< FASTEST

【讨论】:

谢谢,有没有办法避免for循环? for 循环在这种情况下完全有效。 是的,但我的情况是我有数千列,我正在尝试找到一种更有效的方法。 对行进行迭代是有问题的。迭代列,不是那么多。我已经在 (10^5, 10^4) 数据帧上对此进行了测试,耗时不到 2 秒。如果这不是您一遍又一遍地做的事情,则无需避免在列上循环。 @whan 我也测试过这种技术。它是有效的。使用 numpy 通常会更有效,但它会成为更直观的 pandas 和更快的 numpy 之间的选择。 Alexander 已经一次又一次地证明,在特定情况下循环很快,而认为所有循环都是坏的概括是幼稚的。【参考方案2】:

如果你的DataFrame由数字组成,你可以直接改变它的值:

df.values[:] = df.sum()

【讨论】:

这非常快! 还是df.values[:] = df.values.sum(0) 是的,它似乎是迄今为止最快的,虽然它很难测试,因为值很快收敛到无穷大,我担心这可能会影响时间。 @piRSquared df.values[:] = df.values.sum(0) 这比我预期的要快得多。【参考方案3】:

使用transform

x.stack().groupby(level=1).transform('sum').unstack()

【讨论】:

谢谢,刚刚用我的案例测试了 4000+ 行和 2000+ 列。花费的时间大约是 10 秒【参考方案4】:

numpy.tile 的另一个更快的 numpy 解决方案:

print (pd.DataFrame(np.tile(x.sum().values, (len(x.index),1)), 
                    columns=x.columns, 
                    index=x.index))
    a   b
1  25  30
2  25  30
3  25  30
4  25  30
5  25  30

numpy.repeat 的另一个解决方案:

h = pd.DataFrame(x.sum().values[np.newaxis,:].repeat(len(x.index), axis=0),
                 columns=x.columns,
                 index=x.index)

print (h)
    a   b
1  25  30
2  25  30
3  25  30
4  25  30
5  25  30


In [431]: %timeit df = pd.DataFrame([x.sum()] * len(x))
1000 loops, best of 3: 786 µs per loop

In [432]: %timeit (pd.DataFrame(np.tile(x.sum().values, (len(x.index),1)), columns=x.columns, index=x.index))
1000 loops, best of 3: 192 µs per loop

In [460]: %timeit pd.DataFrame(x.sum().values[np.newaxis,:].repeat(len(x.index), axis=0),columns=x.columns, index=x.index)
The slowest run took 8.65 times longer than the fastest. This could mean that an intermediate result is being cached.
10000 loops, best of 3: 184 µs per loop

【讨论】:

这也适用于相当任意的索引...这意味着当索引不唯一时它很健壮。 谢谢,刚刚用我的案例测试了 4000+ 行和 2000+ 列。三种方法花费的时间大致是[1.08s,0.59s,0.58s]【参考方案5】:

我不知道你到底想做什么,但你可以用列表理解做一些事情,比如f = lambda x : [column.sum() for column in x]

【讨论】:

以上是关于将每列中的值分配为该列的总和的主要内容,如果未能解决你的问题,请参考以下文章

显示表中的所有列以及每列中填充的记录数

R中是不是有一种方法,如果一列的值满足另一列中的某个标准,则该列的值应该是上面的值

我的表有多个列,我想获取每列中的值计数并在 postgresql 中分别显示每列的计数值

用于计算同一列的值百分比的 SQL [关闭]

如何对数据表中特定数据列的值求和

矩阵列的最小元素