Python-从数据行中提取并重新格式化字段名
我有一个平面文本文件(infle),我想重新构造。它有几个以制表符分隔的列,如下所示:Python-从数据行中提取并重新格式化字段名,python,regex,text,dictionary,header,Python,Regex,Text,Dictionary,Header,我有一个平面文本文件(infle),我想重新构造。它有几个以制表符分隔的列,如下所示: Person1 HEIGHT=60;WEIGHT=100;AGE=22 Person2 HEIGHT=62;WEIGHT=101;AGE=25 Person3 HEIGHT=64;WEIGHT=110;AGE=29 PERSON HEIGHT WEIGHT AGE 1 60 100 22 2 62
Person1 HEIGHT=60;WEIGHT=100;AGE=22
Person2 HEIGHT=62;WEIGHT=101;AGE=25
Person3 HEIGHT=64;WEIGHT=110;AGE=29
PERSON HEIGHT WEIGHT AGE
1 60 100 22
2 62 101 25
3 64 110 29
我希望它看起来像这样:
Person1 HEIGHT=60;WEIGHT=100;AGE=22
Person2 HEIGHT=62;WEIGHT=101;AGE=25
Person3 HEIGHT=64;WEIGHT=110;AGE=29
PERSON HEIGHT WEIGHT AGE
1 60 100 22
2 62 101 25
3 64 110 29
您可以看到,第二列实际上包含几个以分号分隔的标题/值字段,我想将它们重新构造为典型的列标题行
现在我有:
for line in infile:
line = line.split("\t")
line_meta = line[1].split(";")
print line_meta
我认为最好的解决方案是现在循环行\元变量,使用正则表达式检测标题名称(检测以多个大写字母开头,以“=”\结尾的字符串),将每个标题作为键添加到字典中,然后将字符串的其余部分作为值存储。然后,对于下一行,如果检测到相同的头,只需将其附加到现有字典中
是否有人可以在此代码方面提供帮助或提供有关如何继续的反馈
多谢各位
编辑:感谢您的回复。在本例中,我简化了数据,但下面是一个实际的元列的外观(仍然是分隔的,但值类型是混合的):
您可以只使用一个正则表达式来拆分键=值对:
import re
key_value = re.compile('(?P<key>[A-Z]+)=(?P<value>\[^\s=;]+)(?:(?=;)|$)')
(?:…)
组是非捕获组;此处仅用于标记|
或符号所适用的内容。模式匹配=
符号前的大写字符,以及任何非空白的字符,如=
或代码>字符,前提是有一个
或值后面的字符串结尾
这将为每行拆分键和值:
>>> key_value = re.compile('(?P<key>[A-Z]+)=(?P<value>[^\s=;]+)(?:(?=;)|$)')
>>> key_value.findall('Person1\tHEIGHT=60;WEIGHT=100;AGE=22')
[('HEIGHT', '60'), ('WEIGHT', '100'), ('AGE', '22')]
然后,您可以使用以下方法编写这些内容,例如:
您可以只使用一个正则表达式来拆分键=值对:
import re
key_value = re.compile('(?P<key>[A-Z]+)=(?P<value>\[^\s=;]+)(?:(?=;)|$)')
(?:…)
组是非捕获组;此处仅用于标记|
或符号所适用的内容。模式匹配=
符号前的大写字符,以及任何非空白的字符,如=
或代码>字符,前提是有一个
或值后面的字符串结尾
这将为每行拆分键和值:
>>> key_value = re.compile('(?P<key>[A-Z]+)=(?P<value>[^\s=;]+)(?:(?=;)|$)')
>>> key_value.findall('Person1\tHEIGHT=60;WEIGHT=100;AGE=22')
[('HEIGHT', '60'), ('WEIGHT', '100'), ('AGE', '22')]
然后,您可以使用以下方法编写这些内容,例如:
你可以试试这个
data = open('testfile.dat').read().split('\n')
def newcmp(x,y):
rv = cmp(len(x[1]), len(y[1]))
if rv: return rv
else: return cmp(x[0], y[0]) # alphabetical
persons = {}
attributes = {}
nAttrs = 0
for l in data:
pname , pvals = line.split('\t')[:2]
for atName, atVal in (x.split('=') for x in pvals.psplit(';'))
try:
persons[pName][attributes[atName]] = atVal
except KeyError:
attributes[aName] = nAttrs
persons[pName][attributes[atName]] = atVal
nAttr += 1
headers = ['NAME'] + range(nAttrs)
for x in attributes.keys(): headers[attributes[x]+1] = x
values = []
for pName, pVals in sorted(persons.items(), cmp=newcmp)
if len(pVals) < nAttrs: pVals += [0 for x in xrange(nAttrs - len(pVals))]
values.append('\t'.join(('%d'%x for x in pVals)))
outfh = open('outputfile.dat', 'w')
outfh.write('%s\n%s\n'%('\t'.join(headers), '\n'.join(values)))
outfh.close()
data=open('testfile.dat').read().split('\n')
def newcmp(x,y):
rv=cmp(len(x[1]),len(y[1]))
如果是rv:返回rv
else:按字母顺序返回cmp(x[0],y[0])
人={}
属性={}
nAttrs=0
对于l in数据:
pname,pvals=line.split('\t')[:2]
对于atName,对于pvals.psplit(“;”)中的x,在(x.split(“=”)中使用atVal
尝试:
人员[pName][attributes[atName]]=atVal
除KeyError外:
属性[aName]=nAttrs
人员[pName][attributes[atName]]=atVal
nAttr+=1
标题=['NAME']+范围(nAttrs)
对于attributes.keys()中的x:头[attributes[x]+1]=x
值=[]
对于pName,pVals已排序(persons.items(),cmp=newcmp)
如果len(pVals)
您可以试试这个
data = open('testfile.dat').read().split('\n')
def newcmp(x,y):
rv = cmp(len(x[1]), len(y[1]))
if rv: return rv
else: return cmp(x[0], y[0]) # alphabetical
persons = {}
attributes = {}
nAttrs = 0
for l in data:
pname , pvals = line.split('\t')[:2]
for atName, atVal in (x.split('=') for x in pvals.psplit(';'))
try:
persons[pName][attributes[atName]] = atVal
except KeyError:
attributes[aName] = nAttrs
persons[pName][attributes[atName]] = atVal
nAttr += 1
headers = ['NAME'] + range(nAttrs)
for x in attributes.keys(): headers[attributes[x]+1] = x
values = []
for pName, pVals in sorted(persons.items(), cmp=newcmp)
if len(pVals) < nAttrs: pVals += [0 for x in xrange(nAttrs - len(pVals))]
values.append('\t'.join(('%d'%x for x in pVals)))
outfh = open('outputfile.dat', 'w')
outfh.write('%s\n%s\n'%('\t'.join(headers), '\n'.join(values)))
outfh.close()
data=open('testfile.dat').read().split('\n')
def newcmp(x,y):
rv=cmp(len(x[1]),len(y[1]))
如果是rv:返回rv
else:按字母顺序返回cmp(x[0],y[0])
人={}
属性={}
nAttrs=0
对于l in数据:
pname,pvals=line.split('\t')[:2]
对于atName,对于pvals.psplit(“;”)中的x,在(x.split(“=”)中使用atVal
尝试:
人员[pName][attributes[atName]]=atVal
除KeyError外:
属性[aName]=nAttrs
人员[pName][attributes[atName]]=atVal
nAttr+=1
标题=['NAME']+范围(nAttrs)
对于attributes.keys()中的x:头[attributes[x]+1]=x
值=[]
对于pName,pVals已排序(persons.items(),cmp=newcmp)
如果len(pVals)
感谢您的回复。您能建议如何编辑key_值以容纳不仅仅是数字的值吗?就我的理解水平而言,您的正则表达式非常复杂,但我尝试将其修改为”(?P[A-Z]+)=(?P\S+(:(?=)|$)”
,但它没有确定字段properly@alexhli:您可以使用\w+
作为单词字符,所以a-z加0-9。@alexhli:啊,我错过了您提供的实际示例。我已经更新了正则表达式,使其更加自由,并为您发布了一个演示。您的新演示效果非常好!最后一个问题(我希望),出于某种原因,它现在正在最后一个字段周围打印“”,知道为什么吗?所以它看起来像是person160100“22”
它包含空格;我们可以在字符类中添加不允许的空白:[^\s;=]+
。CSV文件在值周围使用引号表示22
之后的额外空间仍然是值的一部分。感谢您的回复。您能建议如何编辑key_值以容纳不仅仅是数字的值吗?就我的理解水平而言,您的正则表达式非常复杂,但我尝试将其修改为”(?P[A-Z]+)=(?P\S+(:(?=)|$)”
,但它没有确定字段properly@alexhli:您可以使用\w+
作为单词字符,所以a-z加0-9。@alexhli:啊,我错过了您提供的实际示例。我已经更新了正则表达式,使其更加自由,并为您发布了一个演示。您的新演示效果非常好!最后一个问题(我希望),出于某种原因,它现在正在最后一个字段周围打印“”,知道为什么吗?所以它看起来像是person160100“22”
它包含空格;我们可以在character类中添加不允许的空白: