无需循环即可高效创建数据帧

时间:2017-12-26 16:41:14

标签: python pandas dataframe

我正在处理一些广告数据,例如电子邮件数据。我有两个数据集:

  1. 一个在邮件层面,每个人都说明他们邮寄的日期,以及他们转换的日期。

    import pandas as pd
    
    df_emailed=pd.DataFrame()
    df_emailed['person']=['A','A','A','A','B','B','B']
    df_emailed['day']=[2,4,8,9,1,2,5]
    df_emailed
    print(df_emailed)
    
      person  day
    0      A    2
    1      A    4
    2      A    8
    3      A    9
    4      B    1
    5      B    2
    6      B    5
    
  2. 我有一个摘要数据框,说明是否有人转换,以及转换的日期。

    df_summary=pd.DataFrame()
    df_summary['person']=['A','B']
    df_summary['days_max']=[10,5]
    df_summary['convert']=[1,0]
    print(df_summary)
    
      person  days_max  convert
    0      A        10        1
    1      B         5        0
    
  3. 我想将这些结合到最终的数据框中,对每个人说:

    • 1到最大日期,
    • 是否通过电子邮件发送(0,1)以及数据框中的最后一天
    • 他们是否转换(0,1)。

    我们假设他们在数据帧的最后一天进行转换。

    我知道要使用嵌套的for循环来做到这一点,但我认为这非常低效且有点愚蠢。有谁知道这样做的有效方法?

    期望的结果

    df_final=pd.DataFrame()
    df_final['person']=['A','A','A','A','A','A','A','A','A','A','B','B','B','B','B']
    df_final['day']=[1,2,3,4,5,6,7,8,9,10,1,2,3,4,5]
    df_final['emailed']=[0,1,0,1,0,0,0,1,1,0,1,1,0,0,1]
    df_final['convert']=[0,0,0,0,0,0,0,0,0,1,0,0,0,0,0]
    print(df_final)
    
       person  day  emailed  convert
    0       A    1        0        0
    1       A    2        1        0
    2       A    3        0        0
    3       A    4        1        0
    4       A    5        0        0
    5       A    6        0        0
    6       A    7        0        0
    7       A    8        1        0
    8       A    9        1        0
    9       A   10        0        1
    10      B    1        1        0
    11      B    2        1        0
    12      B    3        0        0
    13      B    4        0        0
    14      B    5        1        0
    

    谢谢你,节日快乐!

1 个答案:

答案 0 :(得分:1)

高级方法涉及修改df_summary(别名df2)以获取输出。我们需要

    set_index的{​​{1}}列上执行
  • days_max操作。我们还会将名称更改为df2(稍后会有所帮助)
  • days分组到groupby
  • person对索引进行apply操作(天数,因此我们会在截至最后一天的每一天获取行数)
  • reindex填写因重新索引而生成的fillna列中的NaN
  • convert为我们稍后设置的assign创建一个虚拟列。

接下来,使用emailed索引上一操作的结果。我们将使用这些值将相应的df_emailed单元格设置为emailed。这是通过MultiIndexing与1完成的。

最后,使用loc将索引作为列。

reset_index

哪里

def f(x):
    return x.reindex(np.arange(1, x.index.max() + 1))

df = df2.set_index('days_max')\
        .rename_axis('day')\
        .groupby('person')['convert']\
        .apply(f)\
        .fillna(0)\
        .astype(int)\
        .to_frame()\
        .assign(emailed=0)

df.loc[df1[['person', 'day']].apply(tuple, 1).values, 'emailed'] = 1
df.reset_index()

   person  day  convert  emailed
0       A    1        0        0
1       A    2        0        1
2       A    3        0        0
3       A    4        0        1
4       A    5        0        0
5       A    6        0        0
6       A    7        0        0
7       A    8        0        1
8       A    9        0        1
9       A   10        1        0
10      B    1        0        1
11      B    2        0        1
12      B    3        0        0
13      B    4        0        0
14      B    5        0        1

df1 = df_emailed