如何使用python列表在文本文件的缺失位置填充NA
我在原始文本文件(它是一个日志文件)中有一个数据集,我正在用这个文本文件逐行阅读准备python列表,用这个列表我将使用pyspark创建一个数据框。如果你看到数据集,各个列中缺少一些值,我想用“NA”填充它。这是数据集的示例,缺少的值可以在任何列中,列之间用空格隔开如何使用python列表在文本文件的缺失位置填充NA,python,python-2.7,pyspark,Python,Python 2.7,Pyspark,我在原始文本文件(它是一个日志文件)中有一个数据集,我正在用这个文本文件逐行阅读准备python列表,用这个列表我将使用pyspark创建一个数据框。如果你看到数据集,各个列中缺少一些值,我想用“NA”填充它。这是数据集的示例,缺少的值可以在任何列中,列之间用空格隔开 ============================================== empcode Emnname Date DESC 12d sf 2018-02-06
==============================================
empcode Emnname Date DESC
12d sf 2018-02-06 dghsjf
asf2 asdfw2 2018-02-16 fsfsfg
dsf21 sdf2 2016-02-06 sdgfsgf
sdgg dsds dkfd-sffddfdf aaaa
dfd gfg dfsdffd aaaa
df dfdf efef
4fr freff
----------------------------------------------
霉菌代码:
path="something/demo.txt"
EndStr="----------------------------------------------"
FilterStr="=============================================="
findStr="empcode Emnname"
def PrepareList(findStr):
with open(path) as f:
out=[]
for line in f:
if line.rstrip()==Findstr:
#print(line)
tmp=[]
tmp.append(re.sub("\s+",",",line.strip()))
#print(tmp)
for line in f:
if line.rstrip()==EndStr:
out.append(tmp)
break
tmp.append(re.sub("\s+",",",line.strip()))
return (tmp)
f.close()
LstEmp=[]
LstEmp=prepareDataset("empcode Emnname Dept DESC")
print(LstEmp)
我的输出是:
['empcode,Emnname,Date,DESC',
'12d,sf,2018-02-06,dghsjf',
'asf2,asdfw2,2018-02-16,fsfsfg',
'dsf21,sdf2,2016-02-06,sdgfsgf',
'sdgg,dsds,dkfd-sffddfdf,aaaa',
'dfd,gfg,dfsdffd,aaaa',
'df,dfdf,efef',
'4fr,freff']
预期产出:
['empcode,Emnname,Date,DESC',
'12d,sf,2018-02-06,dghsjf',
'asf2,asdfw2,2018-02-16,fsfsfg',
'dsf21,sdf2,2016-02-06,sdgfsgf',
'sdgg,dsds,dkfd-sffddfdf,aaaa',
'dfd,gfg,dfsdffd,aaaa',
'df,NA,dfdf,efef',
'4fr,NA,NA,freff']
从数据集中可以看出,字段中的文本长度是可变的,字段本身在固定位置开始和结束。这通常发生在选项卡分隔的字段中
==============================================
empcode Emnname Date DESC
12d sf 2018-02-06 dghsjf
asf2 asdfw2 2018-02-16 fsfsfg
dsf21 sdf2 2016-02-06 sdgfsgf
如果是这种情况,则应采取以下措施:
for line in f:
if line.rstrip()==Findstr:
tmp=[]
tmp.append(re.sub("\t",",",line.strip()))
#print(tmp)
for line in f:
if line.rstrip()==EndStr:
out.append(tmp)
break
tmp.append(re.sub("\t",",",line.strip()))
return (tmp)
我已将您代码中的\s
替换为\t
,并删除了+
。
在python正则表达式中,+
符号展开以匹配它前面的一个或多个正则表达式。在这种情况下,\s
从第一个字段的末尾扩展到下一个字段
或者,如果输入文件不是以制表符分隔的,则可以根据固定长度字段提取字段值,然后执行strip()
在这里,我尝试采用一种通用的方法,即不必在代码中预先编程列跨距。要返回数据帧,可以将pd.read\u csv与stringio一起使用。请根据您的文件位置修改路径。这段代码是从您的代码扩展而来的,以使您更容易理解,否则有更多有效的方法来编写相同的逻辑
import re
import pandas as pd
import StringIO
path = "/home/clik/clik/demo.txt"
EndStr = "------------------------------"
FilterStr = "=================="
FindStr = "empcode Emnname"
def match(sp1, sp2):
disjunct = max(sp1[0] - sp2[1], sp2[0] - sp1[1])
if disjunct >= 0:
return -abs((sp1[0]+sp1[1])/2.0 - (sp2[0]+sp2[1])/2.0)
return float(disjunct) / min(sp1[0] - sp2[1], sp2[0] - sp1[1])
def PrepareList():
with open(path) as f:
out = []
for i, line in enumerate(f):
print line.rstrip()
if line.rstrip().startswith(FindStr):
print(line)
tmp = []
col_spans = [m.span() for m in re.finditer("[^\s][^\s]+", line)]
tmp.append(re.sub("\s+", ",", line.strip()))
# print(tmp)
for line in f:
if line.rstrip().startswith(EndStr):
out.append(tmp)
break
row = [None] * len(col_spans)
for m in re.finditer("[^\s][^\s]+", line):
colmatches = [match(m.span(), cspan) for cspan in col_spans]
max_index = max(enumerate(colmatches), key=lambda e: e[1])[0]
row[max_index] = m.group() if row[max_index] is None else (row[max_index] + ' ' + m.group())
tmp.append(','.join(['NA' if e is None else e for e in row]))
#tmp.append(re.sub("\s+", ",", line.strip()))
#for pandas dataframe
#return pd.read_csv(StringIO.StringIO('\n'.join(tmp)))
#for returning list of tuples
return map(tuple, tmp)
#for returning list of list
#return tmp
f.close()
LstEmp = PrepareList()
要将元组列表转换为pyspark dataframe,这里有一个教程,看起来您有一个固定格式的文件。看一看你可能会觉得有用的。基本上,您将文件读取为一个大列,然后按字符串位置拆分文本。@pault谢谢您的评论…不,这是不同的…我的情况是两列之间有空格,但列没有固定长度。谢谢您的回复!!!是的,我使用下面的代码获取值:['empcode Emnname Date DESC'、'12d sf 2018-02-06 dghsjf'、'asf2 asdfw2 2018-02-16 fsfsfg'、'dsf21 sdf2 2016-02-06 sdgfsgf'、'sdgg dsds dkfd SFFDDFDFDF aaaa'、'dfd gfg DFDFFD aaaa'、'DFDFDFDFDFDFDFEF'、'4fr freff']每一行作为一个字符串。如何使用该行创建数据帧,以及如何使用单个列进行下一次计算..感谢您的回答。调用函数“PrepareList”时我遇到了错误。代码:LstEmp=[]LstEmp=PrepareList(“empcode Emnname Date DESC”)获取错误:disjunct=max(sp1[0]-sp2[1],sp2[0]-sp1[1])TypeError:()正好接受1个参数(给出2个)非常感谢它正在工作…我想更新一下这段代码,请在这方面帮助我…1.它将如何工作,或者如果特定列中有2个单词,我必须更改什么,例如:在Emnname列中特定行中的值是“Name姓氏”(示例:Alok Nayak),当前代码仅接受如何处理此情况的最后一个字。2.在标头之后有一行“=============================================================================================================================================================================================================================================================================================如何过滤该行…我解决了第二个问题,所以请忽略第二个问题…你能帮我解决第一个问题吗。@Rudrashis你能提供示例demo.txt让我为这个问题编写可行的解决方案吗。如果不能在这里对此进行注释,你可以编辑该问题。假设同一列字段总是被1个空格隔开虽然不同列中的字段之间的间隔超过1个空格,但我已经更新了header和field regex,以适应单个空格分隔的header和field
import re
import pandas as pd
import StringIO
path = "/home/clik/clik/demo.txt"
EndStr = "------------------------------"
FilterStr = "=================="
FindStr = "empcode Emnname"
def match(sp1, sp2):
disjunct = max(sp1[0] - sp2[1], sp2[0] - sp1[1])
if disjunct >= 0:
return -abs((sp1[0]+sp1[1])/2.0 - (sp2[0]+sp2[1])/2.0)
return float(disjunct) / min(sp1[0] - sp2[1], sp2[0] - sp1[1])
def PrepareList():
with open(path) as f:
out = []
for i, line in enumerate(f):
print line.rstrip()
if line.rstrip().startswith(FindStr):
print(line)
tmp = []
col_spans = [m.span() for m in re.finditer("[^\s][^\s]+", line)]
tmp.append(re.sub("\s+", ",", line.strip()))
# print(tmp)
for line in f:
if line.rstrip().startswith(EndStr):
out.append(tmp)
break
row = [None] * len(col_spans)
for m in re.finditer("[^\s][^\s]+", line):
colmatches = [match(m.span(), cspan) for cspan in col_spans]
max_index = max(enumerate(colmatches), key=lambda e: e[1])[0]
row[max_index] = m.group() if row[max_index] is None else (row[max_index] + ' ' + m.group())
tmp.append(','.join(['NA' if e is None else e for e in row]))
#tmp.append(re.sub("\s+", ",", line.strip()))
#for pandas dataframe
#return pd.read_csv(StringIO.StringIO('\n'.join(tmp)))
#for returning list of tuples
return map(tuple, tmp)
#for returning list of list
#return tmp
f.close()
LstEmp = PrepareList()