我有一个csv文件,其中包含特定列中的字符串以及其他列中的其他值。我还有一个字符串列表。 循环遍历行,我想检查列表中的一个字符串是否完全包含在csv文件的行中。 如果是,则必须将此行写入新的csv文件中。
csv文件是一个行列表,如:
22/06/2017 04:00:32 | string1 | value1
22/06/2017 04:00:32 | string11 | value2
22/06/2017 04:00:32 | string2 | value3
22/06/2017 04:00:32 | string3 | value4
我编写了这段代码,它运行正常,但它没有考虑字符串的“精确”匹配。
import os, csv
def filter_csv(folderpath):
list1 = [
('name1',1,'string1','value1'),
('name2',2,'string2','value2'),
('name3',3,'string3','value3'),
('name4',4,'string4','value4'),
...
]
def column(matrix, i):
return [row[i] for row in matrix]
col = column(list1,2)
for file in os.listdir("%s" % folderpath):
if file.endswith(".csv"):
new_file = 'new_'+file
filepath = os.path.join("%s" % folderpath, file)
new_filepath = os.path.join("%s" % folderpath, new_file)
with open('%s' % filepath) as csvfile:
lines = csvfile.readlines()
with open('%s' % new_filepath, 'wb') as csvfile2:
for line in lines:
for namevar in col:
if namevar in line:
csvfile2.write(line)
return
如何为csv文件的列添加完全匹配的字符串?
答案 0 :(得分:1)
您要做的是将过滤后的列表写入文件。
过滤条件是"某些预定义的有效值之一必须出现在CSV行" 上,我们可以使用集合交集。我们需要一组有效值,当你与当前输入行相交时,有些值保留,然后当前输入行通过。
import os, csv
from glob import glob
def filter_csv(folderpath):
list1 = [
('name1',1,'string1','value1'),
('name2',2,'string2','value2'),
('name3',3,'string3','value3'),
('name4',4,'string4','value4'),
# ...
]
# prepare a set of valid values
valid_values = {row[2] for row in list1}
for filepath in glob("%s/*.csv" % folderpath):
filename = os.path.basename(filepath)
new_filepath = os.path.join(folderpath, 'new_' + filename)
with open(filepath, newline='') as infile, \
open(new_filepath, 'wb') as outfile:
reader = csv.reader(infile)
writer = csv.writer(outfile)
filtered_rows = (row for row in reader if valid_values.intersection(row))
writer.writerows(filtered_rows)
备注
glob()
对于按扩展名查找文件非常有用with
可以处理多个资源\
跨越多行{ ... }
是一种集合理解 - 它将列表转换为集合.split()
或类似的内容答案 1 :(得分:0)
只是为了使用不同的库提供一个略有不同的解决方案,现在我认为它可能有点过分,但你可能会喜欢它:)你应该能够修改示例以插入到你的代码中......
import pandas as pd
# Dummy col
col = ["string1", "string2", "string3"]
# Read in CSV file
df = pd.read_csv("test.csv", header=None, skipinitialspace=True, delimiter ="|")
# Strip all strings so that trailing whitespace is ignored.
# csv library OP used would also be "fooled" by whitepace
df_obj = df.select_dtypes(['object'])
df[df_obj.columns] = df_obj.apply(lambda x: x.str.strip())
# Select only rows with any column that has a value in col
df = df[df.isin(col).any(axis=1)]
# Write out CSV to new file
df.to_csv("test2.csv")
这将通过检查每列中col
中的一个值来过滤CSV的每一行。如果任何列的值为col
,则它会显示在输出CSV文件中。
我发现的一件事是,如果CSV中的文本有尾随空格,那么完全匹配就不会起作用。例如,由于尾随空格,string1
下方的CSV行不会完全匹配。
value1, value2, string1 , value3
因此,修剪所有字符串的额外代码。使用csv
库进行测试,它会遇到同样的问题。如果您知道您的CSV字符串永远不会有尾随空格,那么您甚至可以删除这两行。然后,以完整形式过滤的代码将是(借用Tomalak's use of glob
):
import pandas as pd
import glob
import os
def filter_csv(folderpath):
list1 = [
('name1',1,'string1','value1'),
('name2',2,'string2','value2'),
('name3',3,'string3','value3'),
('name4',4,'string4','value4')
]
def column(matrix, i):
return [row[i] for row in matrix]
col = column(list1,2)
for filepath in glob.glob("%s/*.csv" % folderpath):
filename = os.path.basename(filepath)
new_filepath = os.path.join(folderpath, 'new_' + filename)
df = pd.read_csv(filename, header=None, skipinitialspace=True, delimiter ="|")
df_obj = df.select_dtypes(['object'])
df[df_obj.columns] = df_obj.apply(lambda x: x.str.strip())
df[df.isin(col).any(axis=1)].to_csv(new_filepath, sep="|", header=False, index=False)
但如果空格不是问题,您可以修改代码中的以下行:
df_obj = df.select_dtypes(['object'])
df[df_obj.columns] = df_obj.apply(lambda x: x.str.strip())