使用python构建混乱数据

2024-09-30 22:21:08 发布

您现在位置:Python中文网/ 问答频道 /正文

我有一组不以制表符或逗号分隔的数据。在记事本中打开时,它看起来非常结构化,如下图所示,但在使用Excel打开时,它的结构不正确

Tuesday 19-April-2010 00:01 CC  11   PQ 1.1  PS1.1 CS# 111 +1 RS113' SC 183 ZA 71
 IFJ   SC/LY     AB  CD?  EF  GH  IJK  LM  NO  PQR  ST  UV  WXY  ZA  BC  DEF GHI
 1234 SC 122      A  20?  31   1   4?  10   3   2?  19   9   5?   -       -?   30
 1234 SC 123  '   B  60?  11   2   3?  10   5   6?  19   9   4?  17   4   1?   30
 1234 SC 124      C  20?  21   2   2?  10   2   1?   9   9   0?   -       -?   34
 1234 SC 125 ^    1 100?   -       -?   0   3   3?   -       -?   -       -?   10
 1234 SC 226 *    5  60?   -       -?  14   4   3?   9   9   2?   7   3   3?   18
A=<43>  B=33  C=24
Tuesday 19-April-2010 00:03 CC  11   PQ 1.1  PS1.1 CS# 111 +1 RS113' SC 183 ZA 71
 IFJ   SC/LY     AB  CD?  EF  GH  IJK  LM  NO  PQR  ST  UV  WXY  ZA  BC  DEF GHI
 1234 SC 122      A  21?  31   5   4?  17   3   2?  19   9   1?   -       -?   31
 1234 SC 123  '   B  61?  11   2   3?  19   5   6?  19   9   4?  17   4   3?   32
 1234 SC 124      C  21?  21   5   2?  10   2   1?   9   9   0?   -       -?   33
 1234 SC 125 ^    1 101?   -       -?   7   3   3?   -       -?   -       -?   14
 0000 SC 226 *    5  61?   -       -?  14   4   3?   9   9   2?   7   3   3?   18

有什么方法可以让我用熊猫来处理这些数据进行分析吗?你知道吗


Tags: 数据ablycdcsghccsc
3条回答

编辑:这是我能得到的最接近正则表达式。不幸的是,任何空白字段(如列GH行4和5)都将无法正确处理,数据将发生倾斜。你知道吗

请注意,我在iPhone上,所以您需要替换所有双引号(“)。你知道吗

正则表达式[^0-9A-Z\?\-]+将匹配任何不符合以下条件的字符:

  • 数字0-9
  • 大写字母
  • 问号
  • 连字符

对于一个或多个组合。。。你知道吗

这将删除奇怪的特殊字符并处理多个空格分隔符。你知道吗

您将在开始处得到一个额外的空白列。你可以用更多的正则表达式来处理这个问题,但是我会留给你做一些家庭作业(宿醉)。你知道吗

SC/LY将被分成两部分。通过两个阶段的划分(不使用熊猫开始),你可能可以处理这个问题。你知道吗

>>> import re
>>> regex_string = r”[^0-9A-Z\?\-\/]+”
>>> p=re.compile(regex_string)
>>> header
' IFJ   SC/LY     AB  CD?  EF  GH  IJK  LM  NO  PQR  ST  UV  WXY  ZA  BC  DEF GHI'
>>> single_row
' 1234 SC 125 ^    1 101?   -       -?   7   3   3?   -       -?   -       -?   10'
>>> p.split(header)
['', 'IFJ', 'SC' , 'LY', 'AB', 'CD?', 'EF', 'GH', 'IJK', 'LM', 'NO', 'PQR', 'ST', 'UV', 'WXY', 'ZA', 'BC', 'DEF', 'GHI']
>>> p.split(single_row)
['', '1234', 'SC', '125', '1', '101?', '-', '-?', '7', '3', '3?', '-', '-?', '-', '-?', '10']

对于熊猫来说,这看起来像:

>>> import pandas
>>> df = pandas.read_csv(filepath, skiprows=1, header=True, delimiter= r”[^0-9A-Z\?\-]+”, engine=“python”)

您的第二行似乎是实际的标题。不过,正如梅德温所指出的,这看起来还是不对的。你知道吗

通常,您可以尝试:

import pandas as pd

df = pd.read_csv(<your csv), skiprows=1, delim_whitespace=True)
print(df.head())

但这将无法正常工作,因为CSV的结构不一致。你知道吗

我建议您首先使用一个脚本将数据转换成合适的CSV格式,然后可以使用Pandas毫无问题地加载。你知道吗

大多数数据都是固定宽度的格式,因此列位置可以硬编码,并应用strip()删除任何空格。可以从时间戳行中提取时间和日期,并将其添加到其中每个条目的开头。你知道吗

^{}用于以块的形式读取文件,这还具有跳过段之间不需要的行的效果。它的工作原理是一次读取一行文件,然后将每一行传递给key函数(这是使用lambda函数内联提供的,以节省空间)。如果函数的结果更改,groupby函数将返回具有相同返回的行的列表。在本例中,它正在测试行是否以A=<字符开头。因此您得到一个返回,其中keyTrue包含以时间戳开始的行列表。然后是以A=<开头的行列表(在本例中只有一行)。这使得处理整个片段更容易,而不必担心它在哪里完成。第一个条目是时间戳,后跟所有条目。你知道吗

列表理解用于从行中提取每个单独的值,并创建值的row^{}配方用于从cols读取固定列位置,以获得滑动startend列位置。它们用作字符串片段,用于提取每列的字符。然后,该字符串应用.strip()来删除任何周围的空格。你知道吗

from itertools import groupby, tee
import csv

def pairwise(iterable):
    "s -> (s0,s1), (s1,s2), (s2, s3), ..."
    a, b = tee(iterable)
    next(b, None)
    return zip(a, b)

cols = [0, 5, 12, 15, 19, 24, 28, 32, 37, 41, 45, 50, 54, 58, 63, 68, 71, 76] # + rest
header = None

with open('data.txt') as f_input, open('output.csv', 'w', newline='') as f_output:
    csv_output = csv.writer(f_output)

    for key, group in groupby(f_input, lambda x: not x.startswith('A=<')):
        if key:
            # Extract the timestamp from the first returned line in the segment
            # Split the line on spaces and take the first 3 elements
            timestamp = next(group).split()[:3]
            block = []

            for line in group:
                row = [line[start:end].strip() for start, end in pairwise(cols)]
                row.append(line[cols[-1]:].strip())     # Add GHI column
                block.append(timestamp + row)

            if not header:
                header = block[0][3:]
                header[2] = 'Unknown'
                csv_output.writerow(['Day', 'Date', 'Time'] + header)

            csv_output.writerows(block[1:])

对于你提供的数据,这将给你

Day,Date,Time,IFJ,SC/LY,Unknown,AB,CD?,EF,GH,IJK,LM,NO,PQR,ST,UV,WXY,ZA,BC,DEF,GHI
Tuesday,19-April-2010,00:01,1234,SC 122,,A,20?,31,1,4?,10,3,2?,19,9,5?,-,,-?,30
Tuesday,19-April-2010,00:01,1234,SC 123,',B,60?,11,2,3?,10,5,6?,19,9,4?,17,4,1?,30
Tuesday,19-April-2010,00:01,1234,SC 124,,C,20?,21,2,2?,10,2,1?,9,9,0?,-,,-?,34
Tuesday,19-April-2010,00:01,1234,SC 125,^,1,100?,-,,-?,0,3,3?,-,,-?,-,,-?,10
Tuesday,19-April-2010,00:01,1234,SC 226,*,5,60?,-,,-?,14,4,3?,9,9,2?,7,3,3?,18
Tuesday,19-April-2010,00:03,1234,SC 122,,A,21?,31,5,4?,17,3,2?,19,9,1?,-,,-?,31
Tuesday,19-April-2010,00:03,1234,SC 123,',B,61?,11,2,3?,19,5,6?,19,9,4?,17,4,3?,32
Tuesday,19-April-2010,00:03,1234,SC 124,,C,21?,21,5,2?,10,2,1?,9,9,0?,-,,-?,33
Tuesday,19-April-2010,00:03,1234,SC 125,^,1,101?,-,,-?,7,3,3?,-,,-?,-,,-?,14
Tuesday,19-April-2010,00:03,0000,SC 226,*,5,61?,-,,-?,14,4,3?,9,9,2?,7,3,3?,18

为了更好地理解脚本的实际工作方式,我建议您添加一个小的测试文件(带有两个段),然后还添加一些print语句。你知道吗

相关问题 更多 >