Pandas - 比较 excel 和数据框之间的索引和列以输入值

Pandas - compare index and column between excel and dataframe to enter value

我有一个如下所示的数据框

ID,DIV,APP1,APP2,APP3,Col1,Col4
1,A,AB1,ABC1,ABCD1,20,40
2,A,AB1,ABC2,ABCD2,60,
3,B,BC1,BCD1,BCDE1,10,20

region_1 = pd.read_clipboard(sep=',') 
region_1.set_index(['ID','DIV','APP1','APP2','APP3'],inplace=True)

我有一个 excel 文件,如下所示。您可以从 here

下载它们

如果数据的索引和列名与我的数据框索引和列名匹配,我想将数据输入到 excel 文件中。例如:ID=1Col1(列名)在 excel 和数据框列之间匹配。因此,我们在相应的单元格中输入 in/enter 值 20。

我正在尝试类似下面的操作

all_rows = sales.sheets[0]['B5:B8'].value
region_1_cols = sales.sheets[0]['G3:J3'].value
sales.sheets[0]['G5'].value = region_1.reindex(columns=cols,index=rows)

但这行不通。

根据 SO 的建议,我尝试了以下方法

ws = sales.sheets[0] 
ws.range('G5').options(index=False).value = region_1.astype(str).reset_index(drop=True)

但它在 excel 中键入值时没有进行任何列名检查或 ID 值检查

是否有任何迭代方法可以使用 for 循环等来执行此操作。我们需要保留 excel 的格式。因此,我们根据匹配条件一一输入值。

我希望我的输出如下所示

由于没有答案,我不得不自己回答 post。但是,我确实欢迎任何优雅有效的解决方案。我可以将您的回答标记为已接受。不管怎样,你可以看看我下面的代码

df_value = region_1['ID'].tolist()
for val in df_value:
    for a_cell in sales.sheets[0]['B5:B8']:
        if a_cell.value == val:
            rn1 = a_cell.row
            temp = region_1.loc[[val]]
            temp = temp.dropna(axis=1, how='all')
            colu = temp.columns.tolist()
            for col in colu:
                for b_cell in sales.sheets[0]['G3:J3']:
                    if b_cell.value == col:
                        rn2 = b_cell.row
                        data_entry_loc = str(b_cell.address[1]) + str(rn1)
                        enter_val = temp[col].values
                        sales.sheets[0][data_entry_loc].value = enter_val

虽然这可行,但我不确定这是否可以扩展到大数据解决方案。

欢迎任何更好的方法

DataFrame.fillna 可以接受填充值的整个 DataFrame,在这种情况下,它通过匹配 row/column 标签来填充缺失值。

因此,基于 Excel table 创建一个空的 DataFrame 并用 region_1 填充它。这避免了完全循环,因此它应该可以更好地扩展。

  1. 提取Exceltable的行索引和列名:

    sales_index = sales.sheets[0].range((5, 2), (8, 6)).value
    # [[1, 'A', 'AB1', 'ABC1', 'ABCD1'],
    #  [2, 'A', 'AB1', 'ABC2', 'ABCD2'],
    #  [3, 'B', 'BC1', 'BCD1', 'BCDE1'],
    #  [4, 'B', 'BC1', 'BCD2', 'BCDE2']]
    
    sales_columns = sales.sheets[0].range('G3:J3').value
    # ['Col1', 'Col2', 'Col3', 'Col4']
    

    注意:可能需要调整确切的 xlwings 命令(我无权访问 Linux 上的 xlwings),但我的想法只是提取行索引(嵌套列表)和列名(列表)。

  2. 从提取的行索引和列名称创建一个空 sales_df

    sales_df = (pd.DataFrame(sales_index, columns=region_1.index.names)
                  .set_index(region_1.index.names)
                  .reindex(columns=sales_columns))
    #                         Col1  Col2  Col3  Col4
    # ID DIV APP1 APP2 APP3                         
    # 1  A   AB1  ABC1 ABCD1   NaN   NaN   NaN   NaN
    # 2  A   AB1  ABC2 ABCD2   NaN   NaN   NaN   NaN
    # 3  B   BC1  BCD1 BCDE1   NaN   NaN   NaN   NaN
    # 4  B   BC1  BCD2 BCDE2   NaN   NaN   NaN   NaN
    
  3. region_1填充sales_df:

    sales_df = sales_df.fillna(region_1)
    #                         Col1  Col2  Col3  Col4
    # ID DIV APP1 APP2 APP3                         
    # 1  A   AB1  ABC1 ABCD1    20   NaN   NaN    40
    # 2  A   AB1  ABC2 ABCD2    60   NaN   NaN   NaN
    # 3  B   BC1  BCD1 BCDE1    10   NaN   NaN    20
    # 4  B   BC1  BCD2 BCDE2   NaN   NaN   NaN   NaN
    
  4. 输入填sales_df回Excelsheet:

    sales.sheet[0].range('G5').value = sales_df.values.tolist()