这很难解释,但我会尝试用一个小例子来表示:
NDD = 11/1/2018
Run Code Online (Sandbox Code Playgroud)
付款数量:
1 0 2 0 2 1 1 0 2 1 1 1
Run Code Online (Sandbox Code Playgroud)
由于第一个月以11NDD 开头,然后我的列表的第一个元素将是11,计算下一个元素,我采取第一个月(11)并减去第一个付款1,然后第二个元素是10.如果您按照逻辑进行,我会继续这样做,并且模式很明确
11 10 10 8 8 6 5 4 4 2 1 12
Run Code Online (Sandbox Code Playgroud)
为了更清楚:
number_of_payments = [1 0 2 0 2 1 1 0 2 1 1 1]
Run Code Online (Sandbox Code Playgroud)
算法:
第1步 - 创建一个空列表:
dates = []
Run Code Online (Sandbox Code Playgroud)
步骤2 - 将NDD的第一个月附加到第一个日期索引
dates.append(NDD.month)
Run Code Online (Sandbox Code Playgroud)
第3步 - 现在执行以下公式:
for i in range(1,12):
dates[i] = (dates[i-1] + 12 - number_of_payments[i-1]) % 12
Run Code Online (Sandbox Code Playgroud)
第4步 - 最终结果将是
dates = [11 10 10 8 8 6 5 4 4 2 1 12]
Run Code Online (Sandbox Code Playgroud)
虽然我能够做到这一点,但我需要考虑NDD开始的年份,所以我想要的是结果应该是:
11/18 10/18 10/18 8/18 8/18 6/18 5/18 4/18 4/18 2/18 1/18 12/17
Run Code Online (Sandbox Code Playgroud)
现在跟我拥有的一样.这就是我对NDD的看法:
print(type(NDD))
Run Code Online (Sandbox Code Playgroud)
这是NDD的视图值
print(NDD[0:3])
0   2018-08-01
1   2018-07-01
2   2018-11-01
Run Code Online (Sandbox Code Playgroud)
以下是number_of_payments信息:
print(type(number_of_payments))
<class 'list'>
Run Code Online (Sandbox Code Playgroud)
这是第一行(与上面的例子相同)
print(number_of_payments[0])
[ 0.  1.  0.  1.  1.  1.  0.  5.  1.  0.  2.  1.]
Run Code Online (Sandbox Code Playgroud)
这是我想要获得的结果,但它不起作用:
dates = []
for i in range(len(number_of_payments)):
    dates.append([NDD[i]])
    for j in range(1, len(number_of_payments[i])):
        dates[i].append((dates[i][j-1] + 12 - number_of_payments[i][j-1]) % 12)
for date_row in dates:
    for n, i in enumerate(date_row):
        if i == 0:
            date_row[n] = 12
print(dates[0])
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-123-907a0962fd65> in <module>()
      4     dates.append([NDD[i]])
      5     for j in range(1, len(number_of_payments[i])):
----> 6         dates[i].append((dates[i][j-1] + 12 - number_of_payments[i][j-1]) % 12)
      7 for date_row in dates:
      8     for n, i in enumerate(date_row):
pandas/_libs/tslib.pyx in pandas._libs.tslib._Timestamp.__add__ (pandas\_libs\tslib.c:22331)()
ValueError: Cannot add integral value to Timestamp without freq.
Run Code Online (Sandbox Code Playgroud)
我希望这很清楚.
整个代码:
# In[9]:
# Import modules
import numpy as np
import pandas as pd
import datetime as dt
from functools import reduce
import datetime
from dateutil.relativedelta import *
# In[10]:
# Import data file
df = pd.read_csv("Paystring Data.csv")
df.head()
# In[11]:
# Get column data into a list
x = list(df)
# In[12]:
# Append column data into cpi, NDD, and as of dates
NDD = df['NDD 8/31']
cpi = df['Contractual PI']
as_of_date = pd.Series(pd.to_datetime(df.columns.str[:8], errors='coerce'))
as_of_date = as_of_date[1:13]
payment_months =  pd.to_datetime(as_of_date, errors = 'coerce').dt.month.tolist()
# In[13]:
# Get cash flows
cf = df.iloc[:,1:13].replace('[^0-9.]', '', regex=True).astype(float)
cf = cf.values
# In[14]:
# Calculate number of payments
number_of_payments = []
i = 0
while i < len(cpi):
    number_of_payments.append(np.round_(cf[:i + 1] / cpi[i]))
    i = i + 1
# In[15]:
# Calculate the new NDD dates
# dates = []
# for i in range(len(number_of_payments)):
#     dates.append([NDD_month[i]])
#     for j in range(1, len(number_of_payments[i][0])):
#         dates[i].append((dates[i][j-1] + 12 - number_of_payments[i][0][j-1]) % 12)
# print(dates[0])
d = []
for i in range(len(number_of_payments)):
    d.append(datetime.datetime.strptime(NDD[i], '%m/%d/%Y'))
def calc_payment(previous_payment,i):
    return previous_payment+relativedelta(months=(-1*i)) 
dates = [d]
for p in number_of_payments:
    dates += [calc_payment(result[-1],p)]
# In[ ]:
# Calculate paystring
paystring = []
for i in range(len(payment_months)):
    for j in range(len(dates[i])):
        if payment_months[i] < dates[i][j]:
            paystring.append(0)
        elif NDD_day[j] > 1:
            paystring.append((payment_months[i] + 12 - dates[i][j]) % 12)
        else:
            paystring.append( (payment_months[i] + 12 - dates[i][j]) + 1) % 12)
print(paystring[0])
Run Code Online (Sandbox Code Playgroud)
我目前坚持实施Arnon Rotem-Gal-Oz解决方案以适应这一点.这也是数据框的屏幕截图.如果有更多信息可以帮助,请告诉我.
更新:
我似乎无法得到任何好的答案,因为唯一一个有近距离解决方案的人删除了它.我现在已将其发布到https://www.codementor.io/u/dashboard/my-requests/5p8xirscop?from=active.支付100美元给任何人给我一个完整的解决方案,我的意思是完全完成而不仅仅是完整的.
编辑:
我尝试运行此代码
import numpy as np
import pandas as pd
from datetime import datetime, timedelta
from functools import reduce
from dateutil.relativedelta import *
df=pd.read_csv('Paystring Data.csv')
cpi=df['Contractual PI']
start=df['NDD 8/31'].apply(pd.to_datetime).astype(datetime)
cf = df.iloc[:,1:13].replace('[^0-9.]', '', regex=True).astype(float)
payments =  cf.apply(lambda p: round(p/cpi))
diffs=payments.cumsum(axis=1).applymap(lambda i: relativedelta(months=(-1*i)))
payments=diffs.apply(lambda x: start+x)
result=pd.concat([start,payments],axis=1)
Run Code Online (Sandbox Code Playgroud)
我收到此错误:
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\ops.py in na_op(x, y)
    657             result = expressions.evaluate(op, str_rep, x, y,
--> 658                                           raise_on_error=True, **eval_kwargs)
    659         except TypeError:
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\computation\expressions.py in evaluate(op, op_str, a, b, raise_on_error, use_numexpr, **eval_kwargs)
    210         return _evaluate(op, op_str, a, b, raise_on_error=raise_on_error,
--> 211                          **eval_kwargs)
    212     return _evaluate_standard(op, op_str, a, b, raise_on_error=raise_on_error)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\computation\expressions.py in _evaluate_numexpr(op, op_str, a, b, raise_on_error, truediv, reversed, **eval_kwargs)
    121     if result is None:
--> 122         result = _evaluate_standard(op, op_str, a, b, raise_on_error)
    123 
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\computation\expressions.py in _evaluate_standard(op, op_str, a, b, raise_on_error, **eval_kwargs)
     63     with np.errstate(all='ignore'):
---> 64         return op(a, b)
     65 
~\AppData\Local\Continuum\anaconda3\lib\site-packages\dateutil\relativedelta.py in __radd__(self, other)
    390     def __radd__(self, other):
--> 391         return self.__add__(other)
    392 
~\AppData\Local\Continuum\anaconda3\lib\site-packages\dateutil\relativedelta.py in __add__(self, other)
    362                 month += 12
--> 363         day = min(calendar.monthrange(year, month)[1],
    364                   self.day or other.day)
~\AppData\Local\Continuum\anaconda3\lib\calendar.py in monthrange(year, month)
    123         raise IllegalMonthError(month)
--> 124     day1 = weekday(year, month, 1)
    125     ndays = mdays[month] + (month == February and isleap(year))
~\AppData\Local\Continuum\anaconda3\lib\calendar.py in weekday(year, month, day)
    115        day (1-31)."""
--> 116     return datetime.date(year, month, day).weekday()
    117 
TypeError: integer argument expected, got float
During handling of the above exception, another exception occurred:
TypeError                                 Traceback (most recent call last)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\ops.py in safe_na_op(lvalues, rvalues)
    681             with np.errstate(all='ignore'):
--> 682                 return na_op(lvalues, rvalues)
    683         except Exception:
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\ops.py in na_op(x, y)
    663                 mask = notnull(x) & notnull(y)
--> 664                 result[mask] = op(x[mask], _values_from_object(y[mask]))
    665             elif isinstance(x, np.ndarray):
~\AppData\Local\Continuum\anaconda3\lib\site-packages\dateutil\relativedelta.py in __radd__(self, other)
    390     def __radd__(self, other):
--> 391         return self.__add__(other)
    392 
~\AppData\Local\Continuum\anaconda3\lib\site-packages\dateutil\relativedelta.py in __add__(self, other)
    362                 month += 12
--> 363         day = min(calendar.monthrange(year, month)[1],
    364                   self.day or other.day)
~\AppData\Local\Continuum\anaconda3\lib\calendar.py in monthrange(year, month)
    123         raise IllegalMonthError(month)
--> 124     day1 = weekday(year, month, 1)
    125     ndays = mdays[month] + (month == February and isleap(year))
~\AppData\Local\Continuum\anaconda3\lib\calendar.py in weekday(year, month, day)
    115        day (1-31)."""
--> 116     return datetime.date(year, month, day).weekday()
    117 
TypeError: integer argument expected, got float
During handling of the above exception, another exception occurred:
TypeError                                 Traceback (most recent call last)
<ipython-input-1-6cf75731780d> in <module>()
     10 payments =  cf.apply(lambda p: round(p/cpi))
     11 diffs=payments.cumsum(axis=1).applymap(lambda i: relativedelta(months=(-1*i)))
---> 12 payments=diffs.apply(lambda x: start+x)
     13 result=pd.concat([start,payments],axis=1)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py in apply(self, func, axis, broadcast, raw, reduce, args, **kwds)
   4260                         f, axis,
   4261                         reduce=reduce,
-> 4262                         ignore_failures=ignore_failures)
   4263             else:
   4264                 return self._apply_broadcast(f, axis)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\frame.py in _apply_standard(self, func, axis, ignore_failures, reduce)
   4356             try:
   4357                 for i, v in enumerate(series_gen):
-> 4358                     results[i] = func(v)
   4359                     keys.append(v.name)
   4360             except Exception as e:
<ipython-input-1-6cf75731780d> in <lambda>(x)
     10 payments =  cf.apply(lambda p: round(p/cpi))
     11 diffs=payments.cumsum(axis=1).applymap(lambda i: relativedelta(months=(-1*i)))
---> 12 payments=diffs.apply(lambda x: start+x)
     13 result=pd.concat([start,payments],axis=1)
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\ops.py in wrapper(left, right, name, na_op)
    719                 lvalues = lvalues.values
    720 
--> 721         result = wrap_results(safe_na_op(lvalues, rvalues))
    722         return construct_result(
    723             left,
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\ops.py in safe_na_op(lvalues, rvalues)
    690                 if is_object_dtype(lvalues):
    691                     return libalgos.arrmap_object(lvalues,
--> 692                                                   lambda x: op(x, rvalues))
    693             raise
    694 
pandas\_libs\algos_common_helper.pxi in pandas._libs.algos.arrmap_object()
~\AppData\Local\Continuum\anaconda3\lib\site-packages\pandas\core\ops.py in <lambda>(x)
    690                 if is_object_dtype(lvalues):
    691                     return libalgos.arrmap_object(lvalues,
--> 692                                                   lambda x: op(x, rvalues))
    693             raise
    694 
~\AppData\Local\Continuum\anaconda3\lib\site-packages\dateutil\relativedelta.py in __radd__(self, other)
    389 
    390     def __radd__(self, other):
--> 391         return self.__add__(other)
    392 
    393     def __rsub__(self, other):
~\AppData\Local\Continuum\anaconda3\lib\site-packages\dateutil\relativedelta.py in __add__(self, other)
    361                 year -= 1
    362                 month += 12
--> 363         day = min(calendar.monthrange(year, month)[1],
    364                   self.day or other.day)
    365         repl = {"year": year, "month": month, "day": day}
~\AppData\Local\Continuum\anaconda3\lib\calendar.py in monthrange(year, month)
    122     if not 1 <= month <= 12:
    123         raise IllegalMonthError(month)
--> 124     day1 = weekday(year, month, 1)
    125     ndays = mdays[month] + (month == February and isleap(year))
    126     return day1, ndays
~\AppData\Local\Continuum\anaconda3\lib\calendar.py in weekday(year, month, day)
    114     """Return weekday (0-6 ~ Mon-Sun) for year (1970-...), month (1-12),
    115        day (1-31)."""
--> 116     return datetime.date(year, month, day).weekday()
    117 
    118 
TypeError: ('integer argument expected, got float', 'occurred at index Aug 2018(P&I Applied)')
Run Code Online (Sandbox Code Playgroud)
    这是针对 Python 3 的(您需要 pip install python-dateutil)。(根据评论编辑)
df=pd.read_csv('Paystring Data.csv')
cpi=df['Contractual PI']
start=df['NDD 8/31'].apply(pd.to_datetime).astype(datetime)
cf = df.iloc[:,1:13].replace('[^0-9.]', '', regex=True).astype(float)
payments =  cf.apply(lambda p: round(p/cpi))
diffs=payments.cumsum(axis=1).applymap(lambda i: relativedelta(months=(-1*i)))
payments=diffs.apply(lambda x: start+x)
result=pd.concat([start,payments],axis=1)
Run Code Online (Sandbox Code Playgroud)
        |   归档时间:  |  
           
  |  
        
|   查看次数:  |  
           331 次  |  
        
|   最近记录:  |