我想知道在 R 之外做一些事情是否会更好。以awk 为例,在awkgroup.csv 中使用此数据:
"something","group"
1,"A"
2,"A"
3,"A"
4,"A"
5,"A"
6,"B"
7,"B"
8,"B"
9,"B"
10,"B"
11,"C"
12,"C"
13,"C"
14,"C"
15,"C"
16,"D"
17,"D"
18,"D"
19,"D"
20,"D"
我们可以的
$ awk -F, '$2==inp{line++;if(line<3)print($0)}; $2!=inp{inp=$2;line=0;print($0)};' awkgroup.csv > newdata.csv
$ cat newdata.csv
"something","group"
1,"A"
2,"A"
3,"A"
6,"B"
7,"B"
8,"B"
11,"C"
12,"C"
13,"C"
16,"D"
17,"D"
18,"D"
基本演练(尽管我不认为自己是 awk 向导):
-
$2==inp(以及类似的$2!=inp)测试第二列(我们的分组变量)自上一行以来是否发生了变化。 inp 最初未初始化,因此默认为空字符串。
NB:假设数据是按组排序的。
-
line++;if(line<3)print($0) 是大部分工作,它测试line(我们在当前组中跟踪行的方法)是否小于3(我们在这里使用基于0的line)并打印如果是这样的话。这为我们提供了每组的前 3 行。
-
inp=$2;line=0;print($0) 类似,但在组内的第一行运行;它重置line 计数器,通过分配给inp 设置我们认为当前组的内容,并始终打印(因为这是组中的第一行)。
我无法让它在 fread(cmd="...") 中正常工作,可能是因为它(出于某些原因)使用 shell 代替了公认的也坏了(但不是 这里)system。 可以使用system 并控制输出的去向,然后正常读取,也许
system2("awk", c("-F, '$2==inp{line++;if(line<3)print($0);};$2!=inp{inp=$2;line=0;print($0)};'",
"awkgroup.csv"),
stdout="awkout.csv" )
fread("awkout.csv")
# something group
# <int> <char>
# 1: 1 A
# 2: 2 A
# 3: 3 A
# 4: 6 B
# 5: 7 B
# 6: 8 B
# 7: 11 C
# 8: 12 C
# 9: 13 C
# 10: 16 D
# 11: 17 D
# 12: 18 D
仅供参考,system2 并不比system 好:它只是将引用的(好!)command= 与所有未引用的args(坏!)连接起来:
command <- paste(c(shQuote(command), env, args), collapse = " ")
这就是为什么我能够稍微作弊并将所有awk 的args= 组合成一个向量。
从这里开始,你需要控制两件事:
- 将
$2(在三个位置)更改为分组变量的列号;
- 将
< 3 更改为您想要的任何限制(请记住,它是从0 开始的,所以< 3 为您提供3 个条目,而不是2 个)。