我正在处理大量文件(价值约4GB),这些文件都包含1到100个条目之间的任何格式,格式如下(两个***之间是一个条目):
***
Type:status
Origin: @z_rose yes
Text: yes
URL:
ID: 95482459084427264
Time: Mon Jul 25 08:16:06 CDT 2011
RetCount: 0
Favorite: false
MentionedEntities: 20776334
Hashtags:
***
***
Type:status
Origin: @aaronesilvers text
Text: text
URL:
ID: 95481610861953024
Time: Mon Jul 25 08:12:44 CDT 2011
RetCount: 0
Favorite: false
MentionedEntities: 2226621
Hashtags:
***
***
Type:status
Origin: @z_rose text
Text: text and stuff
URL:
ID: 95480980026040320
Time: Mon Jul 25 08:10:14 CDT 2011
RetCount: 0
Favorite: false
MentionedEntities: 20776334
Hashtags:
***
现在我想以某种方式将这些导入Pandas进行质量分析,但显然我必须将其转换为Pandas可以处理的格式。所以我想编写一个脚本,将上面的内容转换为.csv,看起来像这样(用户是文件标题):
User Type Origin Text URL ID Time RetCount Favorite MentionedEntities Hashtags
4012987 status @z_rose yes yes Null 95482459084427264 Mon Jul 25 08:16:06 CDT 2011 0 false 20776334 Null
4012987 status @aaronsilvers text text Null 95481610861953024 Mon Jul 25 08:12:44 CDT 2011 0 false 2226621 Null
(格式化并不完美,但希望你能得到这个想法)
我已经有一些代码工作,它的工作基于它经常是12段的信息,但遗憾的是一些文件在某些领域包含几个白线。我基本上要做的是:
fields[] =['User', 'Type', 'Origin', 'Text', 'URL', 'ID', 'Time', 'RetCount', 'Favorite', 'MentionedEntities', 'Hashtags']
starPair = 0;
User = filename;
read(file)
#Determine if the current entry has ended
if(stringRead=="***"){
if(starPair == 0)
starPair++;
if(starPair == 1){
row=row++;
starPair = 0;
}
}
#if string read matches column field
if(stringRead == fields[])
while(strRead != fields[]) #until next field has been found
#extract all characters into correct column field
然而,问题出现了一些字段可以包含字段[]中的单词。我可以首先检查\ n char,这将大大减少错误条目的数量,但不会消除它们。
有人能指出我正确的方向吗?
提前致谢!
答案 0 :(得分:2)
您可以使用正则表达式和字典理解的组合:
import regex as re, pandas as pd
rx_parts = re.compile(r'^{}$(?s:.*?)^{}$'.format(re.escape('***'), re.escape('***')), re.MULTILINE)
rx_entry = re.compile(r'^(?P<key>\w+):[ ]*(?P<value>.+)$', re.MULTILINE)
result = ({m.group('key'): m.group('value')
for m in rx_entry.finditer(part.group(0))}
for part in rx_parts.finditer(your_string_here))
df = pd.DataFrame(result)
print(df)
哪个收益
Favorite Hashtags ID MentionedEntities Origin \
0 false 95482459084427264 20776334 @z_rose yes
1 false 95481610861953024 2226621 @aaronesilvers text
2 false 95480980026040320 20776334 @z_rose text
RetCount Text Time Type URL
0 0 yes Mon Jul 25 08:16:06 CDT 2011 status
1 0 text Mon Jul 25 08:12:44 CDT 2011 status
2 0 text and stuff Mon Jul 25 08:10:14 CDT 2011 status
<小时/> 说明:
***
我们最终拥有一个词典生成器,然后我们将其输入pandas
。
提示:
代码未经过大量数据测试,尤其是4gb。此外,您还需要较新的 regex
模块才能使表达式正常工作。
答案 1 :(得分:1)
您的代码/伪代码看起来不像python,但因为您在这里有python标记是我将如何做到的。首先,将文件读入字符串,然后遍历每个字段并创建正则表达式以查找其后的值,将结果推送到2d列表,然后将该2d列表输出到CSV中。此外,您的CSV看起来更像TSV(分隔标签而不是逗号分隔)。
import re
import csv
filename='4012987'
User=filename
# read your file into a string
with open(filename, 'r') as myfile:
data=myfile.read()
fields =['Type', 'Origin', 'Text', 'URL', 'ID', 'Time', 'RetCount', 'Favorite', 'MentionedEntities', 'Hashtags']
csvTemplate = [['User','Type', 'Origin', 'Text', 'URL', 'ID', 'Time', 'RetCount', 'Favorite', 'MentionedEntities', 'Hashtags']]
# for each field use regex to get the entry
for n,field in enumerate(fields):
matches = re.findall(field+':\s?([^\n]*)\n+', data)
# this should run only the first time to fill your 2d list with the right amount of lists
while len(csvTemplate)<=len(matches):
csvTemplate.append([None]*(len(fields)+1)) # Null isn't a python reserved word
for e,m in enumerate(matches):
if m != '':
csvTemplate[e+1][n+1]=m.strip()
# set the User column
for i in range(1,len(csvTemplate)):
csvTemplate[i][0] = User
# output to csv....if you want tsv look at https://stackoverflow.com/a/29896136/3462319
with open("output.csv", "wb") as f:
writer = csv.writer(f)
writer.writerows(csvTemplate)