r语言 - 如何计算分隔文件中非空字段的数量



您可以使用utils::count.fields计算逗号/制表符/任何分隔文本文件中的每行字段数。

下面是一个可复制的例子:

d <- data.frame(
  x = c(1, NA, 3, NA, 5),
  y = c(NA, "b", "c", NA, NA),
  z = c(NA, "beta", "gamma", NA, "epsilon")
)
fname <- "test.csv"
write.csv(d, fname, na = "",  row.names = FALSE)
count.fields(fname, sep = ",")
## [1] 3 3 3 3 3 3

我想计算每行非空字段的数量。我可以用一种笨拙的方式来做到这一点,读取所有内容并计算非NA的值的数量。

d2 <- read.csv(fname, na.strings = "")
rowSums(!is.na(d2))
## [1] 1 2 3 0 2

我真的很想扫描文件的方式(如count.fields),所以我可以针对特定的部分读取。

是否有更好的方法来计算分隔文件中非空字段的数量?

如果您有Rcpp &BH安装包:

library(Rcpp)
library(inline)
csvblanks <- '
string data = as<string>(filename);
ifstream fil(data.c_str());
if (!fil.is_open()) return(R_NilValue);
typedef tokenizer< escaped_list_separator<char> > Tokenizer;
vector<string> fields;
vector<int> retval;
string line;
while (getline(fil, line)) {
  int numblanks = 0;
  Tokenizer tok(line);
  for(Tokenizer::iterator beg=tok.begin(); beg!=tok.end(); ++beg){
    numblanks += (beg->length() == 0) ? 1 : 0 ;
  };
  retval.push_back(numblanks);
}
return(wrap(retval));
'
count_blanks <- rcpp(
  signature(filename="character"),
  body=csvblanks,
  includes=c("#include <iostream>",
             "#include <fstream>",
             "#include <vector>",
             "#include <string>",
             "#include <algorithm>",
             "#include <iterator>",
             "#include <boost/tokenizer.hpp>",
             "using namespace Rcpp;",
             "using namespace std;",
             "using namespace boost;")
)

一旦得到来源,你可以调用count_blanks(FULLPATH),它将返回每行空白字段计数的数字向量。

我在这个文件上运行它:

"DATE","APIKEY","FILENAME","LANGUAGE","JOBID","TRANSCRIPT"
1,2,3,4,5
1,,3,4,5
1,2,3,4,5
1,2,,4,5
1,2,3,4,5
1,2,3,,5
1,2,3,4,5
1,2,3,4,
1,2,3,4,5
1,,3,,5
1,2,3,4,5
,2,,4,
1,2,3,4,5
通过:

count_blanks("/tmp/a.csv")
## [1] 0 0 1 0 1 0 1 0 1 0 2 0 3 0

警告

  • 很明显,它没有忽略头,所以它可以使用header逻辑参数与相关的C/c++代码(这将是相当直接的)。
  • 如果你计算"空格"(即[:space:]+)为"空",你需要一些比调用length更复杂的东西。如果需要的话,这是一种潜在的处理方法。
  • 它使用这里定义的Boost函数escaped_list_separator的默认配置。也可以用引号&分隔符(使进一步模拟read.csv/read.table成为可能。

这将更接近count.fields/C_countfields的性能,并且通过读取每一行来找到您最终想要更优化的目标行,从而消除了消耗内存的需要。我不认为为返回的数字向量预分配空间会增加多少速度,但您可以看到这里的讨论,其中显示了如何在需要时这样做。

最新更新