簡體   English   中英

根據一列內的匹配項合並2個CSV文件,而不管標題行

[英]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。

使用pythonpandas庫:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM