在循环内使用df.loc有条件地设置值

时间:2016-03-16 14:57:11

标签: python python-2.7 pandas

我正在查询MS Access数据库以检索一组租约。我的任务是计算未来60个月基本租金的月总数。租约具有与开始和结束相关的日期,以便在租约在60个期间之前终止时计算正确的期间。当我尝试在特定租约增加的时候将基本租金增加一定金额时,我目前的挑战就出现了。我是初学者级别的Python / pandas,所以我的方法可能不是最佳的,代码粗略看起来。可能是矢量化方法更适合,但我还不能执行这样的代码。

数据: Lease input & output

代码:

try:
    sql = 'SELECT * FROM [tbl_Leases]'
    #sql = 'SELECT * FROM [Copy Of tbl_Leases]'
    df = pd.read_sql(sql, conn)
    #print df
    #df.to_csv('lease_output.csv', index_label='IndexNo')

    df_fcst_periods = pd.DataFrame()

    # init increments
    periods = 0
    i = 0

    # create empty lists to store looped info from original df
    fcst_months = []
    fcst_lease_num = []
    fcst_base_rent = []
    fcst_method = []
    fcst_payment_int = []
    fcst_rate_inc_amt = []
    fcst_rate_inc_int = []
    fcst_rent_start =  []

    # create array for period deltas, rent interval calc, pmt interval calc
    fcst_period_delta =  []
    fcst_rate_int_bool = []
    fcst_pmt_int_bool = []

    for row in df.itertuples():

        # get min of forecast period or lease ending date
        min_period = min(fcst_periods, df.Lease_End_Date[i])

        # count periods to loop for future periods in new df_fcst
        periods =  (min_period.year - currentMonth.year) * 12 + (min_period.month - currentMonth.month)

        for period in range(periods):

            nextMonth = (currentMonth + monthdelta(period))
            period_delta = (nextMonth.year - df.Rent_Start_Date[i].year) * 12 + (nextMonth.month - df.Rent_Start_Date[i].month)
            period_delta = float(period_delta)

            # period delta values allow us to divide by the payment & rent intervals looking for integers
            rate_int_calc = period_delta/df['Rate_Increase_Interval'][i]
            pmt_int_calc = period_delta/df['Payment_Interval'][i]

            # float.is_integer() method - returns bool
            rate_int_bool = rate_int_calc.is_integer()
            pmt_int_bool = pmt_int_calc.is_integer()

            # conditional logic to handle base rent increases
            if df['Forecast_Method'][i] == "Percentage" and rate_int_bool:
                rate_increase = df['Base_Rent'][i] * (1 + df['Rate_Increase_Amt'][i]/100)
                df.loc[df.index, "Base_Rent"] = rate_increase
                fcst_base_rent.append(df['Base_Rent'][i])
                print "Both True"
            else:
                fcst_base_rent.append(df['Base_Rent'][i])
                print rate_int_bool

            fcst_rate_int_bool.append(rate_int_bool)
            fcst_pmt_int_bool.append(pmt_int_bool)
            fcst_months.append(nextMonth)
            fcst_period_delta.append(period_delta)
            fcst_rent_start.append(df['Rent_Start_Date'][i])
            fcst_lease_num.append(df['Lease_Number'][i])
            #fcst_base_rent.append(df['Base_Rent'][i])
            fcst_method.append(df['Forecast_Method'][i])
            fcst_payment_int.append(df['Payment_Interval'][i])
            fcst_rate_inc_amt.append(df['Rate_Increase_Amt'][i])
            fcst_rate_inc_int.append(df['Rate_Increase_Interval'][i])

        i += 1

    df_fcst_periods['Month'] = fcst_months
    df_fcst_periods['Rent_Start_Date'] = fcst_rent_start    
    df_fcst_periods['Lease_Number'] = fcst_lease_num
    df_fcst_periods['Base_Rent'] = fcst_base_rent
    df_fcst_periods['Forecast_Method'] = fcst_method
    df_fcst_periods['Payment_Interval'] = fcst_payment_int
    df_fcst_periods['Rate_Increase_Amt'] = fcst_rate_inc_amt
    df_fcst_periods['Rate_Increase_Interval'] = fcst_rate_inc_int
    df_fcst_periods['Period_Delta'] = fcst_period_delta
    df_fcst_periods['Rate_Increase_Interval_bool'] = fcst_rate_int_bool
    df_fcst_periods['Payment_Interval_bool'] = fcst_pmt_int_bool

except Exception, e:
    print str(e)
    conn.close()

1 个答案:

答案 0 :(得分:0)

我最终在句点循环之前初始化变量,这允许我在循环时执行计算以获得后续句点的正确基本租金。

    # init base rent, rate increase amount, new rate for leases
    base_rent = df['Base_Rent'][i]
    rate_inc_amt = float(df['Rate_Increase_Amt'][i])
    new_rate = 0

    for period in range(periods):

        nextMonth = (currentMonth + monthdelta(period))
        period_delta = (nextMonth.year - df.Rent_Start_Date[i].year) * 12 + (nextMonth.month - df.Rent_Start_Date[i].month)
        period_delta = float(period_delta)

        # period delta values allow us to divide by the payment & rent intervals looking for integers
        rate_int_calc = period_delta/df['Rate_Increase_Interval'][i]
        pmt_int_calc = period_delta/df['Payment_Interval'][i]

        # float.is_integer() method - returns bool
        rate_int_bool = rate_int_calc.is_integer()
        pmt_int_bool = pmt_int_calc.is_integer()

        # conditional logic to handle base rent increases
        if df['Forecast_Method'][i] == "Percentage" and rate_int_bool:
            new_rate = base_rent * (1 + rate_inc_amt/100)
            base_rent = new_rate
            fcst_base_rent.append(new_rate)

        elif df['Forecast_Method'][i] == "Manual" and rate_int_bool:
            new_rate = base_rent + rate_inc_amt
            base_rent = new_rate
            fcst_base_rent.append(new_rate)

        else:
            fcst_base_rent.append(base_rent)

尽管有任何替代方法仍然开放!