2016-03-04 28 views
0

我一直在搜索此解決方案的interweb,但沒有找到任何成功。我有一個腳本的CSV輸出,它以特定方式顯示數據,我需要匹配並與另一個文件合併。如果我可以舍入到簡單的2 x小數點,則可以獲得額外的獎勵。根據列中的匹配結合2個CSV文件,忽略標題行

文件1:dataset1.csv

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(使用第1列作爲主鍵或我要搜索其他文件的內容。):dataset2.csv(如果列2場比賽第1列文件的文件從2連接列1替換數據在第1列文件1.)

"dc2","5033db62b38f86605f0baeccae5e6cbc" 
"dc1","5033d9951846c1841437b437f5a97f0a" 

期望的結果:

文件1(或新file3的):

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個條目,但file2可能只有10個。我只需要一個與長字符串關聯的名稱。

我開始看grep - 但後來我需要一個forEach循環來遍歷所有的結果,並且必須有一個更簡單的方法。

我也看了AWK - 現在這是一個有趣的嘗試弄清楚如何使這項工作。

awk 'FNR==NR {a[$2]; next} $2 in a' file.csv testfile2.csv 

啊....試了很多辦法得到這個比較,因爲這似乎是一般的想法......但還沒有得到它的工作。我希望這是linux的shell腳本的一些類型非常簡單,我可以從一個PHP頁面調用並讓它運行。就像用戶點擊刷新一樣,它會攪動並消化數據。

任何幫助將不勝感激!

謝謝。 j)。

j。

+0

你不介意答案是基於哪種語言? (PHP,Python,awk)? – trincot

+0

我正在探索所有的選擇 - 它只是簡單和容易重複....我仍然在測試下面的一些建議。 – Jared

回答

1

您可以使用排序和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是用於第一文件
+0

這工作很好!謝謝!額外的問題,我將如何刪除那些沒有匹配記錄的?這是你的腳本的幫助 - 12K, 小4K, 小-Gen5,804.12,173.88,977.35 小-2K, 小-1,我想刪除那些沒有任何附加記錄。 – Jared

+0

@Jared這些記錄在哪裏?他們在第二個文件?因爲在第一個文件中沒有在第二個文件中配對的rowed已經被刪除了。 –

+0

@Jared要在第一個文件中沒有配對地刪除行,將腳本的最後一行改爲'FNR!= NR {if($ 3 in vals)print $ 2「,」vals [$ 3]; }' –

1

使用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) 
1

除了格式化真這是做這項工作的數字

$ 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工具集,則不需要編程。

0

這裏是用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); 

NB:由於你提到的第一個文件將是使用柱1作爲主鍵,不應該發生重複的鍵值。如果是這樣,最後一次出現將佔上風。

+0

與此 - 有沒有辦法刪除沒有匹配字符串的記錄? – Jared

+0

是的,我剛剛添加了一行代碼(使用'isset')來跳過第二個文件中與第一個文件不匹配的條目。 – trincot

+0

7NA_01,0.00,0.00,0.00 名稱,,, 更正不是一個錯誤,它輸出到文件,但很像頂部awk示例其匹配名稱的東西。 – Jared