Passing a data frame from-to R and C using .call()

后端 未结 3 1445
Happy的楠姐
Happy的楠姐 2020-12-14 22:46

Is there a general way of passing a data frame with arbitrary columns (integer/factor, numeric, character data) from r to c and back? Pointers to close enough examples woul

相关标签:
3条回答
  • 2020-12-14 23:18

    Here's a link to an example using C++ and package inline by Dirk Eddelbeuttel:

    0 讨论(0)
  • 2020-12-14 23:25

    data.frame type is a list with "data.frame" attribute.

    This is example of creating data.frame in source of R (src/library/stats/src/model.c):

    /* Turn the data "list" into a "data.frame" */
    /* so that subsetting methods will work. */
    
    PROTECT(tmp = mkString("data.frame"));
    setAttrib(data, R_ClassSymbol, tmp);
    UNPROTECT(1);
    

    You can simulate data.frame manually this way:

    l <- list(1:5)
    attr(l, "class") <- "data.frame"
    attr(l, "names") <- "Column 1"
    attr(l, "row.names") <- paste("Row ", 1:5)
    
    0 讨论(0)
  • 2020-12-14 23:31

    A data.frame is a list, so along the lines of

    #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;
    }
    

    and then after 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"
    

    Use GET_CLASS, GET_ATTR and other macros in Rdefines.h (or their equivalent functions, like getAttrib) to discover other information about the data frame. Note though that a data.frame has an API that can differ from its structure. So for instance the R function row.names can return something different from the value stored in the row.names attribute. I think most .Call functions operate on atomic vectors, keeping the manipulation of more complicated objects at the R level.

    0 讨论(0)
提交回复
热议问题