这很难解释,但我会尝试用一个小例子来表示:
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)