我有几个这样的 CSV 文件:
site,run,id,payload,dir
1,1,1,528,1
1,1,1,540,2
1,1,3,532,1
# ... thousands more rows ...
(在我使用的实际情况下,共有三个文件,总共 1,408,378 行。)对于绘图,我想将它们重新调整为这种格式:
label,stream,dir,i,payload
A,1,1,1,586
A,1,1,2,586
A,1,1,3,586
# etc
其中“标签”源自 CSV 文件的名称;“stream”是一个序列号,分配给一个文件中“site”、“run”和“id”的每个组合(因此,仅在“label”中是唯一的);'i' 是每个 'stream' 中的行号;'dir' 和 'payload' 直接取自原始文件。我还想丢弃每个流的前 20 行以外的所有行。我事先知道 CSV 文件中的每个单元格(标题除外)都是一个正整数,并且“dir”只取值 1 和 2。
我用 终止了我最初的尝试plyr
,因为经过一个多小时的计算,它已经运行了高达 6GB 工作集的 R 进程,而且看不到尽头。foreach
最新的对并行性的闪亮新支持plyr
并没有帮助:八个进程每个运行 10 分钟的 CPU 时间,然后它又回到一个进程,又持续了一个小时,是的,再次炸毁了我的 RAM。
于是我用 Python 给自己写了一个帮助脚本,用它我更流利:
import sys
def processOne(fname):
clusters = {}
nextCluster = 1
with open(fname + ".csv", "r") as f:
for line in f:
line = line.strip()
if line == "site,run,id,payload,dir": continue
(site, run, id, payload, dir) = line.split(',')
clind = ",".join((site,run,id))
clust = clusters.setdefault(clind,
{ "i":nextCluster, "1":0, "2":0 })
if clust["i"] == nextCluster:
nextCluster += 1
clust[dir] += 1
if clust[dir] > 20: continue
sys.stdout.write("{label},{i},{dir},{j},{payload}\n"
.format(label=fname,
i=clust["i"],
dir=dir,
j=clust[dir],
payload=payload))
sys.stdout.write("label,stream,dir,i,payload\n")
for fn in sys.argv[1:]: processOne(fn)
并从 R 脚本中调用它:
all <- read.csv(pipe("python preprocess.py A B C", open="r"))
五秒钟内完成。
所以问题是:在 R 中执行此操作的正确方法是什么?不是这个特定的任务,而是这类问题。在分析数据之前,我几乎总是需要对一堆数据进行洗牌,而且在其他语言中它几乎总是更容易——无论是我编写代码还是计算机执行它。这让我觉得我只是将 R 用作一个接口,如果我改为ggplot2
学习的话,从长远来看,也许我会节省自己的时间。matplotlib