【问题标题】:create a function to create new rows in data frames based on the given parameters as list and specific conditions in pandas创建一个函数以根据给定参数作为列表和熊猫中的特定条件在数据框中创建新行
【发布时间】:2020-06-17 10:05:57
【问题描述】:

我有一个如下所示的数据框。数据总是有一个会话。这意味着“会话”列中唯一值的数量将始终为 1。

df:

  B_ID   No_Show   Session  slot_num  Cumulative_no_show
    1     0.4       S1        1       0.4   
    2     0.3       S1        2       0.7      
    3     0.8       S1        3       1.5        
    4     0.3       S1        4       1.8       
    5     0.6       S1        5       2.4         
    6     0.8       S1        6       3.2       
    7     0.9       S1        7       4.1        
    8     0.4       S1        8       4.5
    9     0.6       S1        9       5.1

我尝试使用下面的代码在 df 上方创建。

df = pd.DataFrame({'B_ID': [1, 2, 3, 4, 5, 6, 7, 8, 9], 
                   'No_Show': [0.4, 0.3, 0.8, 0.3, 0.6, 0.8, 0.9, 0.4, 0.6], 
                   'Session': ['s1', 's1', 's1', 's1', 's1', 's1', 's1', 's1', 's1'], 
                   'slot_num': [1, 2, 3, 4, 5, 6, 7, 8, 9], 
                   'Cumulative_no_show': [0.4, 0.7, 1.5, 1.8, 2.4, 3.2, 4.1, 4.5, 5.1]})

df['Cumulative_no_show'] = df.groupby(['Session'])['No_Show'].cumsum() 

我还有一个列表,它可以是任意长度,这里是 9。

walkin_no_show = [ 0.3, 0.2, 0.1, 0.4, 0.5, 0.4, 0.2, 0.7, 0.8]

我还有一个长度为 4 的列表

threshold_p = [0.8, 0.9, 1.0, 1.1]

从上面当 u_cumulative > threshold_p[j] 在下面创建一个新行

 df[No_Show] = walkin_no_show[i]

它的 Session 和 slot_num 应该和前一个相同,并通过从前一个减去 (1 - walkin_no_show[i]) 创建一个名为 u_cumulative 的新列。

我想创建一个名为 overbook_dfs 的函数

def overbook_dfs (df, walkin_no_show, threshold_p ):
     return df_0_8, df_0_9, df_1_0, df_1_1

其中预期的输出dfs如下所示:

预期输出:

df_0_8:

  B_ID   No_Show   Session  slot_num  Cumulative_no_show   u_cumulative
    1     0.4       S1        1       0.4                  0.4
    2     0.3       S1        2       0.7                  0.7   
    3     0.8       S1        3       1.5                  1.5
walkin1   0.3       S1        3       1.5                  0.8
    4     0.3       S1        4       1.8                  1.1
walkin2   0.2       S1        4       1.8                  0.3      
    5     0.6       S1        5       2.4                  0.9
walkin3   0.1       S1        5       2.4                  0.0         
    6     0.8       S1        6       3.2                  0.8       
    7     0.9       S1        7       4.1                  1.7
walkin4   0.4       S1        7       4.1                  1.1
walkin5   0.5       S1        7       4.1                  0.6
    8     0.4       S1        8       4.5                  1.0
walkin6   0.4       S1        8       4.5                  0.4
    9     0.6       S1        9       5.1                  1.0
walkin7   0.2       S1        8       5.1                  0.2

df_0_9:

  B_ID   No_Show   Session  slot_num  Cumulative_no_show   u_cumulative
    1     0.4       S1        1       0.4                  0.4
    2     0.3       S1        2       0.7                  0.7   
    3     0.8       S1        3       1.5                  1.5
walkin1   0.3       S1        3       1.5                  0.8
    4     0.3       S1        4       1.8                  1.1
walkin2   0.2       S1        4       1.8                  0.3      
    5     0.6       S1        5       2.4                  0.9        
    6     0.8       S1        6       3.2                  1.7
walkin3   0.1       S1        6       3.2                  0.8       
    7     0.9       S1        7       4.1                  1.7
walkin4   0.4       S1        7       4.1                  1.1
walkin5   0.5       S1        7       4.1                  0.6    
    8     0.4       S1        8       4.5                  1.0
walkin6   0.4       S1        8       4.5                  0.4    
    9     0.6       S1        9       5.1                  1.0
walkin7   0.2       S1        9       5.1                  0.2

df_1_0:

  B_ID   No_Show   Session  slot_num  Cumulative_no_show   u_cumulative
    1     0.4       S1        1       0.4                  0.4
    2     0.3       S1        2       0.7                  0.7   
    3     0.8       S1        3       1.5                  1.5
walkin1   0.3       S1        3       1.5                  0.8
    4     0.3       S1        4       1.8                  1.1
walkin2   0.2       S1        4       1.8                  0.3      
    5     0.6       S1        5       2.4                  0.9        
    6     0.8       S1        6       3.2                  1.7
walkin3   0.1       S1        6       3.2                  0.8       
    7     0.9       S1        7       4.1                  1.7
walkin4   0.4       S1        7       4.1                  1.1
walkin5   0.5       S1        7       4.1                  0.6    
    8     0.4       S1        8       4.5                  1.1
walkin6   0.4       S1        8       4.5                  0.5
    9     0.6       S1        9       5.1                  1.1
walkin7   0.4       S1        9       4.5                  1.0

df_1_1:

  B_ID   No_Show   Session  slot_num  Cumulative_no_show   u_cumulative
    1     0.4       S1        1       0.4                  0.4
    2     0.3       S1        2       0.7                  0.7   
    3     0.8       S1        3       1.5                  1.5
walkin1   0.3       S1        3       1.5                  0.8
    4     0.3       S1        4       1.8                  1.1      
    5     0.6       S1        5       2.4                  1.6
walkin2   0.2       S1        5       2.4                  0.8        
    6     0.8       S1        6       3.2                  1.6
walkin3   0.1       S1        6       3.2                  0.7       
    7     0.9       S1        7       4.1                  1.6
walkin4   0.4       S1        7       4.1                  1.0
    8     0.4       S1        8       4.5                  1.4
walkin5   0.5       S1        8       4.5                  0.9
    9     0.6       S1        9       5.1                  1.5
walkin6   0.2       S1        9       5.1                  0.7

我提出了@Ben.T 回答的类似问题。非常感谢@Ben.T。这个问题的链接如下所示。 enter link description here

我尝试了下面的代码,但这给了我想要的输出。

# function to create the u_cumulative
def create_u_columns (ser, threshold_ns = 0.8):
    # create a copy
    arr_ns = ser.to_numpy().copy()
    # array for latter insert
    arr_idx = np.zeros(len(ser), dtype=int)
    walkin_id = 0 #start at 0 not 1 for list indexing
    for i in range(len(arr_ns)-1):
        if arr_ns[i]>threshold_ns:
            # remove 1 - walkin
            arr_ns[i+1:] -= (1-walkin_no_show[walkin_id])
            # increment later idx to add
            arr_idx[i] = walkin_id+1
            walkin_id +=1
    # for the last row
    if arr_ns[-1]>threshold_ns:
        arr_idx[-1] = walkin_id+1
    #return a dataframe with both columns
    return pd.DataFrame({'u_cumulative': arr_ns, 'mask_idx':arr_idx}, index=ser.index)

现在定义另一个函数 overbook_dfs

def overbook_dfs (df0, walkin_no_show, threshold_p ):
        l_res = [] #for result
        for th_p in threshold_p: #loop on threshold
            # create a copy of original dataframe
            df = df0.copy() 
            df[['u_cumulative','mask_idx']] = create_u_columns(df['Cumulative_no_show'],
                                                               threshold_ns=th_p)
            # select the rows
            df_toAdd = df.loc[df['mask_idx'].astype(bool), :].copy()
            # replace the values as wanted
            df_toAdd['No_Show'] = walkin_no_show[:len(df_toAdd)]
            df_toAdd['B_ID'] = 'walkin'+df_toAdd['mask_idx'].astype(str)
            df_toAdd['u_cumulative'] -= (1 - df_toAdd['No_Show'])
            # add 0.5 to index for later sort
            df_toAdd.index += 0.5 
            #append the result to a list
            l_res.append(pd.concat([df,df_toAdd])
                           .sort_index()
                           .reset_index(drop=True)
                           .drop('mask_idx', axis=1)
                        )
        return l_res

最后,和参数一起使用

# parameters
walkin_no_show = [ 0.3, 0.2, 0.1, 0.4, 0.5, 0.4, 0.2, 0.7, 0.8]
threshold_p = [0.8, 0.9, 1.0, 1.1]

# call your function
df_0_8, df_0_9, df_1_0, df_1_1 = overbook_dfs(df, walkin_no_show, threshold_p)  

【问题讨论】:

    标签: python pandas numpy


    【解决方案1】:

    这是适用于这种情况的解决方案。有一些小的变化:

    • create_u_columns 中,arr_idx 被列表l_idx 替换,如果每行有几个,则该列表将包含所有walkin 号码,循环中的if 条件被while 替换
    • overlook_dfs,而不是使用 df['mask_idx'].astype(bool) 来选择要添加的行,您现在需要explodemask_idx 列中的列表(由于更改create_u_columns) 并 dropna 删除没有要添加的行的行。

    否则很相似

    def create_u_columns (ser, threshold_ns = 0.8):
        # create a copy
        arr_ns = ser.to_numpy().copy()
        # use a list of list instead of array
        l_idx = [[] for i in range(len(ser))]
        walkin_id = 0
        for i in range(len(arr_ns)-1):
            ## need the value as another varaible for the while method
            val = arr_ns[i]
            while val>threshold_ns: ## while instead of if
                # remove 1 - walkin
                arr_ns[i+1:] -= (1-walkin_no_show[walkin_id])
                val -= (1-walkin_no_show[walkin_id]) # to stop the while
                # increment later idx to add
                walkin_id +=1
                l_idx[i].append(walkin_id)
        # for the last row
        if arr_ns[-1]>threshold_ns:
            l_idx[-1].append(walkin_id+1)
        #return a dataframe with both columns
        return pd.DataFrame({'u_cumulative': arr_ns, 'mask_idx':l_idx}, 
                            index=ser.index)
    

    def overbook_dfs (df0, walkin_no_show, threshold_p ):
        l_res = [] #for result
        for th_p in threshold_p: #loop on threshold
            # create a copy of original dataframe
            df = df0.copy() 
            df[['u_cumulative','mask_idx']] = create_u_columns(df['Cumulative_no_show'], 
                                                               threshold_ns=th_p)
            # select the rows by explode the column mask_idx and dropna
            df_toAdd = df.explode('mask_idx').dropna().copy() ###this is different
            # replace the values as wanted
            df_toAdd['No_Show'] = walkin_no_show[:len(df_toAdd)]
            df_toAdd['B_ID'] = 'walkin'+df_toAdd['mask_idx'].astype(str)
            df_toAdd['u_cumulative'] -= (1 - df_toAdd['No_Show'])
            # add 0.5 to index for later sort
            df_toAdd.index += 0.5 
            #append the result to a list
            l_res.append(pd.concat([df,df_toAdd])
                           .sort_index()
                           .reset_index(drop=True)
                           .drop('mask_idx', axis=1)
                        )
        return l_res
    
    # parameter
    walkin_no_show = [ 0.3, 0.2, 0.1, 0.4, 0.5, 0.4, 0.2, 0.7, 0.8]
    threshold_p = [0.8, 0.9, 1.0, 1.1]
    
    # call your function
    df_0_8, df_0_9, df_1_0, df_1_1 = overbook_dfs(df, walkin_no_show, threshold_p)
    

    你会得到例如

    print (df_0_9)
           B_ID  No_Show Session  slot_num  Cumulative_no_show  u_cumulative
    0         1      0.4      s1         1                 0.4           0.4
    1         2      0.3      s1         2                 0.7           0.7
    2         3      0.8      s1         3                 1.5           1.5
    3   walkin1      0.3      s1         3                 1.5           0.8
    4         4      0.3      s1         4                 1.8           1.1
    5   walkin2      0.2      s1         4                 1.8           0.3
    6         5      0.6      s1         5                 2.4           0.9
    7         6      0.8      s1         6                 3.2           1.7
    8   walkin3      0.1      s1         6                 3.2           0.8
    9         7      0.9      s1         7                 4.1           1.7
    10  walkin4      0.4      s1         7                 4.1           1.1
    11  walkin5      0.5      s1         7                 4.1           1.2
    12        8      0.4      s1         8                 4.5           1.0
    13  walkin6      0.4      s1         8                 4.5           0.4
    14        9      0.6      s1         9                 5.1           1.0
    15  walkin7      0.2      s1         9                 5.1           0.2
    

    【讨论】:

    猜你喜欢
    • 2020-10-06
    • 1970-01-01
    • 1970-01-01
    • 2019-03-27
    • 2019-11-18
    • 2018-07-01
    • 2020-09-30
    • 2022-07-21
    • 2021-02-28
    相关资源
    最近更新 更多