【问题标题】:cumsum() over several columnscumsum() 在几列上
【发布时间】:2016-06-03 06:54:10
【问题描述】:

我想创建以下数据框:

Index       A        B        C
 a          0        0        0
 b          1       10        0
 c         -1        0      -10
 d          1       20        0
 e          0        0        0
 f         -1        0      -20
 g          0        0        0
 h          1       15        0
 i         -1        0      -15

AB 已给出。 C 应通过函数生成,无需迭代。可能以这种方式:

def generate_C():
    C = np.where(A == -1, << here prior value from B * -1 >>, 0)
    df['C] = C
    return df

我尝试通过 cumsum() 对 BC 列进行尝试,但没有成功。请问有什么建议吗?

【问题讨论】:

  • 你的问题很有趣。但是我不明白与cumsum 的联系。
  • 我认为您可以为数据框添加更多值,因为不清楚为什么需要使用 cumsum
  • 我考虑过使用 cumsum() 因为 B 和 C 上的 cumsum() 应该会导致 B 列的剩余正值。例如在行 c 中:B 和 C 上的 cumsum() (来自a 到 b) 行是 +10。在 Excel 中,我会使用这样的 =IF(A7=-1;SUM($B$2:C6)*-1;0)。
  • 我还是不明白。是否可以在 B 列中添加更多价值?
  • @jezrael,当然欢迎替代解决方案。这只是更大数据框的一部分,其中所有 comumns 都是通过该函数生成的。因此,C 的生成也应该是功能的一部分。编辑:添加了更多行

标签: python pandas dataframe cumsum


【解决方案1】:

你可以使用:

df.loc[df.A==-1, 'C'] = (-df.loc[df.A==1, 'B']).values
df.C.fillna(0, inplace=True)
print (df)
       A   B    C   
Index                 
a      0   0   0.0
b      1  10   0.0
c     -1   0 -10.0
d      1  20   0.0
e      0   0   0.0
f     -1   0 -20.0

【讨论】:

  • 这看起来尽可能接近我发布的numpy solution,显然这是pandas 中最易读的方式。我想如果有人坚持使用纯pandas,这应该是首选的方式。
  • 谢谢。我认为所有解决方案都非常好。
  • 也许您可以编辑答案,使其不会生成列 C2 而不是 C。乍一看,我有点惊讶该方法需要一个“帮助”列,但在阅读了代码后,很明显情况并非如此。
  • @jezrael,这个解决方案看起来接近我正在寻找的东西。需要检查如何将其合并到函数中并查看 A 列的生成是否受到影响(因为它间接依赖于 C 的结果,我之前没有提到这一点,因为我没想到我的问题会导致相当复杂的解决方案)
【解决方案2】:

试试:

df.C = (df.B.replace(0, np.nan).ffill().shift() * (df.A == -1) * -1).fillna(0)

确认 jezrael 的建议:

df.C = (df.B.replace(0, np.nan).ffill() * (df.A == -1) * -1).fillna(0)

同样有效。由于我们是前向填充,因此不需要转移。

确认了上校博维尔的建议:

df.C = np.where(df.A==-1, -df.B.replace(0, method='ffill').shift(), 0)

如果它被发布为答案并且实际上是我的选择,那么它也可以作为我选择的答案。

【讨论】:

  • 我觉得shift可以省略(df.B.replace(0, np.nan).ffill() * (df.A == -1) * -1).fillna(0)
  • 或者对于 OP 来说更具可读性:np.where(df.A==-1, -df.B.replace(0, method='ffill').shift(), 0)。与其说 NA,不如说,'想要向前填充 0 值。以及在哪里非常明确。
  • @ColonelBeauvel 这听起来像是一个等待发生的答案。我不知道你可以将method='ffill' 传递给replace。太酷了!
  • 我认为这是最 Pythonic 的单线答案。但它和你的没什么不同,所以我不会发布它。
  • @ColonelBeauvel,单线很有趣。我仍然需要测试 A 列和所有其他列(未全部显示)的生成程度受移位和填充的影响。在过去的问题中,我在函数中使用 shift() 和矢量化设计时也遇到了一些问题。
【解决方案3】:

numpy 中很容易做到,但我还没有找到直接在pandas 中做到这一点的方法,因为显然pandas 不知何故忽略了花哨的索引:

def generate_C(df, inplace=False):
    import numpy

    if not inplace:
        df = df.copy()

    A, B = df.values.T
    C = numpy.zeros_like(A)
    C[A==-1] = -B[A==1]
    df['C'] = C

    return df

编辑:

我找到了使用纯pandas 的方法:

def generate_C(df, inplace=False):
    if not inplace:
        df = df.copy()

    df['C'] = (-df.B[df.A==1]).reindex(df.A[df.A==-1].index,method='pad')
    df['C'].fillna(0, inplace=True)

    return df

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    • 2020-01-25
    相关资源
    最近更新 更多