Полагаю, это решение работает, если одна из ваших переменных числовая, и у вас также есть смысл распределения (поэтому можно разрезать его примерно на равные части)
library(data.table)
# three million x one thousand
w <- data.table( x = 1:3000000 , y = 1:1000 )
z <- data.table::dcast( w , x ~ y , value.var = 'x' )
w[ , cast_cat := findInterval( y , seq( 100 , 900 , 100 ) ) ]
w_list <- split( w , by = 'cast_cat' )
w_list <- lapply( w_list , function( x ) x[ , cast_cat := NULL ] )
w_list <- lapply( w_list , function( z ) data.table::dcast( z , x ~ y , value.var = 'x' ) )
result <- Reduce( function( ... ) merge( ... , by = 'x' , all = TRUE ) , w_list )