Jawaban ini akan mencakup banyak elemen yang sama dengan jawaban yang sudah ada, tetapi masalah ini (meneruskan nama kolom ke fungsi) cukup sering muncul sehingga saya ingin ada jawaban yang mencakup hal-hal sedikit lebih komprehensif.
Misalkan kita memiliki kerangka data yang sangat sederhana:
dat <- data.frame(x = 1:4,
y = 5:8)
dan kami ingin menulis fungsi yang membuat kolom baru z
yang merupakan jumlah kolom x
dan y
.
Batu sandungan yang sangat umum di sini adalah bahwa upaya alami (tetapi tidak benar) sering kali terlihat seperti ini:
foo <- function(df,col_name,col1,col2){
df$col_name <- df$col1 + df$col2
df
}
#Call foo() like this:
foo(dat,z,x,y)
Masalahnya di sini adalah itu df$col1
tidak mengevaluasi ekspresi col1
. Ini hanya mencari kolom yang df
secara harfiah disebut col1
. Perilaku ini dijelaskan di ?Extract
bawah bagian "Objek rekursif (seperti daftar)".
Solusi paling sederhana, dan paling sering direkomendasikan adalah dengan beralih dari $
ke [[
dan meneruskan argumen fungsi sebagai string:
new_column1 <- function(df,col_name,col1,col2){
#Create new column col_name as sum of col1 and col2
df[[col_name]] <- df[[col1]] + df[[col2]]
df
}
> new_column1(dat,"z","x","y")
x y z
1 1 5 6
2 2 6 8
3 3 7 10
4 4 8 12
Ini sering dianggap "praktik terbaik" karena ini adalah metode yang paling sulit untuk gagal. Meneruskan nama kolom sebagai string sama jelasnya dengan yang Anda bisa.
Dua opsi berikut ini lebih maju. Banyak paket populer yang menggunakan jenis teknik ini, tetapi menggunakannya dengan baik membutuhkan lebih banyak perhatian dan keterampilan, karena paket tersebut dapat menimbulkan kerumitan halus dan titik kegagalan yang tidak terduga. Ini bagian dari buku Lanjutan R Hadley adalah referensi yang sangat baik untuk beberapa masalah ini.
Jika Anda benar - benar ingin menyelamatkan pengguna agar tidak mengetik semua tanda kutip tersebut, salah satu opsi mungkin adalah mengonversi nama kolom yang kosong dan tidak bertanda kutip menjadi string menggunakan deparse(substitute())
:
new_column2 <- function(df,col_name,col1,col2){
col_name <- deparse(substitute(col_name))
col1 <- deparse(substitute(col1))
col2 <- deparse(substitute(col2))
df[[col_name]] <- df[[col1]] + df[[col2]]
df
}
> new_column2(dat,z,x,y)
x y z
1 1 5 6
2 2 6 8
3 3 7 10
4 4 8 12
Ini, sejujurnya, mungkin agak konyol, karena kami benar-benar melakukan hal yang sama seperti di new_column1
, hanya dengan banyak pekerjaan tambahan untuk mengubah nama kosong menjadi string.
Terakhir, jika kita ingin benar - benar mewah, kita mungkin memutuskan bahwa daripada memasukkan nama dua kolom untuk ditambahkan, kita ingin lebih fleksibel dan memungkinkan kombinasi lain dari dua variabel. Dalam hal ini kami kemungkinan akan menggunakan eval()
ekspresi yang melibatkan dua kolom:
new_column3 <- function(df,col_name,expr){
col_name <- deparse(substitute(col_name))
df[[col_name]] <- eval(substitute(expr),df,parent.frame())
df
}
Cuma iseng, saya masih pakai deparse(substitute())
untuk nama kolom baru. Di sini, semua hal berikut akan berfungsi:
> new_column3(dat,z,x+y)
x y z
1 1 5 6
2 2 6 8
3 3 7 10
4 4 8 12
> new_column3(dat,z,x-y)
x y z
1 1 5 -4
2 2 6 -4
3 3 7 -4
4 4 8 -4
> new_column3(dat,z,x*y)
x y z
1 1 5 5
2 2 6 12
3 3 7 21
4 4 8 32
Jadi jawaban singkatnya pada dasarnya adalah: berikan nama kolom data.frame sebagai string dan gunakan [[
untuk memilih kolom tunggal. Hanya mulai menggali eval
, substitute
, dll jika Anda benar-benar tahu apa yang Anda lakukan.