Bu cevap, mevcut cevaplarla aynı unsurların çoğunu kapsayacaktır, ancak bu konu (sütun adlarının işlevlere aktarılması), işleri biraz daha kapsamlı bir şekilde kapsayan bir cevap olmasını istediğim kadar sık ortaya çıkıyor.
Çok basit bir veri çerçevemiz olduğunu varsayalım:
dat <- data.frame(x = 1:4,
y = 5:8)
ve z
sütunların toplamı olan yeni bir sütun oluşturan bir işlev yazmak istiyoruz x
ve y
.
Buradaki çok yaygın bir engel, doğal (ancak yanlış) bir girişimin genellikle şöyle görünmesidir:
foo <- function(df,col_name,col1,col2){
df$col_name <- df$col1 + df$col2
df
}
#Call foo() like this:
foo(dat,z,x,y)
Buradaki sorun df$col1
, ifadenin değerlendirilmemesidir col1
. df
Kelimenin tam anlamıyla çağrılan bir sütun arar col1
. Bu davranış, ?Extract
"Özyinelemeli (liste benzeri) Nesneler" bölümünde açıklanmaktadır .
En basit ve en sık önerilen çözüm geçiş basitçe olduğu $
için [[
dizeleri olarak işlev argümanları ve pass:
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
Bu, batırması en zor yöntem olduğu için genellikle "en iyi uygulama" olarak kabul edilir. Sütun adlarını dizeler olarak geçirmek, elde edebileceğiniz kadar nettir.
Aşağıdaki iki seçenek daha gelişmiştir. Pek çok popüler paket bu tür teknikleri kullanır, ancak bunları iyi kullanmak daha fazla özen ve beceri gerektirir, çünkü bunlar ince karmaşıklıklar ve beklenmeyen başarısızlık noktaları ortaya çıkarabilir. Hadley'in Advanced R kitabının bu bölümü, bu sorunlardan bazıları için mükemmel bir referanstır.
Eğer varsa gerçekten tüm bu tırnak yazarak kullanıcıyı kaydetmek istediğiniz, seçeneklerden biri kullanılarak dizeleri çıplak, tırnaksız sütun adlarını dönüştürmek olabilir 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
Açıkçası, bu biraz saçma bir olasılık, çünkü gerçekten de aynı şeyi yapıyoruz new_column1
, sadece çıplak isimleri dizelere dönüştürmek için fazladan bir sürü işle.
Son olarak, gerçekten süslü olmak istiyorsak , eklemek için iki sütunun adlarını iletmek yerine, daha esnek olmaya ve iki değişkenin diğer kombinasyonlarına izin vermeye karar verebiliriz. Bu durumda, muhtemelen eval()
iki sütunu içeren bir ifadeye başvurabiliriz :
new_column3 <- function(df,col_name,expr){
col_name <- deparse(substitute(col_name))
df[[col_name]] <- eval(substitute(expr),df,parent.frame())
df
}
Sırf eğlence olsun diye, hala deparse(substitute())
yeni sütunun adını kullanıyorum . Burada aşağıdakilerin tümü çalışacaktır:
> 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
Yani kısa cevap temelde şudur: data.frame sütun adlarını dizeler olarak geçirin ve [[
tek sütunları seçmek için kullanın . Sadece delving başlamak eval
, substitute
gerçekten ne yaptığını biliyorsan, vb.