我的搜索字词用完了,已经完整了。我已经阅读并尝试了大量的问题和答案,我认为这是一个相当简单的任务,但没有快乐。
我有两个csv文件。
**file1.csv** (2,000 + lines)<br/>
product_code, colour, size, sku, more cols..., barcode<br/>
<span style="color: red">
item98, red, XL, adfd56384678, ..., null<br/>
item99, black, L, adfgk9087467, ..., null<br/>
item98, red, S, adfgad240568, ..., null<br/>
</span>
**file2.csv** (20,000 + lines)<br/>
ITEM_CODE, COLOUR, SIZE, BAR_CODE<br/>
<span style="color: red">
item98, RED, XL, 090900887<br/>
item98, RED, S, 43581034<br/>
item97, BLUE, M, 519685371<br/>
</span>
我需要输出:
**matched-result.csv** (2,000 + lines)<br/>
product_code, colour, size, sku, more cols..., barcode<br/>
<span style="color: red">
item98, red, XL, adfd56384678, ..., 090900887<br/>
item99, black, L, adfgk9087467, ..., null<br/>
item98, red, S, adfgad240568, ..., 519685371<br/>
</span>
sku和条形码是唯一值,只能通过匹配product_code,大小和颜色来识别。我需要在file1.csv末尾的新列中使用条形码。我的第一次成功尝试是使用awk。
<pre>
awk -F',' -v OFS=, 'NR==FNR{a[$1,tolower($2),$3]=$4;next}{if( b = a[$1,tolower($2),$3]){ print $1,$2,$3,$4,b }}' file1.csv file2.csv > matched-result.csv
</pre>
我努力输出整个 file1.csv 的结果,尝试打印$ 0,b ,这会创建一个值为b的新行。我也希望所有file1.csv输出都为非匹配的空值和尽可能的头。我必须对齐列以匹配此awk工作方法,但原始字段不对齐。这没什么大不了的,但我想知道是否有必要解决这个问题?
之后我尝试使用python脚本将 file1.csv 与awk输出文件 matched-result.csv 合并。
import csv from collections import OrderedDict with open('file1.csv') as f: r = csv.reader(f, delimiter=',') dict1 = {row[0]: row[1:] for row in r} with open('matched-result.csv') as f: r = csv.reader(f, delimiter=',') dict2 = OrderedDict((row[0], row[1:]) for row in r) result = OrderedDict() for d in (dict1, dict2): for key, value in d.iteritems(): result.setdefault(key, []).extend(value) with open('desired-result.csv', 'wb') as f: w = csv.writer(f) for key, value in result.iteritems(): w.writerow([key] + value)
输出不是所需的结果。订单错误,记录的数量与 file1.csv 完全匹配还有一行?这个两步法似乎脱节了,如果做得好,感觉就像其中一个可以做到这一点?
我已经尝试过csvkit来加入/合并文件,但输出20,000 +行,其中一些是重复的。我认为它将product_code / ITEM_CODE列视为唯一值,但它们并非如此。我已经考虑过加入和grep,但它们似乎也不是答案。
我已经安装了panda和powerShell,并愿意给他们一个去,但不知道从哪里开始,那里需要明确的指示。哦,我和所有这些语言和程序都是菜鸟,但并不是完全湿透了。
希望我已经提供足够的信息继续下去。我会发布链接到我读过的帖子。你可以把它的工作用于它的90%以上。
请回复,提供代码示例,最好不要使用全新的语言或方法。
//更新
我已经投票赞成@zwer回答,因为它或多或少地在方框栏中进行了一次小调整,请参阅评论。但值得指出的是@RavinderSingh13 awk方法同样有效。当/如果我收到回复并更新此位,我将采用@acushner熊猫方法。
如果有人关心,我认为这是最好的方法吗? Tomatoto,tomarto,不确定是否适用于印刷品。就个人而言,python更容易阅读。 awk很好而且简短,我认为它是一种基于正则表达式的语言,我觉得它更难以理解并且学习曲线更陡峭。
感谢所有评论过的人。我很久以来一直在努力解决这个问题,并将其排在这里。
答案 0 :(得分:1)
我认为您的输出存在一些不一致,理想情况下,如果我们考虑将$ 1,$ 2和$ 3作为file2.csv文件的索引,则显示输出的最后一行不应该存在。
如果是,这是一个错字,那么以下可能会帮助你。
awk -F", " 'FNR==NR{;a[$1,tolower($2),$3]=$NF;next} (($1,$2,$3) in a){$NF=a[$1,$2,$3]} 1' file2.csv file1.csv
编辑:由于OP在Input_file中控制了M个字符,因此现在也添加了以下内容。
awk -F", " '{gsub('/\r/',"")} FNR==NR{;a[$1,tolower($2),$3]=$NF;next} (($1,$2,$3) in a){$NF=a[$1,$2,$3]} 1' file2.csv file1.csv
答案 1 :(得分:0)
一种简单而通用的Python方法:
JSON.parse(`{"person": {
"name": "John",
"lastname": "Doe",
"interests": [
"hiking",
"skiing"
],
"age": 40
}}`);
如果import csv
# load the second file in memory as we need it for a barcode lookup
barcodes = {} # will hold a map for our barcode values
with open("file2.csv", "rU") as f: # open file2.csv for reading
reader = csv.reader(f) # create a CSV reader, you may need to tweak its options
next(reader) # skip the header
for row in reader: # loop it row by row
# store code:color:size map as a tuple in our barcodes map
barcodes[(row[0], row[1].lower(), row[2])] = row[3]
# now you can get a barcode from it like: barcodes[("item98", "red", "XL")]
# open file1.csv for reading and matched-result.csv for writing
with open("file1.csv", "rU") as f, open("matched-result.csv", "w") as out:
reader = csv.reader(f) # create a CSV reader, you may need to tweak its options
header = next(reader) # get the header
indexes = {column: index for index, column in enumerate(header)} # map column indexes
writer = csv.writer(out, lineterminator="\n") # create a CSV writer for our output
writer.writerow(header) # write the same header to the output file
for row in reader: # loop through file1.csv rows
# create a search map entry
search = (row[indexes["product_code"]], row[indexes["colour"]], row[indexes["size"]])
if search in barcodes: # we have a barcode entry
row[indexes["barcode"]] = barcodes[search] # update it in the current row
writer.writerow(row) # write the potentially modified row to our output file
列的顺序可能不同,则必须确保映射部分(file2.csv
)与列顺序匹配,即
编辑 - 由于我以前没有测试过,我写了一个简单的测试,看看它是否正常工作:
barcodes[(row[0], row[1].lower(), row[2])] = row[3]
:
product_code,colour,size,sku,added_col,barcode item98,red,XL,adfd56384678,1,null item99,black,L,adfgk9087467,2,null item98,red,S,adfgad240568,3,null
file1.csv
:
ITEM_CODE,COLOUR,SIZE,BAR_CODE item98,RED,XL,090900887 item98,RED,S,43581034 item97,BLUE,M,519685371
导致file2.csv
包含:
product_code,colour,size,sku,added_col,barcode item98,red,XL,adfd56384678,1,090900887 item99,black,L,adfgk9087467,2,null item98,red,S,adfgad240568,3,43581034
如果您的CSV文件遵循问题中提供的结构,就像这样,它应该可以正常工作。我可能在您的数据中看到的唯一问题是在用逗号分隔值之后有一个空格。如果您的数据确实如此,请将matched-result.csv
添加到每个skipinitialspace=True
的参数中(例如csv.reader()
)以占用额外的空间。正如我在代码中所写的那样,您可能需要调整reader = csv.reader(f, skipinitialspace=True)
选项以匹配您的CSV方言。
答案 2 :(得分:0)
使用pandas
非常简单。你会做这样的事情:
import pandas as pd
df_sku = pd.read_csv('file1.csv', index_col=False)
df_bc = pd.read_csv('file2.csv', index_col=False)
res = df_sku.merge(df_bc, left_on=['product_code', 'colour', 'size'], right_on=['ITEM_CODE', 'COLOUR', 'SIZE'])
试一试,让我知道你是怎么做出来的。另外,如果你要做一堆csv的东西,pandas
是值得学习的。{/ p>