sirallen sirallen -4 years ago 60
R Question

Map lists in single-row data.table

I have a

data.table
with two columns of type
list
that I would like to combine pairwise. The following works:

dt = data.table(a=as.list(1:2), b=as.list(3:4))
dt[, ab:= Map(c, a, b)]
> dt
# a b ab
# 1: 1 3 1,3
# 2: 2 4 2,4


... but it fails when there is only a single row:

dt = data.table(a=list(1), b=list(2))
dt[, ab:= Map(c, a, b)]

Error in `[.data.table`(dt, , `:=`(ab, Map(c, a, b))) :
(converted from warning) Supplied 2 items to be assigned to 1 items of
column 'ab' (1 unused)


Why is this happening? What should I do differently?

Answer Source

We need to wrap it with list

dt[, ab := list(Map(c, a, b))]

We need to check the output of

str(dt[, Map(c, a, b)])
#Classes ‘data.table’ and 'data.frame':  2 obs. of  2 variables:
#$ V1: int  1 3
#$ V2: int  2 4

It is a data.table with 2 columns, when we assign to a single column i.e. 'ab', each column become a list element .

However, in the case of a single row data.table,

str(dt[, Map(c, a, b)])
#Classes ‘data.table’ and 'data.frame':  2 obs. of  1 variable:
#$ V1: num  1 2
#- attr(*, ".internal.selfref")=<externalptr> 

it is not happening as we have a column with 2 elements and we are assigning to create a single column 'ab' while the number of rows is 1. Here, is where we need a list wrapper

str(dt[, list(Map(c, a, b))])
#Classes ‘data.table’ and 'data.frame':  1 obs. of  1 variable:
#$ V1:List of 1
# ..$ : num  1 2
#- attr(*, ".internal.selfref")=<externalptr> 

This will be the same for multiple rows as well

str(dt[, list(Map(c, a, b))])
#Classes ‘data.table’ and 'data.frame':  2 obs. of  1 variable:
#$ V1:List of 2
#  ..$ : int  1 3
#  ..$ : int  2 4
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download