Edit this page on our live server and create a PR by running command !create-pr in the console panel

Exchanging data among kernels

  • Difficulty level: easy
  • Time need to lean: 15 minutes or less
  • Key points:
    • Passing data across kernels allows you to use the best tool of each language
    • Magic %get get variable from another kernel
    • Magic %put put variables to another kernel
    • Magic %with execute the cell in another kernel with input and output variables

A SoS notebook can have multiple live kernels with SoS serving as the master kernel to all other kernels (called subkernels). As described in this tutorial, SoS can process input and output of subkernels without knowing what they actually do. However, if SoS knows what the kernels do via appropriate language modules, it provides much more powerful ways to communicate with the kernels, the most important of which is the exchange of variables among subkernels.

Basic concepts

Before we get to the actual magics on how to exchange variables between kernels, it is helpful to understand that, SoS does not tranfer any variables among kernels, it creates independent homonymous variables of similar types that are native to the destination language. For example, if you have the following two variables

a = 1
b = c(1, 2)

in R and executes a magic

%get a b --from R

in a SoS cell, SoS actually execute the following statements, in the background, to create variables a and b in Python

a = 1
b = [1, 2]

As shown in the following figure, language modules try to choose the best method, sometimes in memory and sometimes via disk, to pass variables from one to another kernel, but all the complexity is hidden from you. Variables in different kernels are independent so that changing the value of variables a or b in one kernel will not affect the variable in another kernel. We also note that a and b are of different types in Python although they are of the same numeric type in R (a is technically speaking an array of size 1). That is to say, SoS does not gurantee one to one correspondence between datatypes, and does not gurantee lossless data exchange.

user_interface

Explicit data exchange with magic %get

The eastest way to get variable from another kernel is to use magic %get. It accepts one or more variable names and an option --from if you are not getting from the master SoS kernel.

For example, with a variable data defined in SoS,

In [1]:

you can %get the variables in a R kernel as follows

In [2]:
  1. -1
  2. 0
  3. 1
  4. 2
  5. 3
In [3]:
'test.txt'

The type of the data is numeric because data is a numeric list in Python

In [4]:
'numeric'

However, if the variable contains different types of data, for example integer and string,

In [5]:

It will be translated to a list in R

In [6]:
  1. 1
  2. 'abs'
In [7]:
'list'

Similarly, you can get a data.frame mtcars from R in SoS, but an option --from R is needed to specify the source kernel

In [8]:
Out[8]:
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6.0 160.0 110.0 3.90 2.620 16.46 0.0 1.0 4.0 4.0
Mazda RX4 Wag 21.0 6.0 160.0 110.0 3.90 2.875 17.02 0.0 1.0 4.0 4.0
Datsun 710 22.8 4.0 108.0 93.0 3.85 2.320 18.61 1.0 1.0 4.0 1.0
Hornet 4 Drive 21.4 6.0 258.0 110.0 3.08 3.215 19.44 1.0 0.0 3.0 1.0
Hornet Sportabout 18.7 8.0 360.0 175.0 3.15 3.440 17.02 0.0 0.0 3.0 2.0
Valiant 18.1 6.0 225.0 105.0 2.76 3.460 20.22 1.0 0.0 3.0 1.0
Duster 360 14.3 8.0 360.0 245.0 3.21 3.570 15.84 0.0 0.0 3.0 4.0
Merc 240D 24.4 4.0 146.7 62.0 3.69 3.190 20.00 1.0 0.0 4.0 2.0
Merc 230 22.8 4.0 140.8 95.0 3.92 3.150 22.90 1.0 0.0 4.0 2.0
Merc 280 19.2 6.0 167.6 123.0 3.92 3.440 18.30 1.0 0.0 4.0 4.0
Merc 280C 17.8 6.0 167.6 123.0 3.92 3.440 18.90 1.0 0.0 4.0 4.0
Merc 450SE 16.4 8.0 275.8 180.0 3.07 4.070 17.40 0.0 0.0 3.0 3.0
Merc 450SL 17.3 8.0 275.8 180.0 3.07 3.730 17.60 0.0 0.0 3.0 3.0
Merc 450SLC 15.2 8.0 275.8 180.0 3.07 3.780 18.00 0.0 0.0 3.0 3.0
Cadillac Fleetwood 10.4 8.0 472.0 205.0 2.93 5.250 17.98 0.0 0.0 3.0 4.0
Lincoln Continental 10.4 8.0 460.0 215.0 3.00 5.424 17.82 0.0 0.0 3.0 4.0
Chrysler Imperial 14.7 8.0 440.0 230.0 3.23 5.345 17.42 0.0 0.0 3.0 4.0
Fiat 128 32.4 4.0 78.7 66.0 4.08 2.200 19.47 1.0 1.0 4.0 1.0
Honda Civic 30.4 4.0 75.7 52.0 4.93 1.615 18.52 1.0 1.0 4.0 2.0
Toyota Corolla 33.9 4.0 71.1 65.0 4.22 1.835 19.90 1.0 1.0 4.0 1.0
Toyota Corona 21.5 4.0 120.1 97.0 3.70 2.465 20.01 1.0 0.0 3.0 1.0
Dodge Challenger 15.5 8.0 318.0 150.0 2.76 3.520 16.87 0.0 0.0 3.0 2.0
AMC Javelin 15.2 8.0 304.0 150.0 3.15 3.435 17.30 0.0 0.0 3.0 2.0
Camaro Z28 13.3 8.0 350.0 245.0 3.73 3.840 15.41 0.0 0.0 3.0 4.0
Pontiac Firebird 19.2 8.0 400.0 175.0 3.08 3.845 17.05 0.0 0.0 3.0 2.0
Fiat X1-9 27.3 4.0 79.0 66.0 4.08 1.935 18.90 1.0 1.0 4.0 1.0
Porsche 914-2 26.0 4.0 120.3 91.0 4.43 2.140 16.70 0.0 1.0 5.0 2.0
Lotus Europa 30.4 4.0 95.1 113.0 3.77 1.513 16.90 1.0 1.0 5.0 2.0
Ford Pantera L 15.8 8.0 351.0 264.0 4.22 3.170 14.50 0.0 1.0 5.0 4.0
Ferrari Dino 19.7 6.0 145.0 175.0 3.62 2.770 15.50 0.0 1.0 5.0 6.0
Maserati Bora 15.0 8.0 301.0 335.0 3.54 3.570 14.60 0.0 1.0 5.0 8.0
Volvo 142E 21.4 4.0 121.0 109.0 4.11 2.780 18.60 1.0 1.0 4.0 2.0

The type of mtcars in SoS (Python) is, not surprisingly, a Pandas DataFrame

In [9]:
Out[9]:
pandas.core.frame.DataFrame

You can also %get variables from one subkernel in another subkernel. For example the following cell gets mtcars from a Julia kernel. As the warning message says, because Julia dataframe does not yet support row labels, mtcars in Julia will not have row label.

In [10]:
Out[10]:
mpg cyl disp hp drat wt qsec vs am gear carb
Mazda RX4 21.0 6.0 160.0 110.0 3.90 2.620 16.46 0.0 1.0 4.0 4.0
Mazda RX4 Wag 21.0 6.0 160.0 110.0 3.90 2.875 17.02 0.0 1.0 4.0 4.0
Datsun 710 22.8 4.0 108.0 93.0 3.85 2.320 18.61 1.0 1.0 4.0 1.0
Hornet 4 Drive 21.4 6.0 258.0 110.0 3.08 3.215 19.44 1.0 0.0 3.0 1.0
Hornet Sportabout 18.7 8.0 360.0 175.0 3.15 3.440 17.02 0.0 0.0 3.0 2.0
Valiant 18.1 6.0 225.0 105.0 2.76 3.460 20.22 1.0 0.0 3.0 1.0
Duster 360 14.3 8.0 360.0 245.0 3.21 3.570 15.84 0.0 0.0 3.0 4.0
Merc 240D 24.4 4.0 146.7 62.0 3.69 3.190 20.00 1.0 0.0 4.0 2.0
Merc 230 22.8 4.0 140.8 95.0 3.92 3.150 22.90 1.0 0.0 4.0 2.0
Merc 280 19.2 6.0 167.6 123.0 3.92 3.440 18.30 1.0 0.0 4.0 4.0
Merc 280C 17.8 6.0 167.6 123.0 3.92 3.440 18.90 1.0 0.0 4.0 4.0
Merc 450SE 16.4 8.0 275.8 180.0 3.07 4.070 17.40 0.0 0.0 3.0 3.0
Merc 450SL 17.3 8.0 275.8 180.0 3.07 3.730 17.60 0.0 0.0 3.0 3.0
Merc 450SLC 15.2 8.0 275.8 180.0 3.07 3.780 18.00 0.0 0.0 3.0 3.0
Cadillac Fleetwood 10.4 8.0 472.0 205.0 2.93 5.250 17.98 0.0 0.0 3.0 4.0
Lincoln Continental 10.4 8.0 460.0 215.0 3.00 5.424 17.82 0.0 0.0 3.0 4.0
Chrysler Imperial 14.7 8.0 440.0 230.0 3.23 5.345 17.42 0.0 0.0 3.0 4.0
Fiat 128 32.4 4.0 78.7 66.0 4.08 2.200 19.47 1.0 1.0 4.0 1.0
Honda Civic 30.4 4.0 75.7 52.0 4.93 1.615 18.52 1.0 1.0 4.0 2.0
Toyota Corolla 33.9 4.0 71.1 65.0 4.22 1.835 19.90 1.0 1.0 4.0 1.0
Toyota Corona 21.5 4.0 120.1 97.0 3.70 2.465 20.01 1.0 0.0 3.0 1.0
Dodge Challenger 15.5 8.0 318.0 150.0 2.76 3.520 16.87 0.0 0.0 3.0 2.0
AMC Javelin 15.2 8.0 304.0 150.0 3.15 3.435 17.30 0.0 0.0 3.0 2.0
Camaro Z28 13.3 8.0 350.0 245.0 3.73 3.840 15.41 0.0 0.0 3.0 4.0
Pontiac Firebird 19.2 8.0 400.0 175.0 3.08 3.845 17.05 0.0 0.0 3.0 2.0
Fiat X1-9 27.3 4.0 79.0 66.0 4.08 1.935 18.90 1.0 1.0 4.0 1.0
Porsche 914-2 26.0 4.0 120.3 91.0 4.43 2.140 16.70 0.0 1.0 5.0 2.0
Lotus Europa 30.4 4.0 95.1 113.0 3.77 1.513 16.90 1.0 1.0 5.0 2.0
Ford Pantera L 15.8 8.0 351.0 264.0 4.22 3.170 14.50 0.0 1.0 5.0 4.0
Ferrari Dino 19.7 6.0 145.0 175.0 3.62 2.770 15.50 0.0 1.0 5.0 6.0
Maserati Bora 15.0 8.0 301.0 335.0 3.54 3.570 14.60 0.0 1.0 5.0 8.0
Volvo 142E 21.4 4.0 121.0 109.0 4.11 2.780 18.60 1.0 1.0 4.0 2.0

If you really need such information for your analysis in Julia, you will have to transfer it separately,

In [11]:
In [12]:
Out[12]:
32-element Array{String,1}:
 "Mazda RX4"        
 "Mazda RX4 Wag"    
 "Datsun 710"       
 "Hornet 4 Drive"   
 "Hornet Sportabout"
 "Valiant"          
 "Duster 360"       
 "Merc 240D"        
 "Merc 230"         
 "Merc 280"         
 "Merc 280C"        
 "Merc 450SE"       
 "Merc 450SL"       
 ⋮                  
 "Toyota Corona"    
 "Dodge Challenger" 
 "AMC Javelin"      
 "Camaro Z28"       
 "Pontiac Firebird" 
 "Fiat X1-9"        
 "Porsche 914-2"    
 "Lotus Europa"     
 "Ford Pantera L"   
 "Ferrari Dino"     
 "Maserati Bora"    
 "Volvo 142E"       

Putting variable to another kernel using magic %put

Magic %put is similar to %get but it puts variable from the current kernel to another. It by default put variables to SoS but can put to another subkernel with option --to.

For example, the following cell puts variable ncars to SoS:

In [13]:

It is important to note here, that although the %put magic is specified at the beginning of the cell (as required by SoS), it is actually executed after the cell is executed.

ncars is available in SoS after the %put magic

In [14]:
Out[14]:
32

Similarly, you can put variables to another kernel using the --to option:

In [15]:

and the variable df will be available in R

In [16]:
A data.frame: 4 × 3
num_legsnum_wingsnum_specimen_seen
<dbl><dbl><dbl>
falcon2210
dog40 2
spider80 1
fish00 8

Evaluating statements in another kernel with input and output variables using %with magic

Say during a Python-based data analysis procedure you are in need of a bunch of random numbers, and either you do not have Scipy installed or are more familiar with how R, you can call R as follows

In [17]:
In [18]:
In [19]:
Out[19]:
[0.777989112038058,
 -1.09720171824747,
 -0.937071777746947,
 -0.821497681562507,
 -0.651744430567863]

Here the %with magic is just a shortcut to

In [20]:

but %with R magic will appear to be function-call like procedure without changing the cell kernel.

The %with magic can also be used from a subkernel and calling statements in SoS or another subkernel. For example, the following cell calls the head function of DataFrame to get the first few rows of mtcars, and return as data.frame in R.

In [21]:
In [22]:
A data.frame: 5 × 11
mpgcyldisphpdratwtqsecvsamgearcarb
<dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl><dbl>
Mazda RX421.061601103.902.62016.460144
Mazda RX4 Wag21.061601103.902.87517.020144
Datsun 71022.84108 933.852.32018.611141
Hornet 4 Drive21.462581103.083.21519.441031
Hornet Sportabout18.783601753.153.44017.020032

Compare to all other multi-language approaches such as Python's rpy2, Julia's PyCall, or MATLAB's python engine, it is important to note that all statements and datatypes in a SoS environment are native and therefore easier to work with, with the disadvantage that your analyses can only be executed in SoS notebook (not as a standalone script).