我一直在寻找这种解决方案的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的资源。
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页面调用并让它运行。就像用户点击刷新一样,它会通过它进行搅拌并消化数据。
非常感谢任何帮助!
谢谢。
Ĵ。
答案 0 :(得分:1)
使用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)
答案 1 :(得分:1)
您可以使用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
对于第一个文件答案 2 :(得分: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工具集,则无需编程。
答案 3 :(得分: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);
注意:正如您所提到的,第一个文件将使用第1列作为主键,因此不应出现重复的键值。如果是,则最后一次出现。