为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

湖上湖 2023-02-15 15:55:55
我们有来自测量多个部件的设备的数据,并将每个部件的多个测量结果输出到一个 CSV 文件中。我们将 CSV 文件读入具有如下结构的数据帧:PartNo  12Meas1   45Meas2   23!ENDPartNo  13Meas1   63Meas2   73!ENDPartNo  12Meas1   82Meas2   84!END“!END”标志表示一个部分的数据在哪里结束,下一个部分从哪里开始。我们想重塑数据,使其看起来像:PartNo  Meas1   Meas212      45      2313      63      7312      82      84(请注意,一个部分可能出现不止一次 - 因此没有字段保证在所有记录中都是唯一的。)枢轴产生:0   !END  Meas1  Meas2  PartNo0    NaN    NaN    NaN    12.01    NaN   45.0    NaN     NaN2    NaN    NaN   23.0     NaN3    NaN    NaN    NaN     NaN4    NaN    NaN    NaN    13.05    NaN   63.0    NaN     NaN6    NaN    NaN   73.0     NaN7    NaN    NaN    NaN     NaN8    NaN    NaN    NaN    12.09    NaN   82.0    NaN     NaN10   NaN    NaN   84.0     NaN11   NaN    NaN    NaN     NaN我如何压缩这些行以按 PartNo 分组?转置产生:       0      1      2     3       4      5      6     7       8      9      10    110  PartNo  Meas1  Meas2  !END  PartNo  Meas1  Meas2  !END  PartNo  Meas1  Meas2  !END1      12     45     23   NaN      13     63     73   NaN      12     82     84   NaN我怎样才能每第 4 个项目重置该行?我可以在原始数据框中创建一个新的索引列,然后遍历行,使用 !END 为每一行递增索引(然后使用索引对数据进行分组),但似乎应该有一个更优雅的方法变形函数来处理这种情况,或者可能有一个 Pivot 或 Transpose 的参数可以处理这种情况。我是 Python 初学者。这是完整的代码:import pandas as pdfrom io import StringIOtdata = ('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)
查看完整描述

4 回答

?
当年话下

TA贡献1890条经验 获得超9个赞

#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


查看完整回答
反对 回复 2023-02-15
?
皈依舞

TA贡献1851条经验 获得超3个赞

这是我会怎么做。我会将文件解析为任何文本文件,然后根据我需要的字段创建记录。我会使用 '!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,如下所示:-

//img1.sycdn.imooc.com//63ec902f000141fb05670358.jpg

查看完整回答
反对 回复 2023-02-15
?
GCT1015

TA贡献1827条经验 获得超4个赞

该文件不是 csv 文件,因此使用 csv 模块解析它无法产生正确的输出。它不是众所周知的格式,所以我会使用自定义解析器:


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)


查看完整回答
反对 回复 2023-02-15
?
墨色风雨

TA贡献1853条经验 获得超6个赞

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


df = df[df[0] != '!END']

out = df.groupby(0).agg(list).T.apply(lambda x: x.explode(), axis=0)

输出:


0 Meas1 Meas2 PartNo

1    45    23     12

1    63    73     13

1    82    84     12

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


查看完整回答
反对 回复 2023-02-15
  • 4 回答
  • 0 关注
  • 184 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号