Search code examples
rreshape2dcast

reshape2 dcast non-numeric argument to binary operator


I am trying to convert a data frame from long to wide using dcast from reshape2.

I create a data frame like this:

> Person=c("A","A","A","A","B","B","C","C","C","C")
> Object=c("car", "watch", "bike", "phone","car","skateboard","car","bike","motorcycle")
> Value=c("1","1","1","1","1","1","1","1","1","1")
> df=data.frame(Person, Object, Value)

and get,

> df
   Person     Object Value
1       A        car     1
2       A      watch     1
3       A       bike     1
4       A      phone     1
5       B        car     1
6       B skateboard     1
7       C        car     1
8       C       bike     1
9       C motorcycle     1
10      C         TV     1

Then, with dcast

> library(reshape2)
> dcast(df, Person + Object, variable.var="Value", fun.aggregate=length)
Error in Person + Object : non-numeric argument to binary operator

Why dcast would need numeric argument for Person and Object column anyway?

I am trying to get this output:

Person    car    watch    bike    phone    skateboard    motorcycle    TV
     A      1        1       1        1             0             0     0
     B      1        0       0        0             1             0     0
     C      1        0       1        0             0             1     1

* EDIT * @neilfws found a solution:

dcast(df, Person ~ . + Object, variable.var="Value")

However, when the data frame is imported from a tab-delimited file:

df = read.table("Person_Object.tab", header=T, sep="\t")

the same dcast command returns:

Error in eval(expr, envir, enclos) : object 'Person' not found

Solution

  • Showing how to fill empty cells.

    Person=c("A","A","A","A","B","B","C","C","C","C")
    Object=c("car", "watch", "bike", "phone","car","skateboard","car","bike","motorcycle", "TV")
    Value=c("1","1","1","1","1","1","1","1","1","1")
    
    # note the extra parameter StringsAsFactors - needed so that "0" can be used 
    df=data.frame(Person, Object, Value, stringsAsFactors = FALSE)
    
    library(reshape2)
    dcast(df, Person ~ Object, value.var="Value", fill = "0")
    
    #   Person bike car motorcycle phone skateboard TV watch
    # 1      A    1   1          0     1          0  0     1
    # 2      B    0   1          0     0          1  0     0
    # 3      C    1   1          1     0          0  1     0
    >