data.frame - это список, поэтому в соответствии с
#include <Rdefines.h>
SEXP df_fun(SEXP df)
{
int i, len = Rf_length(df);
SEXP result;
PROTECT(result = NEW_CHARACTER(len));
for (i = 0; i < len; ++i)
switch(TYPEOF(VECTOR_ELT(df, i))) {
case INTSXP:
SET_STRING_ELT(result, i, mkChar("integer"));
break;
case REALSXP:
SET_STRING_ELT(result, i, mkChar("numeric"));
break;
default:
SET_STRING_ELT(result, i, mkChar("other"));
break;
};
UNPROTECT(1);
return result;
}
и затем после R CMD SHLIB df_fun.c
> dyn.load("df_fun.so")
> df=data.frame(x=1:5, y=letters[1:5], z=pi, stringsAsFactors=FALSE)
> .Call("df_fun", df)
[1] "integer" "other" "numeric"
Используйте GET_CLASS
, GET_ATTR
и другие макросы в Rdefines.h (или их эквивалентные функции, такие как getAttrib
), чтобы найти другую информацию о фрейме данных. Обратите внимание, что data.frame имеет API, который может отличаться от его структуры. Так, например, функция R row.names
может возвращать что-то отличное от значения, хранящегося в атрибуте row.names. Я думаю, что большинство .Call
функций работают с атомными векторами, сохраняя манипулирование более сложными объектами на уровне R.