【问题标题】:panda add several new columns based on values from other columns at the same time?panda 同时根据其他列的值添加几个新列?
【发布时间】:2015-11-20 22:26:22
【问题描述】:

如何根据其他列的值同时添加几个新列?我只找到了一次添加一行的示例。

我可以添加 3 个新列,但这似乎效率不高,因为它必须遍历所有行 3 次。 有没有办法遍历一次DF?

import pandas as pd
from decimal import Decimal
d = [
    {'A': 2, 'B': Decimal('628.00')},
    {'A': 1, 'B': Decimal('383.00')},
    {'A': 3, 'B': Decimal('651.00')},
    {'A': 2, 'B': Decimal('575.00')},
    {'A': 4, 'B': Decimal('1114.00')},
]

df = pd.DataFrame(d)

In : df
Out:
   A        B
0  2   628.00
1  1   383.00
2  3   651.00
3  2   575.00
4  4  1114.00

# How to do those in one operation to avoid traversing the DF 3 times
df['C'] = df.apply(lambda row: row['B']-1000, axis=1)
df['D'] = df.apply(lambda row: row['B']*row['B'], axis=1)
df['E'] = df.apply(lambda row: row['B']/2, axis=1)

In : df
Out:
   A        B        C             D       E
0  2   628.00  -372.00   394384.0000  314.00
1  1   383.00  -617.00   146689.0000  191.50
2  3   651.00  -349.00   423801.0000  325.50
3  2   575.00  -425.00   330625.0000  287.50
4  4  1114.00   114.00  1240996.0000  557.00

【问题讨论】:

    标签: python python-3.x pandas


    【解决方案1】:

    我不会使用 lambda 函数。简单的矢量化实现既更快又更易于阅读。

    df['C'] = df['B'] - 1000
    df['D'] = df['B'] ** 2
    df['E'] = df['B'] / 2
    
    >>> df
       A        B        C             D       E
    0  2   628.00  -372.00   394384.0000  314.00
    1  1   383.00  -617.00   146689.0000  191.50
    2  3   651.00  -349.00   423801.0000  325.50
    3  2   575.00  -425.00   330625.0000  287.50
    4  4  1114.00   114.00  1240996.0000  557.00
    

    让我们在一个有一百万行的数据帧上计时:

    df = pd.concat([df for _ in range(200000)], ignore_index=True)
    >>> df.shape
    (1000000, 2)
    
    >>> %%timeit -n 3
        df['C'] = df.apply(lambda row: row['B'] - 1000, axis=1)
        df['D'] = df.apply(lambda row: row['B'] * row['B'], axis=1)
        df['E'] = df.apply(lambda row: row['B'] / 2, axis=1)
    3 loops, best of 3: 1min 20s per loop
    
    >>> %%timeit -n 3
        df['C'] = df['B'] - 1000
        df['D'] = df['B'] ** 2
        df['E'] = df['B'] / 2
    3 loops, best of 3: 49.7 s per loop
    

    如果您取消 Decimal 类型并改用浮点数,速度会明显更快

    d = [
        {'A': 2, 'B': 628.00},
        {'A': 1, 'B': 383.00},
        {'A': 3, 'B': 651.00},
        {'A': 2, 'B': 575.00},
        {'A': 4, 'B': 1114.00}]
    
    df = pd.DataFrame(d)
    df = pd.concat([df for _ in range(200000)], ignore_index=True)
    
    >>> %%timeit -n 3
        df['C'] = df['B'] - 1000
        df['D'] = df['B'] ** 2
        df['E'] = df['B'] / 2
    3 loops, best of 3: 33.1 ms per loop
    
    >>> df.shape
    (1000000, 5)
    

    【讨论】:

    • 这个操作的速度是否重要尚不清楚——可能根本不重要。不过,使用系列运算而不是应用在这类情况下,这当然是一件不错的、正常的、可读的事情。
    • @MikeGraham 鉴于 OP 在第二段中关于效率的评论,我将其解释为速度的效率。
    • 很好的答案。谢谢。如果我很了解熊猫的工作原理,那么每次我们添加的每一行/新列都必须遍历整个 DF 是否正确?所以在这种情况下,它将在整个 DF 中循环 3 次,因为我们添加了 3 列。如果我想添加更多列,有没有办法改进这一点,因为每次都遍历整个 DF 是没有意义的。是否可以同时计算每行上的所有新列,因此只循环一次 DF?也许它不是更快?我还不太了解熊猫。谢谢。
    • 另外,使用浮点数的区别令人印象深刻。 df['B'] = df['B'].astype(numpy.float64) 是投射一列 Decimal 对象的正确方法吗?谢谢。
    • 是的,您可以转换为df['B'].astype('float')df['B'].astype(np.float),或df['B'].astype(np.float32)
    猜你喜欢
    • 2019-04-04
    • 1970-01-01
    • 2022-12-17
    • 1970-01-01
    • 2021-07-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多