【问题标题】:Aggregating customer spend without any customer ID在没有任何客户 ID 的情况下汇总客户支出
【发布时间】:2020-11-13 20:30:42
【问题描述】:

我有 2 列,如下所示。第一列是支出,第二列是从报价开始的月份。不幸的是,没有识别每个客户的 ID。在下面的例子中,有三个客户。例如前 5 行代表客户 1,接下来的 3 行是客户 2,最后 7 行是客户 3。您可以通过查看months_from_offer 来判断,每个客户从 -x 到 x 个月(x 不一定每个客户都相同,如此处所示,其中 x=2,1,3 分别代表客户 1,2,3)。

我要做的是计算每位客户的报价后支出与报价前支出的差异。我不关心个别客户本身,但我想要一个概述 - 例如10 位客户的后期/前期差价在 0 美元到 100 美元之间。

以下面的数据为例,计算客户 1 的 post/pre offer 差异,它是-$10 - $32 + $23 + $54 = $35

对于客户 2:-$21 + $87 = $66

对于客户 3:-$12 - $83 - $65 + $80 + $67 + $11 = -$2

spend  months_from_offer
$10    -2
$32    -1
$43     0
$23     1
$54     2
$21    -1
$23     0
$87     1
$12    -3
$83    -2
$65    -1
$21     0
$80     1
$67     2
$11     3

【问题讨论】:

    标签: python excel pandas


    【解决方案1】:

    创建标识

    s = df['months_from_offer'].iloc[::-1].cumsum().eq(0).iloc[::-1].cumsum()
    0     1
    1     1
    2     1
    3     1
    4     1
    5     2
    6     2
    7     2
    8     3
    9     3
    10    3
    11    3
    12    3
    13    3
    14    3
    Name: months_from_offer, dtype: int32
    

    然后assign

    df['id']=s 
    

    【讨论】:

      【解决方案2】:

      您可以使用以下方法识别客户,然后按客户分组:

      df['customer'] = df['months_from_offer'].cumsum().shift().eq(0).cumsum().add(1)
      #Another way to calculate customer per @teylyn method
      #df['customer'] = np.sign(df['months_from_offer']).diff().lt(0).cumsum().add(1)
      
      df['amount'] = df['spend'].str[1:].astype(int) * np.sign(df['months_from_offer']
      df.groupby('customer')['amount'].sum().reset_index()
      

      输出:

         customer  amount
      0         1      35
      1         2      66
      2         3      -2
      

      它是如何完成的:

        spend  months_from_offer  customer  amount
      0    $10                 -2         1     -10
      1    $32                 -1         1     -32
      2    $43                  0         1       0
      3    $23                  1         1      23
      4    $54                  2         1      54
      5    $21                 -1         2     -21
      6    $23                  0         2       0
      7    $87                  1         2      87
      8    $12                 -3         3     -12
      9    $83                 -2         3     -83
      10   $65                 -1         3     -65
      11   $21                  0         3       0
      12   $80                  1         3      80
      13   $67                  2         3      67
      14   $11                  3         3      11
      
      • 使用cumsumshifteqadd 计算“客户”列,从客户 1 开始。
      • 使用字符串操作计算“金额”并乘以np.sign '从报价开始的月份'
      • sum“金额”与groupby“客户”

      【讨论】:

        【解决方案3】:

        使用pandas.Series.diffcumsum 创建伪用户ID:

        s = df["months_from_offer"].diff().lt(0).cumsum()
        

        输出:

        0     0
        1     0
        2     0
        3     0
        4     0
        5     1
        6     1
        7     1
        8     2
        9     2
        10    2
        11    2
        12    2
        13    2
        14    2
        Name: months_from_offer, dtype: int64
        

        然后使用pandas.Series.clip 将级数设为-1、0 或1,然后进行乘法运算:

        spend = (df["spend"] * df["months_from_offer"].clip(-1, 1))
        

        然后使用 groupby.sum 和伪 id s

        spend.groupby(s).sum()
        

        最终输出:

        months_from_offer
        0    35
        1    66
        2    -2
        dtype: int64
        

        【讨论】:

          【解决方案4】:

          在 Excel 中,您可以插入一个辅助列,该列查看符号并确定符号是否与上面的行不同,然后增加一个计数器编号。

          将客户 ID 1 硬编码到第一行数据中,然后计算其余部分。

          =IF(AND(SIGN(A3)=-1,SIGN(A3)<>SIGN(A2)),B2+1,B2)
          

          复制结果并粘贴为值,然后您可以使用它们来汇总数据

          【讨论】:

          • 我喜欢这种计算客户+1的方法。
          【解决方案5】:

          我假设您想使用 pandas 读取 excel 文件。

          import pandas as pd
          
          df = pd.read_excel('file.xlsx', sheetname='yoursheet')
          
          pre  = 0
          post = 0
          for i in df.index:
              if df['months_from_offer'][i] < 0:
                  pre  += int(df['spend'][i])
              if df['months_from_offer'][i] > 0:
                  post += int(df['spend'][i])
          dif = post - pre
          

          如果您想读取每个客户的数据

          import pandas as pd
          
          df = pd.read_excel('file.xlsx', sheetname='yoursheet')
          
          customers = list[]
          last = None
          pre  = 0
          post = 0
          for i in df.index:
              if last is not None and abs(last + df['months_from_offer'][i]) > 1:
                  customers.append(post - pre)
                  pre  = 0
                  post = 0
              if df['months_from_offer'][i] < 0:
                  pre  += int(df['spend'][i])
              if df['months_from_offer'][i] > 0:
                  post += int(df['spend'][i])
              last = df['months_from_offer'][i]
          

          或者您可以使用字典来命名客户。我把客户分开的方式是当2个月大于(int) 1时,必须有另一个人的记录开始。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2019-12-17
            • 1970-01-01
            • 2018-05-03
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多