Das geht zum Glück ganz einfach: Man benutzt das $-Zeichen mit dem neuen Spaltennamen, um der Spalte direkt Werte zuzuweisen. Falls die Spalte noch nicht exisitert, wird sie hinzugefügt.

df <- data.frame(x = rnorm(10))
# fügt dem data.frame df eine neue Spalte y mit den quadrierten Werten von x hinzu
df$y <- df$x^2

Willst Du die Syntax von dem Package dplyr nutzen, geht das mit dem Befehl mutate. Dabei wir der data.frame df als erstes Argument übergeben. Als zweites Argument kommt dann die neue Variable y mit der Zuweisung. Allerdings ist dplyr

library(dplyr)
df <- data.frame(x = rnorm(10))
# der mutate-Befehl aus dem Package dplyr macht das gleiche
df <- mutate(df, y = x^2)
 
#alternativ mit der magrittr-Pipe
df <- df %>% mutate(y = x^2)

Mehr über das Package dplyr kannst Du in meiner ausführlichen Anleitung zu dplyr nachles

Mit dem Befehl mutate kann man auch mehrere neue Spalten mit einem Befehl hinzufügen. Diese dürfen sogar voneinander abhängen (wie in unserem Beispiel z von y), sofern die Reihenfolge stimmt (hier y vor z). Natürlich geht das ganze auch mit zwei base-R-Befehlen hintereinander.

# mehrere Spalten gleichzeitig hinzufügen
df <- mutate(df, 
             y = x^2, 
             z = 3*y + rnorm(10)
             )
 
# klassisch
df$y <- df$x^2
df$z <- 3*df$y + rnorm(10)

Benchmark

Ein (nicht sehr realitätsnahes) Benchmark zeigt, dass die klassische Variante schneller ist:

library(rbenchmark)
n = 1000
benchmark(klassisch = {df <- data.frame(x = rnorm(n));df$y <- df$x^2},
          dplyr = {df <- data.frame(x = rnorm(n));df <- mutate(df, y = x^2)},
          replications = 1000
          )
 
benchmark(klassisch = {df <- data.frame(x = rnorm(n));df$y <- df$x^2;df$z <- 3*df$y+rnorm(n)},
          dplyr = {df <- data.frame(x = rnorm(n));df <- mutate(df, y = x^2, z = 3*y + rnorm(n))},
          replications = 1000
)