我有一组不是制表符或逗号分隔的数据。在记事本中打开时,其结构看起来如下图所示,但在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
我是否可以使用熊猫处理此类数据以进行某些分析?
答案 0 :(得分:1)
我建议您先使用脚本将数据转换为合适的CSV格式,然后使用Pandas可以毫无问题地加载它。
大多数数据似乎都采用固定宽度格式,因此可以对列位置进行硬编码,并应用strip()
来删除任何空白。可以从时间戳记行中提取时间和日期,并将其添加到其中的每个条目的开头。
groupby()
用于按块读取文件,这还具有跳过段之间不需要的行的效果。它的工作方式是一次读取一行文件,然后将每一行传递给key
函数(使用lambda
函数内联提供以节省空间)。如果函数的结果更改,groupby函数将返回具有相同返回值的行的列表。在这种情况下,它将测试行是否不以A=<
字符开头。因此,您得到一个返回,其中key
是True
,其中包含以时间戳开头的行列表。然后是一行以A=<
开头的行的列表(在本例中为一个)。这使得处理整个片段变得更加容易,而不必担心片段的完成位置。第一个条目是时间戳,然后是所有条目。
列表推导用于从行中提取每个单独的值并创建值row
。 pairwise()
配方用于从cols
读取固定的列位置,以获得滑动的start
和end
列位置。这些用作字符串切片以提取每一列的字符。然后,该字符串已应用.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
为了更好地了解脚本的实际工作方式,我建议您添加创建一个小的测试文件(分为两个部分),然后添加一些打印语句。
答案 1 :(得分:0)
您的第二行似乎是实际的标题。但随后,正如MEdwin指出的那样,它看起来并不正确。
通常,您可以尝试:
import pandas as pd
df = pd.read_csv(<your csv), skiprows=1, delim_whitespace=True)
print(df.head())
但是,由于CSV的结构不一致,因此无法正常工作。
答案 2 :(得分:0)
编辑:这是我能用正则表达式得到的最接近的东西。不幸的是,任何空白字段(例如列GH
的第4&5行)都将无法正确处理,并且数据会出现偏差。
请注意,我使用的是iPhone,因此您需要替换所有双引号(“)。
正则表达式[^0-9A-Z\?\-]+
会匹配所有不符合以下条件的字符:
对于一种或多种组合...
这将删除奇怪的特殊字符并处理多个空格分隔符。
最后,您将在开头添加一个空白列。您可以使用更多的正则表达式来解决这个问题,但是我会把它留给您来做一些家庭作业(悬停)。
列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”)