使用np.where的Pandas DF多个条件

时间:2018-06-04 15:27:45

标签: python pandas numpy dataframe

我正在尝试将一些相对简单的条件组合到一个np.where子句中,但是在获取逻辑语法时遇到了麻烦。

我当前的数据框看起来像下面的df,有四列。我想添加两个列,命名如下,具有以下条件:

所需的输出低于 - df df_so_v2

  1. 自活动以来的几天 *查找具有相同ID的最新前一行,然后减去日期列 *如果没有最新值,请返回NA

  2. 变动。平均。值 条件1:如果Count = 0,NA 条件2:如果Count!= 0,找到最近的前一行,同时ID和Count!= 0,然后找到平均值的差异。值列。

  3. 但是,我正在构建简单的np.where查询,如下所示,并且不知道如何组合这种情况下所需的多个条件。

    df['CASH'] = np.where(df['CASH'] != 0, df['CASH'] + commission , df['CASH'])
    

    非常感谢你对此的帮助。

    df_dict={'DateOf': ['2017-08-07','2017-08-07','2017-08-07','2017-08-04','2017-08-04','2017-08-04'
                    , '2017-08-03','2017-08-03','2017-08-03','2017-08-02','2017-08-02','2017-08-02','2017-08-01','2017-08-01','2017-08-01'],
        'ID': ['553','559','914','553','559','914','553','559','914','553','559','914','553','559','914'], 'Count': [0, 4, 5, 0, 11, 10, 3, 9, 0,1,0,2,4,4,0],
        'Avg. Value': [0,3.5,2.2,0,4.2,3.3,5.3,5,0,3,0,2,4.4,6.4,0]}
    df_so=pd.DataFrame(df_dict)
    
    df_dict_v2={'DateOf': ['2017-08-07','2017-08-07','2017-08-07','2017-08-04','2017-08-04','2017-08-04'
                    , '2017-08-03','2017-08-03','2017-08-03','2017-08-02','2017-08-02','2017-08-02','2017-08-01','2017-08-01','2017-08-01'],
        'ID': ['553','559','914','553','559','914','553','559','914','553','559','914','553','559','914'], 'Count': [0, 4, 5, 0, 11, 10, 3, 9, 0,1,0,2,4,4,0],
        'Avg. Value': [0,3.5,2.2,0,4.2,3.3,5.3,5,0,3,0,2,4.4,6.4,0],
        'Days_since_activity': [4,3,1,1,1,2,1,2,1,1,1,1,'NA','NA','NA'],
        'Chg. Avg Value': ['NA',-0.7,-1.1,'NA',-0.8,1.3,2.3,-1.4,'NA',-1.4,'NA','NA','NA','NA','NA']
        }
    
    df_so_v2=pd.DataFrame(df_dict_v2)
    

1 个答案:

答案 0 :(得分:0)

Here is the answer to this part of the question. I need more clarification on the conditions of 2.

1) Days since activity *Find most recent prior row with same ID, then subtract dates column *If no most recent value, return NA

First you need to convert strings to datetime, then sort the dates in ascending order. Finally use .transform to find the difference.

df_dict={'DateOf': ['2017-08-07','2017-08-07','2017-08-07','2017-08-04','2017-08-04','2017-08-04'
                , '2017-08-03','2017-08-03','2017-08-03','2017-08-02','2017-08-02','2017-08-02','2017-08-01','2017-08-01','2017-08-01'],
    'ID': ['553','559','914','553','559','914','553','559','914','553','559','914','553','559','914'], 'Count': [0, 4, 5, 0, 11, 10, 3, 9, 0,1,0,2,4,4,0],
    'Avg. Value': [0,3.5,2.2,0,4.2,3.3,5.3,5,0,3,0,2,4.4,6.4,0]}
df_so = pd.DataFrame(df_dict)
df_so['DateOf'] = pd.to_datetime(df_so['DateOf'])

df_so.sort_values('DateOf', inplace=True)
df_so['Days_since_activity'] = df_so.groupby(['ID'])['DateOf'].transform(pd.Series.diff)
df_so.sort_index()

Edited based on your comment: Find the most recent previous day that does not have a count of Zero and calculate the difference.

df_dict={'DateOf': ['2017-08-07','2017-08-07','2017-08-07','2017-08-04','2017-08-04','2017-08-04'
                , '2017-08-03','2017-08-03','2017-08-03','2017-08-02','2017-08-02','2017-08-02','2017-08-01','2017-08-01','2017-08-01'],
    'ID': ['553','559','914','553','559','914','553','559','914','553','559','914','553','559','914'], 'Count': [0, 4, 5, 0, 11, 10, 3, 9, 0,1,0,2,4,4,0],
    'Avg. Value': [0,3.5,2.2,0,4.2,3.3,5.3,5,0,3,0,2,4.4,6.4,0]}

df = pd.DataFrame(df_dict)
df['DateOf'] = pd.to_datetime(df['DateOf'], format='%Y-%m-%d')

df.sort_values(['ID','DateOf'], inplace=True)
df['Days_since_activity'] = df.groupby(['ID'])['DateOf'].diff()

mask = df.ID != df.ID.shift(1)
mask2 = df.groupby('ID').Count.shift(1) == 0

df['Days_since_activity'][mask] = np.nan
df['Days_since_activity'][mask2] = df.groupby(['ID'])['DateOf'].diff(2)

df['Chg. Avg Value'] = df.groupby(['ID'])['Avg. Value'].diff()
df['Chg. Avg Value'][mask2] = df.groupby(['ID'])['Avg. Value'].diff(2)

conditions = [((df['Count'] == 0)),]
choices = [np.nan,]
df['Chg. Avg Value'] = np.select(conditions, choices, default = df['Chg. Avg Value'])

# df = df.sort_index()
df

New unsorted Output for easy comparison:

    DateOf  ID  Count   Avg. Value  Days_since_activity Chg. Avg Value
12  2017-08-01  553 4   4.4      NaT        NaN
9   2017-08-02  553 1   3.0      1 days     -1.4
6   2017-08-03  553 3   5.3      1 days     2.3
3   2017-08-04  553 0   0.0      1 days     NaN
0   2017-08-07  553 0   0.0      4 days     NaN
13  2017-08-01  559 4   6.4      NaT        NaN
10  2017-08-02  559 0   0.0      1 days     NaN
7   2017-08-03  559 9   5.0      2 days     -1.4
4   2017-08-04  559 11  4.2      1 days     -0.8
1   2017-08-07  559 4   3.5      3 days     -0.7
14  2017-08-01  914 0   0.0      NaT        NaN
11  2017-08-02  914 2   2.0      NaT        NaN
8   2017-08-03  914 0   0.0      1 days     NaN
5   2017-08-04  914 10  3.3      2 days     1.3
2   2017-08-07  914 5   2.2      3 days     -1.1

index 11 should be NaT because the most current previous row has a count of zero and there is nothing else to compare it to