Questo dovrebbe essere completamente portatile a patto di avere i Rcpp
& BH
pacchetti installati:
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;")
)
Una volta che è di provenienza si può chiamare count_blanks(FULLPATH)
e restituirà un vettore numerico di conti di campi vuoti per riga.
ho corse contro questo file:
"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
via:
count_blanks("/tmp/a.csv")
## [1] 0 0 1 0 1 0 1 0 1 0 2 0 3 0
CAVEATS
- E 'abbastanza ovvio che non è ignorare l'intestazione, in modo che potesse usare un parametro logico
header
con codice C/C++ associato (che sarà b e piuttosto semplice).
- Se contate "spazi" (ad esempio
[:space:]+
) come "vuoti", avrete bisogno di qualcosa di un po 'più complesso della chiamata a length
. This è un modo potenziale per affrontarlo se necessario.
- Sta utilizzando la configurazione predefinita per la funzione Boost
escaped_list_separator
che è definita here. Che può anche essere personalizzato con citando & caratteri separatori (rendendo possibile simulare ulteriore read.csv
/read.table
.
Ciò più strettamente avvicinarsi count.fields
/C_countfields
performance e può eliminare la necessità di utilizzare la memoria leggendo in ogni riga solo per trovare le linee che alla fine vuoi raggiungere in modo più ottimale. Non penso che preallocare lo spazio per il vettore numerico restituito aggiungerà molto alla velocità, ma puoi vedere la discussione here che mostra come farlo se necessario
ho appena realizzato che volevi contare _non-vuoto_, spero che l'inverso di questo sia abbastanza banale non garantire una modifica ;-) – hrbrmstr