Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/311.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python excel差分发生器_Python_Excel_Pandas - Fatal编程技术网

Python excel差分发生器

Python excel差分发生器,python,excel,pandas,Python,Excel,Pandas,我正在尝试创建一个python程序,该程序为我提供了两个包含多个工作表的大型excel文件之间的差异。我让它将结果打印到excel中,但显然,当其中一个单元格包含日期时间数据时,将布尔数据框与包含日期的数据框相乘的操作就不再有效了。我得到以下错误: TypeError:不支持*:“bool”和“datetime.datetime”的操作数类型 “编辑”:我刚刚意识到这个方法对字符串也不起作用(它只对纯数字数据起作用)。对于字符串、数字和时间数据,有什么更好的方法可以做到这一点 #start of

我正在尝试创建一个python程序,该程序为我提供了两个包含多个工作表的大型excel文件之间的差异。我让它将结果打印到excel中,但显然,当其中一个单元格包含日期时间数据时,将布尔数据框与包含日期的数据框相乘的操作就不再有效了。我得到以下错误:

TypeError:不支持*:“bool”和“datetime.datetime”的操作数类型

“编辑”:我刚刚意识到这个方法对字符串也不起作用(它只对纯数字数据起作用)。对于字符串、数字和时间数据,有什么更好的方法可以做到这一点

#start of program
    import pandas as pd
    from pandas import ExcelWriter
    import numpy as np

    df1 = pd.read_excel('4_Input EfE_2030.xlsm',None)
    df2 = pd.read_excel('5_Input EfE_2030.xlsm',None)
    keys1=df1.keys()
    keys2=df2.keys()
    writer = ExcelWriter('test1.xlsx')
#loop for all sheets and create new dataframes with the differences    
    for x in keys1:
        df3 = pd.read_excel('4_Input EfE_2030.xlsm',sheetname=x,header=None)
        df4 = pd.read_excel('5_Input EfE_2030.xlsm',sheetname=x,header=None)
        dif = df3 != df4
        df=dif*df3
        df2=dif*df4
        nrcolumns=len(df.columns)
#when there are no differences in the entire sheet the dataframe will be empty. Add 1 to row indexes so the number coincides with excel rownumbers
        if not df.empty:
            # df.columns = ['A']
            df.index = np.arange(1, len(df) + 1)
        if not df2.empty:
            # df2.columns = ['A']
            df2.index = np.arange(1, len(df) + 1)
#delete rows with all 0
        df = df.loc[~(df == 0).all(axis=1)]
        df2 = df2.loc[~(df2 == 0).all(axis=1)]
#create new df with the data of the 2 sheets
        result = pd.concat([df,df2],axis=1)
        print(result)
        result.to_excel(writer,sheet_name=x)
最新答案 方法 这是一个有趣的问题。另一种方法是使用Pandas提供的
面板
数据结构,将一个Excel工作表中的列值与另一个Excel工作表中的列值进行比较。此数据结构将数据存储为三维数组。使用存储在
面板中的两个Excel工作表中的数据,我们可以比较工作表中由一个或多个列(例如,唯一ID)唯一标识的行。要进行此比较,请应用自定义函数,将一个工作表中每列的每个单元格中的值与第二个工作表中同列的同一单元格中的值进行比较。这种方法的一个好处是,每个值的数据类型不再重要,因为我们只是比较值(例如,
1==1
“我的名字”==“我的名字”
,等等)

假设 这种方法对您的数据做出了以下几个假设:

  • 每个工作表中的行共享唯一标识每一行的一列或一组列
  • 两个工作表中都存在用于比较的列,它们共享相同的列标题
  • (我可能没有注意到其他假设。)

    实施 这种方法的实现有点复杂。此外,由于我没有访问您的数据的权限,因此无法专门针对您的数据自定义实现。话虽如此,我将使用如下所示的一些虚拟数据来实现这种方法

    “旧”数据集:

    id  col_num col_str                col_datetime
     1  123     My string 1            2001-12-04
     2  234     My string 2            2001-12-05
     3  345     My string 3            2001-12-06
    
    id  col_num col_str                col_datetime
     1  123     My string 1 MODIFIED   2001-12-04
     3  789     My string 3            2001-12-10
     4  456     My string 4            2001-12-07
    
    “新”数据集:

    id  col_num col_str                col_datetime
     1  123     My string 1            2001-12-04
     2  234     My string 2            2001-12-05
     3  345     My string 3            2001-12-06
    
    id  col_num col_str                col_datetime
     1  123     My string 1 MODIFIED   2001-12-04
     3  789     My string 3            2001-12-10
     4  456     My string 4            2001-12-07
    
    请注意这两个数据帧的以下差异:

    df_old = pd.read_excel('old.xlsx', 'Sheet1', na_values=['NA'])
    df_new = pd.read_excel('new.xlsx', 'Sheet1', na_values=['NA'])
    
    df_old['VER'] = 'OLD'
    df_new['VER'] = 'NEW'
    
        col_num     col_str                             col_datetime
    id              
    1   123         My string 1 -> My string 1 MODIFIED 2001-12-04 00:00:00 
    3   345 -> 789  My string 3                         2001-12-06 00:00:00 -> 2001-12-10 00:00:00
    
  • id为
    1的行中的
    col\u str
    不同
  • id为
    3的行中的
    col_num
    不同
  • id为
    3的行中的
    col\u datetime
    不同
  • id为
    2的行存在于“旧”中,但不在“新”中
  • id为
    4的行存在于“新建”中,但不存在于“旧”中
  • 好的,让我们开始吧。首先,我们将数据集读入单独的数据帧:

    df_old = pd.read_excel('old.xlsx', 'Sheet1', na_values=['NA'])
    df_new = pd.read_excel('new.xlsx', 'Sheet1', na_values=['NA'])
    
    df_old['VER'] = 'OLD'
    df_new['VER'] = 'NEW'
    
        col_num     col_str                             col_datetime
    id              
    1   123         My string 1 -> My string 1 MODIFIED 2001-12-04 00:00:00 
    3   345 -> 789  My string 3                         2001-12-06 00:00:00 -> 2001-12-10 00:00:00
    
    然后,我们在每个数据帧中添加一个新的版本列,以保持思路的清晰。稍后,我们还将使用此列将“旧”和“新”数据帧中的行分离为各自独立的数据帧:

    df_old = pd.read_excel('old.xlsx', 'Sheet1', na_values=['NA'])
    df_new = pd.read_excel('new.xlsx', 'Sheet1', na_values=['NA'])
    
    df_old['VER'] = 'OLD'
    df_new['VER'] = 'NEW'
    
        col_num     col_str                             col_datetime
    id              
    1   123         My string 1 -> My string 1 MODIFIED 2001-12-04 00:00:00 
    3   345 -> 789  My string 3                         2001-12-06 00:00:00 -> 2001-12-10 00:00:00
    
    然后,我们将“旧”和“新”数据集连接到一个数据帧中。请注意,
    ignore\u index
    参数设置为
    True
    ,因此我们忽略索引,因为它对该操作没有意义:

    df_full=pd.concat([df_old,df_new],ignore_index=True)

    现在,我们将识别两个数据帧中存在的所有重复行。在这些行中,“旧”和“新”数据帧中的所有列值都相同。换句话说,这些是不存在差异的行:

    一旦确定,我们将删除这些重复的行。我们剩下的是(a)两个数据帧之间不同的行,(b)存在于“旧”数据帧中但不存在于“新”数据帧中,以及(c)存在于“新”数据帧中但不存在于“旧”数据帧中的行:

    df_diff=df_full。删除重复项(子集=['id','col_num','col_str','col_datetime'])

    接下来,我们为存在于“旧”和“新”数据帧中的行识别并提取
    id
    (即,跨越“旧”和“新”数据帧的主键)的值。需要注意的是,这些
    id
    s包括一个或其他数据帧中存在的行,但不包括两个数据帧中存在的行(即删除的行或添加的行):

    diff\u id=df\u diff.set\u index('id').index.get\u duplicates()

    现在,我们将
    df_full
    限制为仅由
    diff_id
    中的
    id
    s标识的行:

    df_diff_id=df_full[df_full['id'].isin(diff_id)]

    现在,我们将“旧”和“新”数据帧中的重复行移动到单独的数据帧中,我们可以将这些数据帧插入
    面板
    数据结构中进行比较:

    df_diff_old = df_diff_ids[df_diff_ids['VER'] == 'OLD']
    df_diff_new = df_diff_ids[df_diff_ids['VER'] == 'NEW']
    
    接下来,我们将这两个数据帧的索引设置为主键(即,
    id
    )。这是
    面板有效工作所必需的:

    df_diff_old.set_index('id', inplace=True)
    df_diff_new.set_index('id', inplace=True)
    
    我们将这两个数据帧插入
    面板
    数据结构:

    df_panel=pd.panel(dict(df1=df_diff_old,df2=df_diff_new))

    最后,我们使用自定义函数(
    find_diff
    )和
    apply
    方法进行比较:

    def find_diff(x):
        return x[0] if x[0] == x[1] else '{} -> {}'.format(*x)
    
    df_diff = df_panel.apply(find_diff, axis=0)
    
    如果打印出
    df_diff
    的内容,您可以很容易地注意到在“旧”和“新”数据帧之间更改了哪些值:

    df_old = pd.read_excel('old.xlsx', 'Sheet1', na_values=['NA'])
    df_new = pd.read_excel('new.xlsx', 'Sheet1', na_values=['NA'])
    
    df_old['VER'] = 'OLD'
    df_new['VER'] = 'NEW'
    
        col_num     col_str                             col_datetime
    id              
    1   123         My string 1 -> My string 1 MODIFIED 2001-12-04 00:00:00 
    3   345 -> 789  My string 3                         2001-12-06 00:00:00 -> 2001-12-10 00:00:00
    
    改进 对于这个实现,我将留给您做一些改进

  • 添加一个二进制(1/0)标志,指示 换行
  • 确定删除了“旧”数据框中的哪些行 (即,“新”数据框中不存在)
  • 确定列表中的哪些行 添加了“新”数据帧(即,“旧”数据帧中不存在)
  • 原始答案 问题: 问题是您无法对
    datetimes
    执行算术运算

    但是,您可以对
    时间增量执行算术运算。