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=1
和 Col1
(列名)在 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
填充它。这避免了完全循环,因此它应该可以更好地扩展。
提取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
),但我的想法只是提取行索引(嵌套列表)和列名(列表)。
从提取的行索引和列名称创建一个空 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
用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
输入填sales_df
回Excelsheet:
sales.sheet[0].range('G5').value = sales_df.values.tolist()
我有一个如下所示的数据框
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=1
和 Col1
(列名)在 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
填充它。这避免了完全循环,因此它应该可以更好地扩展。
提取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
),但我的想法只是提取行索引(嵌套列表)和列名(列表)。从提取的行索引和列名称创建一个空
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
用
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
输入填
sales_df
回Excelsheet:sales.sheet[0].range('G5').value = sales_df.values.tolist()