我有pandas pand

    data = {
    'sec_id': ['1', '', '1.2', '1.3', '1.3.1', '1.3.2', '2', '2.1', '2.2', '2.3', '', '2.3.2', '2.3.3', '3', '4', '4.1', '4.1.1', '4.2', '4.3', '4.4', '5', '5.1', '5.2', '5.3', '5.3.1', '5.3.2', '5.3.3', '5.3.4', '5.3.5', '5.4', '5.5', '6', '6.1', '6.1.1', '6.2', '6.3', '6.4', '6.5', '6.6', '6.6.1', '6.6.2', '6.6.3', '6.7', '6.8', '6.9', '6.9.1', '', '', '6.9.2'],
    'p_type': ['Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading1', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading4', 'Heading4', 'Heading3']
}
df = pd.DataFrame(data)

问题是用准确的节ID值填充空白的"document_section_id"值,并使用前面的节ID值作为参考.

条件:

  1. 位数由"段落类型"一栏决定.例如,对于"Heading3",应该有4位数和3个点,如下所示:1.2.3.1.

  2. 对于每个空值,它应该引用前面可用的"段落类型",并相应地递增1. 示例1:给定输入,第12行的节ID可以从前一行派生,从而得到计算值2.3.1.示例2: 对于第48行和第49行,节ID需要分别派生为6.9.1.1和6.9.1.2.

最多可以有10个级别的子节,所以无论子节的数量如何,都应加以注意.

输出:

   sec_id = [
    '1', '1.1', '1.2', '1.3', '1.3.1', '1.3.2', '2', '2.1', '2.2', '2.3', 
    '2.3.1', '2.3.2', '2.3.3', '3', '4', '4.1', '4.1.1', '4.2', '4.3', 
    '4.4', '5', '5.1', '5.2', '5.3', '5.3.1', '5.3.2', '5.3.3', '5.3.4', 
    '5.3.5', '5.4', '5.5', '6', '6.1', '6.1.1', '6.2', '6.3', '6.4', 
    '6.5', '6.6', '6.6.1', '6.6.2', '6.6.3', '6.7', '6.8', '6.9', '6.9.1', 
    '6.9.1.1', '6.9.1.2', '6.9.2'
]

p_type = [
    'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 
    'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 
    'Heading3', 'Heading1', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 
    'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 
    'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading2', 
    'Heading2', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 'Heading2', 
    'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 'Heading3', 
    'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading4', 
    'Heading4', 'Heading3'
]

这是我try 过的,但它没有给出准确的输出:

current_section_id = ""
current_level = 0

for index, row in df.iterrows():
    if row['sec_id'] == '':
        current_level += 1
        section_id = current_section_id.split('.')
        section_id[current_level - 1] = str(int(section_id[current_level - 1]) + 1)
        section_id = '.'.join(section_id[:current_level])
        current_section_id = section_id
        df.at[index, 'document_section_id'] = section_id
    else:
        current_section_id = row['sec_id']
        current_level = row['paragraph_type'].count('Heading') - 1

推荐答案

我不认为你需要在Pandas 做这个. 您可以创建一个类,跟踪当前节并将其提升1,或附加子节,或根据段落类型进行截断和递增.

下面是一个例子:

class SectionCreator:
    def __init__(self):
        self.section = [0]

    def __call__(self, paragraph_type: str):
        depth = int(paragraph_type.replace('Heading', ''))
        section = self.section[:depth]
        if depth == len(section) + 1:
            section.append(1)
        elif depth > len(section) + 1:
            raise ValueError(f'Heading depth increased from {len(section)} to {depth}')
        else:
            section[depth - 1] += 1
        self.section = section
        return '.'.join(map(str, self.section))

要使用它,实例化对象并每次传递一个段落类型.

headings = ['Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 
'Heading3', 'Heading1', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 
'Heading3', 'Heading3', 'Heading1', 'Heading1', 'Heading2', 'Heading3', 
'Heading2', 'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading2', 
'Heading2', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 'Heading3', 
'Heading2', 'Heading2', 'Heading1', 'Heading2', 'Heading3', 'Heading2', 
'Heading2', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading3', 
'Heading3', 'Heading2', 'Heading2', 'Heading2', 'Heading3', 'Heading4', 
'Heading4', 'Heading3']

sc = SectionCreator()

for h in headings:
    print(sc(h))

打印输出为:

1
1.1
1.2
1.3
1.3.1
1.3.2
2
2.1
2.2
2.3
2.3.1
2.3.2
2.3.3
3
4
4.1
4.1.1
4.2
4.3
4.4
5
5.1
5.2
5.3
5.3.1
5.3.2
5.3.3
5.3.4
5.3.5
5.4
5.5
6
6.1
6.1.1
6.2
6.3
6.4
6.5
6.6
6.6.1
6.6.2
6.6.3
6.7
6.8
6.9
6.9.1
6.9.1.1
6.9.1.2
6.9.2

我添加了一个例外情况,即段落类型 skip 超过1级深度. 所以从2到4会引发一个异常.

sc = SectionCreator()
sc('Heading1')    # -> "1"
sc('Heading2')    # -> "1.1"
sc('Heading4')
# raises:
ValueError: Heading depth increased from 2 to 4

Python相关问答推荐

如何在Windows上用Python提取名称中带有逗号的文件?

从numpy数组和参数创建收件箱

基于索引值的Pandas DataFrame条件填充

创建可序列化数据模型的最佳方法

如何根据一列的值有条件地 Select 前N组?

Pandas Loc Select 到NaN和值列表

需要帮助重新调整python fill_between与数据点

使用Python和文件进行模糊输出

如何从列表框中 Select 而不出错?

dask无groupby(ddf. agg([min,max])?''''

基于行条件计算(pandas)

合并与拼接并举

如何从pandas DataFrame中获取. groupby()和. agg()之后的子列?

504未连接IB API TWS错误—即使API连接显示已接受''

对于标准的原始类型注释,从键入`和`从www.example.com `?

遍历列表列表,然后创建数据帧

Django更新视图未更新

如何在PYTHON中向单元测试S Side_Effect发送额外参数?

Scipy.linprog的可行性有问题吗?(A_ub@x0<;=b_ub).all()为True-但是-linprog(np.zeros_like(X0),A_ub=A_ub,b_ub=b_ub)不可行

Pandas:使列中的列表大小与另一列中的列表大小相同