Pandas转置行模式不一致的原始数据

g6baxovj  于 2023-02-11  发布在  其他
关注(0)|答案(3)|浏览(154)

我有以下原始数据导出:

import pandas as pd
df = pd.DataFrame({ 
     'Data': ['A15','abc','A25',50,'abc','A30',20,'def','A4','hijk','A',10,'mnop'],

    })
df

我正尝试将此原始数据转置到具有3列的表中:Name, Number and Text
我希望每次出现A时都有一行,因为这是一致的模式。之后总是有一个文本,但有时会有一个数字。如果出现此数字,它总是A之后的直接行。我的预期输出如下:

有什么想法,我可以如何处理这一点?非常感谢!

4ngedf3f

4ngedf3f1#

import re
import pandas as pd
import numpy as np

df = pd.DataFrame({'Data': ['A15', 'abc', 'A25', 50, 'abc', 'A30', 20, 'def', 'A4', 'hijk', 'A', 10, 'mnop']})

转换为列表:

flat_list = df['Data'].tolist()

遍历列表,如果元素匹配A\d+,则添加新子列表,否则追加到最后一个子列表:

nested_list = []
while len(flat_list) > 0:
    element = flat_list.pop(0)
    if re.fullmatch("A\d*", str(element)):
        nested_list.append([element])
    else:
        nested_list[-1].append(element)

如果子列表只有两个项目,则返回到'Number'为np.NaN的字典列表:

as_records = [
    {'Name': l[0], 'Number': l[1], 'text': l[2]} if len(l) == 3 else {'Name': l[0], 'Number': np.NaN, 'text': l[1]} 
    for l in nested_list]

转换为数据框:

df_out = pd.DataFrame(as_records)

该函数返回:

Name  Number  text
0  A15     NaN   abc
1  A25    50.0   abc
2  A30    20.0   def
3   A4     NaN  hijk
4    A    10.0  mnop
hjzp0vay

hjzp0vay2#

您可以定义遮罩并使用pivot

m1 = df['Data'].str.startswith('A')
m2 = m1.isna() #OR: pd.to_numeric(df['Data'], errors='coerce').notna()
m1 = m1.fillna(False)

df2 = (df
 .assign(index=m1.cumsum(),
         col=np.select([m1, m2], ['Name', 'Number'], 'Text')
        )
 .pivot(index='index', columns='col', values='Data')
)

输出:

col   Name Number  Text
index                  
1      A15    NaN   abc
2      A25     50   abc
3      A30     20   def
4       A4    NaN  hijk
5        A     10  mnop

中间体:

Data     m1  m1(v2)     m2  m1(cumsum)
0    A15   True    True  False           1
1    abc  False   False  False           1
2    A25   True    True  False           2
3     50    NaN   False   True           2
4    abc  False   False  False           2
5    A30   True    True  False           3
6     20    NaN   False   True           3
7    def  False   False  False           3
8     A4   True    True  False           4
9   hijk  False   False  False           4
10     A   True    True  False           5
11    10    NaN   False   True           5
12  mnop  False   False  False           5
xytpbqjk

xytpbqjk3#

def function1(dd:pd.DataFrame):
    ss1=dd.loc[df.Data.astype(str).str.isdigit(),"Data"]
    ss2=pd.Index(dd.iloc[1:].Data).difference(ss1)
    return pd.Series(dict(Name=dd.head(1).squeeze(),Number=ss1.max(),text=ss2.max()),name=dd.name)

col1=df.Data.astype(str).str.contains("A").cumsum()
df.groupby(col1).apply(function1).reset_index(drop=True)

出局

Name  Number  text
Data                   
0     A15     NaN   abc
1     A25    50.0   abc
2     A30    20.0   def
3      A4     NaN  hijk
4       A    10.0  mnop

相关问题