Python函数使用来自另一个Dataframe

时间:2015-11-20 19:00:13

标签: python function python-2.7 pandas apply

我是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 ..?

3 个答案:

答案 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的SalesForecastNaN反映了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']
)