我是Python的新手,我正在努力编写在PHP / SQL中看似简单的东西,我希望你能帮助我。
我有2个Pandas Dataframes,我已经简化了以便更好地理解。
在第一个Dataframe df2015 中,我有2015年的销售额。 !请注意,遗憾的是,我们没有每个商店的所有值!
>>> df2015
Store Date Sales
0 1 2015-01-15 6553
1 3 2015-01-15 7016
2 6 2015-01-15 8840
3 8 2015-01-15 10441
4 9 2015-01-15 7952
2016年销售预测的另一个名为 df2016 的Dataframe,其中列出了所有商店。
(正如您所想,列 SalesForecast 是要填充的列。)
>>> df2016
Store Date SalesForecast
0 1 2016-01-15
1 2 2016-01-15
2 3 2016-01-15
3 4 2016-01-15
4 5 2016-01-15
我想创建一个函数, df2016 中的每一行都会从 df2015 中检索销售值,例如,这些值会增加5%并添加SalesForecast列中的这些新值 df2016 。
我们说预测是我创建的我要申请的功能:
def forecast(store_id,date):
sales2015 = df2015['Sales'].loc[(df2015['Store'].values == store_id) & (df2015['Date'].values == date )].values
forecast2016 = sales2015 * 1.05
return forecast2016
我已经用硬编码方式测试了这个函数,如下所示:
>>> forecast(1,'2015-01-15')
array([ 6880.65])
但是我们的问题在于......我如何将此功能应用于数据帧?
通过为 df2016 中的每一行创建一个循环,并通过 SELECT 从df2015中检索值(如果存在),可以很容易地在PHP中完成和 WHERE Store = store_id和Date = date .. ...但似乎逻辑与Pandas Dataframes和Python不一样。
我尝试了 apply 功能,如下所示:
df2016['SalesForecast'] = df2016.apply(df2016['Store'],df2016['Date'])
但是我无法正确地提出论据,或者我做错了......
我认为我没有好的方法,或者我的方法根本不适合Pandas和Python ..?
答案 0 :(得分:0)
我相信你快到了!缺少的是你在args中传递的功能。
apply
函数接受一个函数及其args。文档是here。
如果没有在我自己的系统上试过这个,我建议你这样做:
df2016['SalesForecast'] = df2016.apply(func=forecast, args=(df2016['Store'],df2016['Date']))
答案 1 :(得分:0)
Pandas的一个好处是它可以很好地处理丢失的数据。诀窍是在两个数据帧上使用公共索引。例如,如果我们将两个数据帧的索引设置为“Store”列:
df2015.set_index('Store', inplace=True)
df2016.set_index('Store', inplace=True)
然后做你想做的事就像:
df2016['SalesForecast'] = df2015['Sales'] * 1.05
导致:
Date SalesForecast
Store
1 2016-01-15 6880.65
2 2016-01-15 NaN
3 2016-01-15 7366.80
4 2016-01-15 NaN
5 2016-01-15 NaN
商店2的SalesForecast
为NaN
反映了df2015
数据框中不存在商店2的事实。
答案 2 :(得分:0)
请注意,如果您只需要将Df2015的Sales列乘以1.05,那么您可以这样做,全部在df2015中:
In [18]: df2015['Forecast'] = df2015['Sales'] * 1.05
In [19]: df2015
Out[19]:
Store Date Sales Forecast
0 1 2015-01-15 6553 6880.65
1 3 2015-01-15 7016 7366.80
2 6 2015-01-15 8840 9282.00
3 8 2015-01-15 10441 10963.05
4 9 2015-01-15 7952 8349.60
此时,如果您需要将此结果显示在df2016
数据集中,则可以将该结果加入df2016
:
In [20]: pandas.merge(df2016, # left side of join
df2015, # right side of join
on='Store', # similar to SQL 'on' for 'join'
how='outer', # same as SQL, outer join.
suffixes=('_2016', '_2015')) # rename same-named
# columns w/suffix
Out[20]:
Store Date_2016 Date_2015 Sales Forecast
0 1 2016-01-15 2015-01-15 6553 6880.65
1 2 2016-01-15 NaN NaN NaN
2 3 2016-01-15 2015-01-15 7016 7366.80
3 4 2016-01-15 NaN NaN NaN
4 5 2016-01-15 NaN NaN NaN
5 6 2016-01-15 2015-01-15 8840 9282.00
6 7 2016-01-15 NaN NaN NaN
7 8 2016-01-15 2015-01-15 10441 10963.05
8 9 2016-01-15 2015-01-15 7952 8349.60
如果两个DataFrame恰好具有兼容的索引,您可以直接在结果列中写入df2016
,即使它是在df2015
之类的另一个DataFrame上进行计算。一般来说,你需要注意这一点,明确地执行连接可能更为通用(正如我上面使用merge
函数所做的那样)。哪种方式最好取决于您的应用程序和您对索引列的了解。
有关列,整个DataFrame或子帧组的更一般功能应用,请参阅the documentation for this type of operation in Pandas。
还有一些菜谱示例的链接,以及您在SQL中表达类似操作的方式的比较。
请注意,我创建了数据以使用以下命令复制示例数据:
df2015 = pandas.DataFrame([[1, datetime.date(2015, 1, 15), 6553],
[3, datetime.date(2015, 1, 15), 7016],
[6, datetime.date(2015, 1, 15), 8840],
[8, datetime.date(2015, 1, 15), 10441],
[9, datetime.date(2015, 1, 15), 7952]],
columns=['Store', 'Date', 'Sales'])
from itertools import izip_longest
df2016 = pandas.DataFrame(
list(izip_longest(range(1,10),
[datetime.date(2016, 1, 15)],
fillvalue=datetime.date(2016, 1, 15))),
columns=['Store', 'Date']
)