如何计算分隔文件中的非空字段数?

Ric*_*ton 6 csv import 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
Run Code Online (Sandbox Code Playgroud)

我想计算每行的非空字段数.我可以通过读取所有内容并计算不是的值的数量,以笨重的方式做到这一点NA.

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

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

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

hrb*_*str 6

如果安装了Rcpp&BHpackages,这应该是完全可移植的:

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;")
)
Run Code Online (Sandbox Code Playgroud)

一旦获得该源,您就可以调用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
Run Code Online (Sandbox Code Playgroud)

通过:

count_blanks("/tmp/a.csv")
## [1] 0 0 1 0 1 0 1 0 1 0 2 0 3 0
Run Code Online (Sandbox Code Playgroud)

CAVEATS

  • 很明显,它不会忽略标头,因此它可以使用header带有相关C/C++代码的逻辑参数(这将非常简单).
  • 如果你把"空格"(即[:space:]+)视为"空",那么你需要的东西比调用要复杂得多length.如果需要,是一种处理它的潜在方法.
  • 它使用此处escaped_list_separator定义的Boost功能的默认配置.也可以使用引号和分隔符来定制(可以进一步模仿/ .read.csvread.table

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