如何使用python列表在文本文件的缺失位置填充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

我在原始文本文件(它是一个日志文件)中有一个数据集,我正在用这个文本文件逐行阅读准备python列表,用这个列表我将使用pyspark创建一个数据框。如果你看到数据集,各个列中缺少一些值,我想用“NA”填充它。这是数据集的示例,缺少的值可以在任何列中,列之间用空格隔开

==============================================
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()