将VBA脚本转换为Python脚本

0 人关注

我正在尝试将一些VBA脚本转换为Python脚本,我一直在努力解决一些问题,因为结果似乎与Excel文件给出的结果不同。 我有一个这样的数据框架例子。

|Name    |  A_Date    |
_______________________
|RAHEAL  |  04/30/2020|
|GIFTY   |  05/31/2020|
||ERIC   |  03/16/2020|
|PETER   |  05/01/2020|
|EMMANUEL|  12/15/2019| 
|BABA    |  05/23/2020|

我想实现这个结果(VBA脚本的结果)。

|Name    |  A_Date    | Sold
__________________________________
|RAHEAL  |  04/30/2020| No
|GIFTY   |  05/31/2020| Yes
||ERIC   |  03/16/2020| No
|PETER   |  05/01/2020| Yes
|EMMANUEL|  12/15/2019| No
|BABA    |  05/23/2020| Yes

通过转换这个VBA脚本。

Range("C2").Select
    Selection.Value = _
        "=IF(RC[-1]>=(INT(R2C2)-DAY(INT(R2C2))+1),""Yes"",""No"")"
    Selection.AutoFill Destination:=Range("C2", "C" & Cells(Rows.Count, 1).End(xlUp).Row)
    Range("C1").Value = "Sold"
    ActiveSheet.Columns("C").Copy
    ActiveSheet.Columns("C").PasteSpecial xlPasteValues

Simply :=IF(B2>=(INT($B$2)-DAY(INT($B$2))+1),"Yes","No")

To this Python script:

sales['Sold']=np.where(sales['A_Date']>=(sales['A_Date'] - pd.to_timedelta(sales.A_Date.dt.day, unit='d'))+ timedelta(days=1),'Yes','No') 

但我一直得到一个 "是 "的答案....,谁能帮我找出我可能犯了某种错误的地方?

4 个评论
为什么不试试自动转换器?这就是我首先要尝试的,然后看看它是否有效,也许可以清理一下代码。
Dela
@wamster 你能推荐一下外面的好东西吗?
对不起,我没有这方面的经验,但在谷歌上快速搜索后发现 this 可能符合你的要求。最主要的是要确保它最近被更新了,而这个已经被更新了。否则,如果它是5年前的,它可能会转换为Python2。
你的VBA引用的是L列,但你的数据框架最初只有2列。而且你的VBA公式与你的Excel公式不一致。如果你的Excel公式是正确的,那么你的第一个期望输出的Sold值是错误的。
python
excel
vba
dataframe
Dela
Dela
发布于 2021-01-11
2 个回答
buran
buran
发布于 2021-01-11
已采纳
0 人赞同
import pandas as pd
df = pd.DataFrame({'Name':['RAHEAL','GIFTY','ERIC','PETER','EMMANUEL','BABA'],
                   'A_Date':['04/30/2020','05/31/2020','03/16/2020',
                             '05/01/2020','12/15/2019','05/23/2020']})
df['A_Date'] = pd.to_datetime(df['A_Date'])
print(df)
df['Sold'] = df['A_Date'] >= df['A_Date'].iloc[0].replace(day=1)
df['Sold'] = df['Sold'].map({True:'Yes', False:'No'})
print(df)

output:

       Name     A_Date
0    RAHEAL 2020-04-30
1     GIFTY 2020-05-31
2      ERIC 2020-03-16
3     PETER 2020-05-01
4  EMMANUEL 2019-12-15
5      BABA 2020-05-23
       Name     A_Date Sold
0    RAHEAL 2020-04-30  Yes
1     GIFTY 2020-05-31  Yes
2      ERIC 2020-03-16   No
3     PETER 2020-05-01  Yes
4  EMMANUEL 2019-12-15   No
5      BABA 2020-05-23  Yes

If I read the formula right - if A_Date value >= 04/01/2020 (i.e. first day of month for date in B2), so RAHEAL should be Yes too

我不知道你是否注意到(以及是否有意这样做),但如果A_Date值有一个小数部分(即时间),当你计算每月1日的值时,就会有误差。如果B2中的时间是上午10:00,当你计算切割值时,它将是04/1/2020 10:00。然后如果你有另一个值,比如说04/01/2020 09:00,它将被评估为False/No。这也是在你的Excel公式中的工作方式。

编辑(2021年1月12日)。注意,列A_Date中的数值是datetime.datetimedatetime.date的类型。据推测,它们是在读取Excel文件时或事后明确转换的。

@QHarr, 根据使用 DAY 的公式我假设它在Excel中是一个Date,但无论如何,我都会在数据框架中把它(我也这么做了)转换成 datetime 对象。如果愿意的话,他们总是可以将其转换为 str
@YasserKhalil 如果不看你的代码,就很难判断你的问题是什么。我所展示的是我的代码和输出。如果你能分享一些代码和完整的跟踪记录。注意, A_Date 列的值是 datetime.datetime datetime.date 对象,而不是 str 。我使用 datetime.datetime.replace()
@YasserKhalil,检查 stackoverflow.com/q/28133018/4046632 我编辑了我的答案,明确提到了这一点。
@YasserKhalil,你是对的, iloc(0) 将返回列的第一个值(即索引0)(见 this ).他们想从excel转换的公式是$B$2(B1单元格是标题)。【替换代码1- 在我之前的评论中,有一个链接。
@YasserKhalil,是的,它可以用一行完成,但它的可读性较差,而可读性是很重要的。在慢动作中跟随代码会更容易,而不是单行的。至少这也是我为什么要分行做的原因。
QHarr
QHarr
发布于 2021-01-11
0 人赞同

非常尴尬的是,我没有看到buran给出的简单优雅的解决方案+。我做了更多的字面翻译。

first_date.toordinal() - 693594 是你初始日期的整数日期值, current_date.toordinal() - 693594 是日期列当前迭代的整数日期值。我将 apply 的单元格公式逻辑转换为每个 A_Date 的行值并输出为相应的 Sold 的列值。

import pandas as pd
from datetime import datetime
def is_sold(current_date:datetime, first_date:datetime, day_no:int)->str:
    # use of toordinal idea from @rjha94 https://stackoverflow.com/a/47478659
    if current_date.toordinal() - 693594 >= first_date.toordinal() - 693594 - day_no + 1:
        return "Yes" 
    else:
        return "No"
sales = pd.DataFrame({'Name':['RAHEAL','GIFTY','ERIC','PETER','EMMANUEL','BABA'],