簡體   English   中英

vectorize操作在Python中根據不同條件創建多個新列 dataframe

[英]Vectorize operation to create multiple new columns based on different conditions in a dataframe in Python

我有一個 dataframe,如下所示:

+-----+---------+--------+-------------+
| 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,類型始終為“電子郵件”,狀態有多個值,其中我只對“打開”和“單擊”感興趣。

對於記錄 R2,類型始終為“事件”,狀態具有多個值,其中我只對“打開”和“已注冊”感興趣。

然而,對於記錄 R3,可以有多個類型值,即“搜索”、“故事”等,並且每種類型都有我感興趣的不同狀態值。

我想在以下條件下創建新的計數列:

  • 如果記錄為“R1”,則 email_cnt = 1,否則為 0

  • 如果記錄為“R2”,則 event_cnt = 1,否則為 0

  • 如果記錄為“R3”且類型為“故事”,則 story_cnt = 1,否則為 0

  • 如果記錄為“R3”且類型為“搜索”,則 search_cnt = 1,否則為 0,對於所有不同的 R3 類型,依此類推。

我已經使用iterrows遍歷 dataframe 的每一行並替換值。 我知道這不是最有效的方法,但我無法制定如何使用 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)

您可以列出您的條件並從中制作一個 DataFrame:

conditions=[
    (df['Record'].eq('R1') & (df['Status'].isin(['Open', 'Click']))),
    (df['Record'].eq('R2') & (df['Status'].isin(['Open', 'Registered']))),
    (df['Record'].eq('R3') & df['Type'].eq('Story')),
    (df['Record'].eq('R3') & df['Type'].eq('Search'))
           ]

out=pd.concat(conditions,axis=1).astype(int)
out.columns=['email_cnt', 'event_cnt', 'story_cnt', 'search_cnt']

或者

你可以使用np.where() 4次:

import numpy as np

df['email_cnt']=np.where((df['Record'].eq('R1') & (df['Status'].isin(['Open', 'Click']))),1,0)
df['event_cnt']=np.where((df['Record'].eq('R2') & (df['Status'].isin(['Open', 'Registered']))),1,0)
df['story_cnt']=np.where((df['Record'].eq('R3') & df['Type'].eq('Story')),1,0)
df['search_cnt']=np.where( (df['Record'].eq('R3') & df['Type'].eq('Search')),1,0)

注意:你也可以像 np.where 一樣使用loc 4 步

您可以使用以下方法創建所有新列:

new_cols = [col.lower() + '_cnt' for col in set(df['Type'])]
df = df.assign({col: 0 for col in new_cols})

然后使用以下命令用您的特定條件填充 1:

df.loc[(df['Record'] == 'R1') & (df['Type'] == 'Story') & df['Status'].isin(['Open', 'Click']), 'email_cnt'] = 1

因此,對於您擁有的所有條件。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM