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

问题描述 投票:1回答:1

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

  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

我想将这些结合到最终的数据框中,对每个人说:

  • 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

谢谢你,节日快乐!

python pandas dataframe
1个回答
1
投票

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

  • set_indexdays_maxdf2专栏上的操作。我们还将名称更改为days(稍后会有所帮助)
  • groupby加入person
  • apply对指数进行reindex操作(天数,所以我们得到每天排到最后一天的行)
  • fillna填充由于重新索引而生成的convert列中的NaNs
  • assign为我们稍后设置的emailed创建一个虚拟列。

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

最后,使用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

和,

df2 = df_summary 
© www.soinside.com 2019 - 2024. All rights reserved.