根据值合并行(熊猫到 excel - xlsxwriter)

Posted

技术标签:

【中文标题】根据值合并行(熊猫到 excel - xlsxwriter)【英文标题】:Merge rows based on value (pandas to excel - xlsxwriter) 【发布时间】:2020-07-27 18:50:15 【问题描述】:

我正在尝试使用 xlsxwriter 将 Pandas 数据框输出到 excel 文件中。但是我正在尝试应用一些基于规则的格式;特别是试图合并具有相同值的单元格,但在想出如何编写循环时遇到了麻烦。 (这里是 Python 新手!)

输出与预期输出见下文:

(正如您根据上图看到的那样,当单元格具有相同的值时,我正在尝试合并“名称”列下的单元格)。

这是我目前所拥有的:

#This is the logic you use to merge cells in xlsxwriter (just an example)
worksheet.merge_range('A3:A4','value you want in merged cells', merge_format)

#Merge Car type Loop thought process...
#1.Loop through data frame where row n Name = row n -1 Name
#2.Get the length of the rows that have the same Name
#3.Based off the length run the merge_range function from xlsxwriter, worksheet.merge_range('range_found_from_loop','Name', merge_format)


for row_index in range(1,len(car_report)):
     if car_report.loc[row_index, 'Name'] == car_report.loc[row_index-1, 'Name'] 
     #find starting point based off index, then get range by adding number of rows to starting point. for example lets say rows 0-2 are similar I would get 'A0:A2' which I can then put in the code below
     #from there apply worksheet.merge_range('A0:A2','[input value]', merge_format)

非常感谢任何帮助!

谢谢!

【问题讨论】:

你能澄清一下具体是什么问题吗?请提供minimal reproducible example。此外,除非绝对必要,否则请不要将信息作为图像共享。请参阅:meta.***.com/questions/303812/…、idownvotedbecau.se/imageofcode、idownvotedbecau.se/imageofanexception。 @AMC 图像中没有代码。该图像是 excel 文件应该是什么样子的输出。代码在代码部分。 无论是代码还是数据,都适用相同的参数。 @AMC 让我知道它让您感到困惑的地方。问题是我不知道如何创建一个循环来查看前面的行,找到相似的值,并将合并函数应用于具有相同值的所有行;然后随后对整个数据帧执行此操作。 (请参阅图片,了解我正在尝试做的事情)。 您是否尝试过在纸上解决问题,编写伪代码之类的? 【参考方案1】:

您的逻辑几乎是正确的,但是我通过稍微不同的方法解决了您的问题:

1) 对列进行排序,确保所有值都分组在一起。

2) 重置索引(使用 reset_index() 并可能传递 arg drop=True)。

3) 然后我们必须捕获值是新的行。为此,创建一个列表并添加第一行 1,因为我们肯定会从那里开始。

4) 然后开始迭代该列表的行并检查一些条件:

4a) 如果我们只有一行有值,merge_range 方法会报错,因为它不能合并一个单元格。在这种情况下,我们需要将 merge_range 替换为 write 方法。

4b) 使用此算法,您将在尝试写入列表的最后一个值时出现索引错误(因为它会将其与下一个索引位置中的值进行比较,并且因为它是列表的最后一个值没有下一个索引位置)。所以我们需要特别提到,如果我们得到一个索引错误(这意味着我们正在检查最后一个值)我们想要合并或写入直到数据帧的最后一行。

4c) 最后我没有考虑该列是否包含空白或空单元格。在这种情况下,需要调整代码。

最后的代码可能看起来有点混乱,您必须记住,pandas 的第一行索引为 0(标题是单独的),而 xlsxwriter 的标题索引为 0,第一行索引为 1。

这是一个工作示例,可以准确地实现您想要做的事情:

import pandas as pd

# Create a test df
df = pd.DataFrame('Name': ['Tesla','Tesla','Toyota','Ford','Ford','Ford'],
                   'Type': ['Model X','Model Y','Corolla','Bronco','Fiesta','Mustang'])

# Create the list where we 'll capture the cells that appear for 1st time,
# add the 1st row and we start checking from 2nd row until end of df
startCells = [1]
for row in range(2,len(df)+1):
    if (df.loc[row-1,'Name'] != df.loc[row-2,'Name']):
        startCells.append(row)


writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1', index=False)
workbook = writer.book
worksheet = writer.sheets['Sheet1']
merge_format = workbook.add_format('align': 'center', 'valign': 'vcenter', 'border': 2)


lastRow = len(df)

for row in startCells:
    try:
        endRow = startCells[startCells.index(row)+1]-1
        if row == endRow:
            worksheet.write(row, 0, df.loc[row-1,'Name'], merge_format)
        else:
            worksheet.merge_range(row, 0, endRow, 0, df.loc[row-1,'Name'], merge_format)
    except IndexError:
        if row == lastRow:
            worksheet.write(row, 0, df.loc[row-1,'Name'], merge_format)
        else:
            worksheet.merge_range(row, 0, lastRow, 0, df.loc[row-1,'Name'], merge_format)


writer.save()

输出:

【讨论】:

感谢您的解决方案。如果我的多列中有需要合并的行,您将如何更新代码? 你好丽莎,我不确定我是否正确理解了你的要求。也许提出一个单独的问题并联系我,让我看看? 嘿 Dimitris,我在这里发布了一个新的 ***.com/questions/68208503/… 提前感谢 ;) 我看到有人已经发布了一个答案,这是一行!我需要更多的行才能完成这项工作,但我很高兴有人在这方面帮助了你。 如何合并像 B2、C2 这样的单元格【参考方案2】:

替代方法: 可以使用 unique() 函数来查找分配给每个唯一值(本例中为汽车名称)的索引。使用上述测试数据,

import pandas as pd

# Create a test df
df = pd.DataFrame('Name': ['Tesla','Tesla','Toyota','Ford','Ford','Ford'],
                   'Type': ['Model X','Model Y','Corolla','Bronco','Fiesta','Mustang'])

writer = pd.ExcelWriter('test.xlsx', engine='xlsxwriter')
df.to_excel(writer, sheet_name='Sheet1', index=False)
workbook = writer.book
worksheet = writer.sheets['Sheet1']
merge_format = workbook.add_format('align': 'center', 'valign': 'vcenter', 'border': 2)

for car in df['Name'].unique():
    # find indices and add one to account for header
    u=df.loc[df['Name']==car].index.values + 1

    if len(u) <2: 
        pass # do not merge cells if there is only one car name
    else:
        # merge cells using the first and last indices
        worksheet.merge_range(u[0], 0, u[-1], 0, df.loc[u[0],'Name'], merge_format)
writer.save()

【讨论】:

以上是关于根据值合并行(熊猫到 excel - xlsxwriter)的主要内容,如果未能解决你的问题,请参考以下文章

ValueError 将多索引熊猫数据框转换为 Excel

根据列值从熊猫数据框中提取行

如何合并熊猫中的重复行?

如何根据合并的数据框之一的两列的值在熊猫数据框中添加值

熊猫,根据行中的值创建列

熊猫内部合并/加入返回所有行