Python2.7 - 将参数传递给命令行以根据参数过滤 CSV

Python2.7 - Passing argument to command line to filter CSV according to parameter

我还没有这方面的代码,因为我不确定如何解决。 使用 pythonsci-kit 中的 tfidfVectorizer,我计算了电影评论中使用的术语的 tfidf 分数。

我将我的结果输出到一个 CSV 文件中,该文件有 4 列,其中包含

Col1 = indDocID 
Col2 = Word 
Col3 = MovieID 
Col4 = Score

我想传递一个命令行参数来解析 CSV 文件并只打印那些对应于 MovieID.

的结果

这样,直接从命令行,我就可以将我感兴趣的结果作为文件调用$python tfidf.py -i uniqMovieID

我一直在阅读所有关于传递命令行参数的文献,并一直在试验我的代码,但它们似乎没有解决我在过滤包含相同参数的信息时遇到的问题MovieID我直接在命令行中指出。

CSV 文件中的数据示例是

indDocID,Word,MovieID,Score
1,love,4583B,.09
2,good,4583B,.37
3,funny,4583B,.64
4,love,34623C,.34
5,hate,34623C,.57

我的目标是 运行 使用以下命令 python tfidf.py -i 4583B 的脚本,以便结果是:

indDocID,Word,MovieID,Score
1,love,4583B,.09
2,good,4583B,.37
3,funny,4583B,.64

我一直在寻找 here 并且尝试了某些示例,例如

from optparse import OptionParser

parser = OptionParser()
parser.add_option("-i", "--idMovie", dest="arg",
                  help="insertMovieIds", metavar="variable")

还有这个:

def main(argv):
   movieIds = ''

   try:
      opts, args = getopt.getopt(argv,"hi:",["movieid="])
   except getopt.GetoptError:
      print 'test.py -i <movieID>'
      sys.exit(1)
   for opt, arg in opts:
      if opt == '-h':
         print 'tfidf.py -i <movieIds>'
         sys.exit()
      elif opt in ("-i", "--id"):
         movieIds = arg

   print 'MovieID is:', movieIds



if __name__ == "__main__":
   main(sys.argv[1:])

但我不确定如何将它们成功地集成到我的代码中,以便它与我的 CSV 中的特定行相关联以达到上述预期结果。

使用 csv.DictReader 提取与传入脚本的唯一 MovieID 相匹配的任何行:

import csv
from optparse import OptionParser

parser = OptionParser()
parser.add_option("-i", "--idMovie", dest="arg",
                  help="insertMovieIds", metavar="variable")
opt, args = parser.parse_args()
un_id = opt.arg
with open("out.txt") as f:
    names = next(f).rstrip().split(",")
    r = csv.DictReader(f, fieldnames=names)
    print(",".join(names))
    for d in r:
        if un_id == d["MovieID"]:
            print(",".join([d[n] for n in names]))

输出:

$ python test.py -i 4583B 
indDocID,Word,MovieID,Score
1,love,4583B,.09
2,good,4583B,.37
3,funny,4583B,.64

你需要添加你的错误检查等。如果你想为不同的列重用代码,只需将逻辑放在一个函数中,你也可能只想打印 header 如果你发现匹配项,如果未找到匹配项,则向用户报告:

def find_by_val(col, k, fle, delim=","):
    with open(fle) as f:
        names = next(f).rstrip().split(delim)
        if col not in names:
            print("Column does not exist.")
            return
        r, found = csv.DictReader(f, fieldnames=names), False
        for d in r:
            if un_id == d[col]:
                if not found:
                    print(",".join(names))
                    print(",".join([d[n] for n in names]))
                    found = True
                else:
                    print(",".join([d[n] for n in names]))
        if not found:
            print("No matching value for {} found".format(k))

输出:

padraic@lab:~$ python test.py -i 4583B 
indDocID,Word,MovieID,Score
1,love,4583B,.09
2,good,4583B,.37
3,funny,4583B,.64
padraic@lab:~$ python test.py -i foo
No matching value for foo found

如果将输出存储在列表中,可以写得更简洁一点:

def find_by_val(col, k, fle, delim=","):
    with open(fle) as f:
        names = next(f).rstrip().split(delim)
        if col not in names:
            print("Column does not exist.")
            return
        r, found = csv.DictReader(f, fieldnames=names), False
        output = [",".join(d[n] for n in names) for d in r if d[col] == k ]
        if not output:
            print("No matching value for {} found".format(k))
        else:
            print(",".join(names))
            print("\n".join(output))

如果您想要更通用的方法,您可能还应该将列名作为参数并使用多个值来查找。

如果您只需要将行与 MoveID 匹配,则可能不需要使用附加参数 -i(如果您需要指定,附加参数可能会有所帮助,我们使用哪个列来匹配)。您可以使用 python tfidf.py 4583B

测试下面的代码
#!/usr/bin/env python

import sys, csv

def search(db, mid):
    # open csv file
    with open(db, 'r') as csvfile:
        reader = csv.reader(csvfile, delimiter=',')
        for r in reader:
            # print line if MovieID matches
            if r[2] == mid:
                print(','.join(r))

if __name__ == '__main__':
    # parse arguments    
    db, mid = sys.argv[1:]
    search(db, mid)