Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Assignment to empty index (empty square brackets x[]<-) on LHS

While looking at an answer posted recently on SO, I noticed an unfamiliar assignment statement. Instead of the usual form of myVar<- myValue, it used the form myVar[]<- myValue, i.e. the object on lefthand side is indexed with empty square brackets. Personally, I had never seen such an assignment, but it had a highly useful effect-- it reshaped the assigned data 'myValue' to the shape of 'myVar'.

I would like to use this in my code as this makes things lot easier. However the documentation for "<-" seems to be silent on it.

Is this a well established feature and one can rely on it to work in all cases?

Also, my guess is that it might be a side effect of a function call stack, i.e. calling <- and [ in sequence, but I could not figure out how. Can someone throw some light on that?

Here's an example--

# A dataframe
df1 <- data.frame(a = 1:4, b = 11:14)

# simple assignment assigns to class of RHS
df1 <- c(21:24, 31:34)
df1 
#[1] 21 22 23 24 31 32 33 34
class(df1)
#[1] "integer"

#assignment with [] casts to class of LHS 
df1<- data.frame(a = 1:4, b = 11:14)
df1[]<- c(21:24,31:34)
df1

#    a  b
# 1 21 31
# 2 22 32
# 3 23 33
# 4 24 34


# recycling to preserve shape
df1[]<- c(101:102)
df1

#     a   b
# 1 101 101
# 2 102 102
# 3 101 101
# 4 102 102

class(df1)
#data.frame

# reshaping 

df1<- data.frame(a = 1:4, b = 11:14)
df1[] <- matrix(1:8, 2,4)
df1 #matrix reshaped 
class(df1)
#[1] "data.frame"

# flattening 
x<- 1:8
x[] <- matrix(1:8,4,2)
x
#[1] 1 2 3 4 5 6 7 8
like image 977
R.S. Avatar asked Dec 16 '16 19:12

R.S.


People also ask

What does empty square brackets mean in MATLAB?

MATLAB has positional input arguments. Many MATLAB functions use an empty numeric array (i.e. []) to indicate that an input argument is undefined, which allows further input arguments to be specified.

What do empty brackets mean in Python?

This is to indicate that you have an empty "list" as opposed to any variables. It also allows you to invoke specific methods like . append used in your code for subst_words.

How do you use square brackets in Python?

Values in a Python dictionary can be accessed by placing the key within square brackets next to the dictionary. Values can be written by placing key within square brackets next to the dictionary and using the assignment operator ( = ). If the key already exists, the old value will be overwritten.


1 Answers

This is an intentional and documented feature. As joran mentioned, the documentation page "Extract" includes this in the "Atomic Vectors" section:

An empty index selects all values: this is most often used to replace all the entries but keep the attributes.

However, in the case of recursive objects (data.frames or lists, for example), the attributes are only kept for the subsetted object. Its parts don't get such protection.

Here's an example:

animals <- factor(c('cat', 'dog', 'fish'))
df_factor <- data.frame(x = animals)
rownames(df_factor) <- c('meow', 'bark', 'blub')
str(df_factor)
# 'data.frame': 3 obs. of  1 variable:
#   $ x: Factor w/ 3 levels "cat","dog","fish": 1 2 3

df_factor[] <- 'cat'
str(df_factor)
# 'data.frame': 3 obs. of  1 variable:
#   $ x: chr  "cat" "cat" "cat"
rownames(df_factor)
# [1] "meow" "bark" "blub"

df_factor kept its rownames attribute, but the x column is just the character vector used in the assignment instead of a factor. We can keep the class and levels of x by specifically replacing its values:

df_factor <- data.frame(x = animals)
df_factor$x[] <- 'cat'
str(df_factor)
# 'data.frame': 3 obs. of  1 variable:
#   $ x: Factor w/ 3 levels "cat","dog","fish": 1 1 1

So replacement with empty subsetting is very safe for vectors, matrices, and arrays, because their elements can't have their own attributes. But it requires some care when dealing with list-like objects.

like image 112
Nathan Werth Avatar answered Sep 30 '22 16:09

Nathan Werth