【问题标题】:Vectorize operation to create multiple new columns based on different conditions in a dataframe in Python矢量化操作以在 Python 中根据数据框中的不同条件创建多个新列
【发布时间】:2023-04-04 01:13:01
【问题描述】:

我有一个如下所示的数据框:

+-----+---------+--------+-------------+
| Id  | Record  | Type   |   Status    |
+-----+---------+--------+-------------+
| 111 |  R1     | Email  |   Open      |
| 123 |  R2     | Event  |   Accepted  |
| 234 |  R3     | Story  |   Pending   |
| 135 |  R3     | Search |   Click     |
+-----+---------+--------+-------------+

It has around 1 million rows

记录列只能包含三个值,即“R1”、“R2”和“R3”。

对于记录 R1,type 始终是“Email”,status 有多个值,我只对“Open”和“Click”感兴趣。 p>

对于记录 R2,type 始终是“Event”,status 有多个值,我只对“Open”和“Registered”感兴趣。 p>

但是对于记录 R3,type 可以有多个值,即“搜索”、“故事”等,并且每种类型都有不同的 status 值,我是有兴趣。

我想在以下条件下创建新的计数列:

  • 如果记录是“R1”,则 email_cnt = 1,否则为 0

  • 如果记录是'R2',则event_cnt = 1,否则为0

  • 如果记录是'R3'并且类型是'Story',那么story_cnt = 1,否则为0

  • 如果记录为“R3”且类型为“搜索”,则对于所有不同的 R3 类型,search_cnt = 1,否则为 0,依此类推。

我使用 iterrows 来迭代每一行数据框并替换值。我知道这不是最有效的方法,但我无法制定如何使用 apply 方法或进行矢量化来加快计算速度。

如果您知道更快/更好的方法,请提出建议。

下面是我的代码:

df = pd.read_csv('file.csv')

# Create new metrics columns
tempcols = ['email_cnt', 'event_cnt', 'dm_cnt', 'enc_cnt', 'exp_cnt', 'orgsearch_cnt', 'orgsocial_cnt', 'paidsm_cnt', 'paidsearch_cnt', 'pd_cnt', 'smrtroom_cnt', 'stry_cnt', 'tm_cnt']

# Append new metrics in the existing campaigns dataframe
df = pd.concat([df, pd.DataFrame(columns=tempcols)])

# Values of Status column that we need
status_vals = ['Accepted', 'Call Completed', 'Commented', 'Declined', 'Liked', 'Responded', 'Shared']

for index, row in df.iterrows():
    if((row['Record']=='R1') & (row['Status'] in ['Open', 'Click'])):
        df.at[index, 'email_cnt'] = 1
    
    if((row['Record']=='R2') & (row['Status'] in ['Open', 'Registered'])):
        df.at[index, 'event_cnt'] = 1
    
    if(row['Record']=='R3'):
        if((row['Type']=='Story') & (row['Status'] in status_vals)):
            df.at[index, 'stry_cnt'] = 1
        if((row['Type']=='Search') & (row['Status'] in status_vals+['Downloaded', 'Registered'])):
            df.at[index, 'search_cnt'] = 1
        if((row['Type']=='Experience') & (row['Status'] in status_vals)):
            df.at[index, 'exp_cnt'] = 1

df.fillna(0, inplace=True)

【问题讨论】:

    标签:
    python
    pandas
    dataframe
    vectorization