我的目标是能够在记录表中识别价格增长。
我知道这可能与数据工具的可能性相差甚远,所以我感谢任何帮助或改进建议。
我遇到的直接麻烦是,如果pandas行中的某些数据不存在,则scipy.stats.linregress
不会返回。我认为有必要进行某种掩蔽或填充以返回存在空值的行的斜率度量。抛出异常但它仍然有效。
另外,我是否使用最佳解决方案来寻找增长? 我观察到,如果我过滤具有正斜率,较高rvalue(相关性)和较低stderr(标准误差)的记录,则这些行的趋势线是向上且一致的。
我尝试使用斜率和其他数值来量化价格增长的原因是因为如果我绘制excel图表中所有数据的线条,那么选择显示一致向上移动的线条是非常困难的,因为有太多噪声。它能以更好的方式完成吗?
以下是工作样本:
# credit jezrael
import pandas as pd
import numpy as np
import scipy
from scipy import stats
def calc_slope(row):
a = scipy.stats.linregress(row, y=axisvalues)
return pd.Series(a._asdict())
table=pd.DataFrame({'Category':['A','A','A','B','C','C','C','B','B','A','A','A','B','B','D','A','B','B'],
'Quarter':['2016-Q1','2017-Q2','2017-Q3','2017-Q4','2017-Q2','2016-Q2','2017-Q2','2016-Q3','2016-Q4','2016-Q2','2016-Q3','2017-Q4','2016-Q1','2016-Q2','2016-Q4','2016-Q4','2017-Q2','2017-Q3'],
'Value':[100,200,500,800,700,900,300,400,600,200,300,400,200,300,100,300,500,600]})
db=(table.groupby(['Category','Quarter']).filter(lambda group: len(group) >= 1)).groupby(['Category','Quarter'])["Value"].mean()
db=db.unstack()
axisvalues=list(range(1,len(db.columns)+1)) #used in calc_slope function
db = db.join(db.apply(calc_slope,axis=1))
答案 0 :(得分:2)
您可以使用:
#np.arange instead range
axisvalues= np.arange(1,len(db.columns)+1)
def calc_slope(row):
#mask NaNs out
mask = row.notnull()
a = scipy.stats.linregress(row[mask.values], y=axisvalues[mask])
return pd.Series(a._asdict())
db = db.join(db.apply(calc_slope,axis=1))
print (db)
print (db)
2016-Q1 2016-Q2 2016-Q3 2016-Q4 2017-Q2 2017-Q3 2017-Q4 \
Category
A 100.0 200.0 300.0 300.0 200.0 500.0 400.0
B 200.0 300.0 400.0 600.0 500.0 600.0 800.0
C NaN 900.0 NaN NaN 500.0 NaN NaN
D NaN NaN NaN 100.0 NaN NaN NaN
slope intercept rvalue pvalue stderr
Category
A 0.012895 0.315789 0.802955 0.029677 0.004281
B 0.010057 -0.885057 0.947623 0.001172 0.001516
C -0.007500 8.750000 -1.000000 0.000000 0.000000
D NaN NaN 0.000000 NaN NaN
但是对于最后一行获取RuntimeWarning
s,因为2016-Q4
中只有一个值。
对于删除警告,可以使用filterwarnings
,感谢Kdog:
import warnings
warnings.filterwarnings("ignore")