繁体   English   中英

如何使用 Python 将一系列重复的数据行转换为多条记录的列?

[英]How do I convert a series of repeated data rows into columns of multiple records using Python?

我们有来自测量多个部件的设备的数据,它将每个部件的多个测量结果输出到 CSV 文件中。 我们将 CSV 文件读取到 dataframe 中,其结构如下:

PartNo  12
Meas1   45
Meas2   23
!END
PartNo  13
Meas1   63
Meas2   73
!END
PartNo  12
Meas1   82
Meas2   84
!END

“,END”标志表示来自某一部分的数据在哪里结束。 下一部分开始:我们想重塑数据,使其看起来像:

PartNo  Meas1   Meas2
12      45      23
13      63      73
12      82      84

(请注意,一个部分可能会出现不止一次 - 因此没有一个字段可以保证在所有记录中都是唯一的。)

pivot 产生:

0   !END  Meas1  Meas2  PartNo
0    NaN    NaN    NaN    12.0
1    NaN   45.0    NaN     NaN
2    NaN    NaN   23.0     NaN
3    NaN    NaN    NaN     NaN
4    NaN    NaN    NaN    13.0
5    NaN   63.0    NaN     NaN
6    NaN    NaN   73.0     NaN
7    NaN    NaN    NaN     NaN
8    NaN    NaN    NaN    12.0
9    NaN   82.0    NaN     NaN
10   NaN    NaN   84.0     NaN
11   NaN    NaN    NaN     NaN

如何将这些行压缩到按 PartNo 分组?
转置产生:

       0      1      2     3       4      5      6     7       8      9      10    11
0  PartNo  Meas1  Meas2  !END  PartNo  Meas1  Meas2  !END  PartNo  Meas1  Meas2  !END
1      12     45     23   NaN      13     63     73   NaN      12     82     84   NaN

我怎样才能每 4 项重置该行?

我可以在原始 dataframe 中创建一个新的索引列,然后遍历行,用 END 为每一行增加索引(然后使用索引对数据进行分组),但似乎应该有一个更优雅变形 function 来处理这种情况。 或者 Pivot 或 Transpose 有一个参数可以处理这个问题。 我是 Python 初学者:这是完整代码:

import pandas as pd
from io import StringIO

tdata = (
'PartNo,    12\n'
'Meas1, 45\n'
'Meas2, 23\n'
'!END\n'
'PartNo,    13\n'
'Meas1, 63\n'
'Meas2, 73\n'
'!END\n'
'PartNo,    12\n'
'Meas1, 82\n'
'Meas2, 84\n'
'!END\n')
tdf = pd.read_csv(StringIO(tdata), header=None)
print(tdf)
print(tdf.pivot(index=None, columns=0, values=1))
print(tdf.T)

该文件不是 csv 文件,因此使用 csv 模块对其进行解析无法生成正确的 output。 这不是一种众所周知的格式,所以我会使用自定义解析器:

with open(filename) as fd:
    data  = []
    row = None
    for line in fd:
        line = line.strip()
        if line == '!END':
            row = None
        else:
            k,v = line.split(None, 1)
            if row is None:
                row = {k : v}
                data.append(row)
            else:
                row[k] = v

header = set(i for row in data for i in row.keys())
df = pd.DataFrame(data, columns=header)

根据提供的信息,我认为您应该能够使用这种方法实现您想要的:

df = df[df[0] != '!END']
out = df.groupby(0).agg(list).T.apply(lambda x: x.explode(), axis=0)

output:

0 Meas1 Meas2 PartNo
1    45    23     12
1    63    73     13
1    82    84     12

这基本上按 PartNo、Meas1 和 Meas2 键对原始 df 进行分组,并为每个列表创建一个列表。然后它将每个列表分解为一个 pd.Series,从而为每个列表创建一个列,其中行数等于条目数每个键(都应该相同)

#having dataframe x:
>>> x = pd.DataFrame([['PartNo',12],['Meas1',45],['Meas2',23],['!END',''],['PartNo',13],['Meas1',63],['Meas2',73],['!END',''],['PartNo',12],['Meas1',82],['Meas2',84],['!END','']])
>>> x
         0   1
0   PartNo  12
1    Meas1  45
2    Meas2  23
3     !END    
4   PartNo  13
5    Meas1  63
6    Meas2  73
7     !END    
8   PartNo  12
9    Meas1  82
10   Meas2  84
11    !END    

#grouping by first column, and aggregating values to list. First column then contains Series that you want. By converting each list in this series to series, dataframe is created, then you just need to transpose
>>> df = x.groupby(0).agg(lambda x: list(x))[1].apply(lambda x: pd.Series(x)).transpose()
>>> df[['PartNo','Meas1','Meas2']]
0 PartNo Meas1 Meas2
0     12    45    23
1     13    63    73
2     12    82    84

这是我将如何做到的。 我会将文件解析为任何文本文件,然后根据我需要的字段创建记录。 我将使用“!END”行作为完成行创建的指示符,将其写入列表,然后最终将列表转换为 DataFrame

import pandas as pd

filename='PartDetail.csv'
with open(filename,'r') as file:
    LinesFromFile=file.readlines()
    
RowToWrite=[]
for EachLine in LinesFromFile:
    ValuePosition=EachLine.find(" ")+1
    CurrentAttrib=EachLine[0:ValuePosition-1]
    if CurrentAttrib=='PartNo':
        PartNo=EachLine[ValuePosition+1:len(EachLine)-1].strip()
    if CurrentAttrib=='Meas1':
        Meas1=EachLine[ValuePosition+1:len(EachLine)-1].strip()
    if CurrentAttrib=='Meas2':
        Meas2=EachLine[ValuePosition+1:len(EachLine)-1].strip()
    if EachLine[0:4]=='!END':
        RowToWrite.append([PartNo,Meas1,Meas2])
        
PartsDataDF=pd.DataFrame(RowToWrite,columns=['PartNo','Meas1','Meas2']) #Converting to DataFrame

这将为您提供更清洁的 DataFrame,如下所示:-

在此处输入图像描述

希望能帮助到你。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM