[英]Combine 2 CSV files based on a match within a column disregarding the header row
我一直在尋找這種解決方案的ole interweb,但沒有發現任何成功的方法。 我有一個腳本的CSV輸出,該腳本具有以特定方式顯示的數據,我需要將其匹配並與另一個文件合並。 如果我可以舍入到簡單的2 x小數點,則可以增加獎金。
文件1:dataset1.csv(使用第1列作為主鍵或我要搜索其他文件的內容。)
5033db62b38f86605f0baeccae5e6cbc,20.875,20.625,41.5
5033d9951846c1841437b437f5a97f0a,3.3529411764705882,12.4117647058823529,13.7647058823529412
50335ab3ab5411f88b77900736338bc6,6.625,1.0625,3
5033db62b38f86605f0baeccae5e6cbc,2.9375,1,1.4375
文件2:dataset2.csv(如果第2列與文件2的文件聯接第1列的第1列匹配,則替換文件1的第1列中的數據。)
"dc2","5033db62b38f86605f0baeccae5e6cbc"
"dc1","5033d9951846c1841437b437f5a97f0a"
所需結果:
文件1(或新文件3):
dc1,3.35,12.41,13.76
dc2,20.875,20.625,41.5
只是為了證明我一直在尋找一種方法,而不僅僅是隨機地問一個問題,希望別人能解決我的問題。
我發現了許多使用連接的資源。
join -o 1.1,1.2,1.3,1.4,2.3 file 1 file 2
等等。我已經用許多不同的方式測試了它。 我讀了許多文章,結果需要排序-這么長的字符串有點難。 更不用說文件1可能有30到40個條目,而文件2可能只有10個條目。我只需要一個與長字符串關聯的名稱。
我開始研究grep-但是隨后我將需要一個forEach循環來循環遍歷所有結果,並且必須有一種更簡單的方法。
我也看過AWK-現在這是一個有趣的嘗試,試圖弄清楚如何進行這項工作。
awk 'FNR==NR {a[$2]; next} $2 in a' file.csv testfile2.csv
是的...。嘗試了多種方法來進行比較,因為這似乎是一個普遍的想法……但仍然沒有奏效。 我希望這是Linux的某種類型的Shell腳本,它非常簡單,可以從php頁面調用並運行它。 就像用戶點擊刷新一樣,它會攪動並消化數據。
任何幫助將不勝感激!
謝謝。
j。
使用python
和pandas
庫:
import pandas as pd
# Read in the csv files.
df1 = pd.read_csv(dataset1.csv, header=None, index_col=0)
df2 = pd.read_csv(dataset2.csv, header=None, index_col=1)
# Round values in the first file to two decimal places.
df1 = df1.round(2)
# Merge the two files.
df3 = pd.merge(df2, df1, how='inner', left_index=True, right_index=True)
# Write the output.
df3.to_csv(output.csv, index=False, header=False)
您可以結合使用sort和gnu awk:
mergef.awk:
BEGIN { FS= "[ ,\"]+"; }
FNR == NR { if ( !($1 in vals) ) vals [ $1 ] = sprintf("%.2f,%.2f,%.2f", $2, $3,$4) ;}
FNR != NR { print $2 "," vals[ $3 ]; }
假設您的文件是f1.csv和f2.csv,然后使用以下命令:
awk -f mergef.awk f1.csv f2.csv | sort
$1
) if
會確保僅使用鍵的首次出現。 FNR == NR
對於第一個文件為true 除了格式化數字之外,這項工作
$ join -t, -1 1 -2 2 -o2.1,1.2,1.3,1.4 <(sort file1) <(tr -d '"' <file2 | sort -t, -k2)
dc1,3.3529411764705882,12.4117647058823529,13.7647058823529412
dc2,2.9375,1,1.4375
dc2,20.875,20.625,41.5
請注意,dc2有兩個匹配項。
獎勵:對於必需的格式化,將上一個腳本的輸出傳遞到
$ ... | tr ',' ' ' | xargs printf "%s,%.2f,%.2f,%.2f\n"
dc1,3.35,12.41,13.76
dc2,2.94,1.00,1.44
dc2,20.88,20.62,41.50
但是,也許awk
是更好的選擇。 這表明如果可以利用現有的unix工具集,則無需編程。
這是PHP的解決方案:
foreach (file("dataset1.csv") as $line_no => $csv) {
if (!$line_no) continue; // in case you have a header on first line
$fields = str_getcsv($csv);
$key = array_shift($fields);
$data1[$key] = array_map(function ($v) { return number_format($v, 2); }, $fields);
};
foreach (file("dataset2.csv") as $csv) {
$fields = str_getcsv($csv);
if (!isset($data1[$fields[1]])) continue;
$data2[$fields[0]] = array_merge(array($fields[0]), $data1[$fields[1]]);
};
ksort($data2);
$csv = implode("\n", array_map(function ($v) {
return implode(',', $v);
}, $data2));
file_put_contents("dataset3.csv", $csv);
注意:正如您提到的那樣,第一個文件將使用列1作為主鍵 ,所以不應出現重復的鍵值。 如果是這樣,則以最后一次出現為准。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.