Büyük R programları nasıl organize edilir?


161

Herhangi bir karmaşıklıkta bir R projesi üstlendiğimde, komut dosyalarım hızla uzar ve kafa karıştırır.

Kodumun her zaman çalışmaktan zevk alacağı şekilde benimseyebileceğim bazı uygulamalar nelerdir? Gibi şeyleri düşünüyorum

  • İşlevlerin kaynak dosyalara yerleştirilmesi
  • Bir şey başka bir kaynak dosyaya ne zaman çıkarılır?
  • Ana dosyada ne olmalı
  • İşlevleri örgütsel birimler olarak kullanma (R'nin küresel duruma erişmeyi zorlaştırdığı göz önüne alındığında, bunun değerli olup olmadığı)
  • Girinti / satır sonu uygulamaları.
    • Tedavi edin ({?
    • )} Gibi şeyleri 1 veya 2 satıra koy?

Temel olarak, büyük R betiklerini düzenlemek için temel kurallarınız nelerdir?


12
topluluk wiki olmalı
SilentGhost

ProjectTemplatePakete bakmak da isteyebilirsiniz .
ctbrown

Yanıtlar:


71

Standart cevap paketleri kullanmaktır - R Eklentileri Yazma kılavuzunun yanı sıra web'deki farklı eğitimlere bakın.

Sana verir

  • kodunuzu konuya göre düzenlemenin yarı otomatik bir yolu
  • arayüz hakkında düşünmenizi sağlayan bir yardım dosyası yazmanızı şiddetle tavsiye eder
  • bir sürü akıl sağlığı kontrolü R CMD check
  • regresyon testleri ekleme şansı
  • ve ad alanları için bir araç.

Sadece source()kod üzerinden geçmek gerçekten kısa parçacıklar için çalışır. Diğer her şey bir paket içinde olmalıdır - dahili depolar için dahili paketler yazabileceğiniz için yayınlamayı planlamasanız bile.

'Nasıl düzenlenir' bölümüne gelince, R Internals kılavuzunun Bölüm 6'da mükemmel R kodlama standartları vardır. Aksi takdirde Emacs'ın ESS modunda varsayılanları kullanma eğilimindeyim .

Güncelleme 2008-Ağu-13: David Smith Google R Stil Rehberi hakkında yeni blog yazdı .


8
Kaynak ağacınızı / analizinizi "organik olarak" büyütüyorsanız, bunu zor / külfetli bulmuyor musunuz? Kodunuzda bir hata fark ederseniz (yeni bir sorun alanı keşfederken yaygındır), (i) kaynağı düzeltmeniz gerekir; (ii) paketi yeniden yükleme; (iii) çalışma alanınıza yeniden yüklensin mi? Önceden yüklenmiş bir paketi yeniden yüklemek için kitaplığı (...) çağırmanın bir yolu var mı (yukarıdaki adım iii)? Çalışma alanınızı öldürmeniz, R'yi yeniden başlatmanız ve doğru olup olmadığını görmek için kitaplığınızı / paketinizi yeniden yüklemeniz gerekmez mi?
Steve Lianoglou

1
R kodlama stili için googling deniyor.
hadley

3
@SteveLianoglou Bunun oldukça eski olduğunu biliyorum ama Hadley'in devtools paketi tüm kodlarınızı yeniden yüklemeyi çok kolay hale getiriyor.
Dason

1
Bu blog yayını çıplak kemikleri ilk paketi oluşturmak için gerçekten iyi hızlı öğretici bir (fikrimi) verir: hilaryparker.com/2014/04/29/writing-an-r-package-from-scratch
panterasBox


51

Kendi dosyalarına farklı işlevler koymayı seviyorum.

Ama R'nin paket sistemini sevmiyorum. Kullanımı oldukça zor.

Bir dosyanın işlevlerini bir ortama yerleştirmek için (diğer her dilin "ad alanı" olarak adlandırdığı şey) hafif bir alternatifi tercih ediyorum. Örneğin, şöyle bir 'util' işlev grubu yaptım:

util = new.env()

util$bgrep = function [...]

util$timeit = function [...]

while("util" %in% search())
  detach("util")
attach(util)

Tüm bunlar util.R dosyasındadır . Kaynak yaptığınızda, çevreyi 'util' alırsınız, böylece arayabilirsiniz util$bgrep()ve böyle; ancak dahası, attach()çağrı bunu çok adil bgrep()ve doğrudan yapar. Tüm bu işlevleri kendi ortamlarına koymazsanız, tercümanın üst düzey ad alanını (gösteren olanı ls()) kirletir .

Her dosyanın bir modül olduğu Python sistemini simüle etmeye çalışıyordum. Sahip olmak daha iyi olurdu, ama bu iyi görünüyor.


Teşekkürler, Brendan. Bu çok faydalı. While döngüsü ne durumda? If (! (% Search ()) içinde "util"%) attach (util) ile ilgili sorun nedir
Dan Goldstein

2
böylece ince ayar yapmak istiyorsanız kaynak ("util.R") öğesini tekrar tekrar yapabilirsiniz.
Brendan OConnor

gerçekten bir while döngüsüne ihtiyacınız yok - ihtiyacınız olan tek şey ayırın (util). zaten yüklü değilse bir hata verir ya da değil hatırlayamıyorum, ama bu en güvenli ve işe yarıyor. önerilerinizi bekliyoruz.
Brendan OConnor

1
İşlevlere özgü ortamlar oluşturmak ve onu takmak benim için doğru yoldur. Başka bir yöntem (diğer bir modülarite) farklı bir şekilde bu işlem için kullanımı için sys.source: MyEnv <- attach(NULL, name=s_env); sys.source(file, MyEnv). Başlangıçta bile (kendi ortamında!) sys.source2Aynı adda bir ortam zaten buradaysa ve yeni bir tane oluşturmak yerine bunu besleyen bir işlevi açıklar. Bu, kişisel işlevler eklemeyi hızlı, kolay ve biraz organize hale getirir :-)
Antoine Lizée

5
Sadece bugün gördüm ve bir paket alternatifi için geçerlidir: github.com/klmr/modules
ctbrown

34

Bu, özellikle bir programcıysanız biraz açık gelebilir, ancak mantıksal ve fiziksel kod birimlerini düşünüyorum.

Senin durumun bu olup olmadığını bilmiyorum, ama R'de çalışırken nadiren büyük bir karmaşık programla başlıyorum. Genellikle bir komut dosyasında başlar ve genellikle işlevleri kullanarak, mantıksal olarak ayrılabilir birimlere kod ayırırım. Veri işleme ve görselleştirme kodu kendi işlevlerine vb. Yerleştirilir. Ve bu işlevler dosyanın bir bölümünde (üstte veri işleme, sonra görselleştirme vb.) Birlikte gruplandırılır. Sonuçta senaryonuzu korumanızı ve hata oranını düşürmenizi nasıl kolaylaştıracağınızı düşünmek istersiniz.

İşlevlerinizi ne kadar iyi / kaba tanecik yaptığınız değişir ve çeşitli temel kurallar vardır: örneğin 15 satırlık kod veya "bir işlev adıyla tanımlanan bir görevi yerine getirmekten sorumlu olmalıdır" vb. . R, çağrı yoluyla referansı desteklemediğinden, genellikle veri çerçevelerini veya benzer yapıları geçmeyi içerdiğinde işlevlerimi çok ince yapılıyorum. Ancak bu, R ile ilk başladığımda bazı aptalca performans hatalarının aşırı telafisi olabilir.

Mantıksal birimleri ne zaman kendi fiziksel birimlerine (kaynak dosyalar ve paketler gibi daha büyük gruplar gibi) çıkarmalıyız? İki vakam var. İlk olarak, dosya çok büyür ve mantıksal olarak ilgisiz birimler arasında dolaşmak bir sıkıntıdır. İkincisi, diğer programlar tarafından yeniden kullanılabilen işlevlerim varsa. Genelde veri işleme işlevleri gibi bazı gruplanmış birimleri ayrı bir dosyaya yerleştirerek işe başlarım. Daha sonra bu dosyayı başka bir komut dosyasından kaynaklayabilirim.

İşlevlerinizi dağıtacaksanız, paketleri düşünmeye başlamanız gerekir. R kodunu üretimde veya başkaları tarafından çeşitli nedenlerle yeniden kullanmıyorum (kısaca: org kültürü diğer dilleri, performansla ilgili endişeleri, GPL vb. Ayrıca, kaynaklı dosyalar koleksiyonlarımı sürekli olarak iyileştirme ve eklememe eğilimindeyim ve bir değişiklik yaptığımda paketlerle ilgilenmemeyi tercih ederim. Bu yüzden, bu cephede daha fazla ayrıntı için Dirk's gibi paketle ilgili diğer cevaplara göz atmalısınız.

Son olarak, sorunuzun R'ye özgü olmadığını düşünüyorum. Steve McConnell'in Code Complete tarafından okunması ve bu konular ve kodlama uygulamaları hakkında birçok bilgelik içeren gerçekten okunmasını tavsiye ederim.


3
Çok yararlı yorum, ars, teşekkür ederim. Ben bir programcıyım, ama başkalarına danışmak güzel. "R, çağrı referansını desteklemediğinden, genellikle işlevlerimi çok ince taneli yapmaktan çekiniyorum" dediğinizde, sizi duyuyorum. Ben ReadData () gibi işlevleri yazmaya alışkınım; CleanData (); Veri analizi(); GraphData (); ve R bunu hantal yapar. Diğer dillerde işlevleri kullanma şeklimi "kaynak" olarak kullanmam gerektiği fikrine uyanıyorum.
Dan Goldstein

2
Haklısın Dan. Kendimi veri kümesi hazırlama görevleri için bu şekilde "kaynak" kullanarak buldum, bu yüzden gerçek analiz yapılan diğer komut dosyaları arasında hazırlanmış bir data.frame kullanabilirsiniz. Bunun iyi bir uygulama olup olmadığından hiç emin olamadım çünkü diğer dillere göre garip geliyor - daha çok kabuk komut dosyası gibi. Notları karşılaştırmak iyidir. :)
ars

Güzel cevap ve yorumlar. Bunun özellikle R'de sinir bozucu olduğunu düşünüyorum, çünkü genellikle yeniden kullanılabilir işlevler yazmak gerçekten zor olan belirli bir formattaki verilerle çalışıyorsunuz. Öyleyse asla tekrar kullanılmayacağını bilseniz bile güzel bir işlevsel kod yazıyor musunuz, yoksa sadece büyük nesnelerle biraz daha fazla verimlilik elde etmek için hızlı ve kötü bir prosedür kodu mu yazıyorsunuz? Bir ikilem biraz .. R referans ile çağrı kesinlikle harika olurdu ..
naught101

Peki, bir çeşit yapılabilir, ancak verimlilik kazancı yoktur ...
naught101

19

Dirk tavsiyesine katılıyorum! IMHO, programlarınızı basit komut dosyalarından belgelenmiş paketlere düzenlemek, R'de Programlama için, Word'den TeX / LaTeX'e yazmak için geçiş yapmak gibidir. Çok yararlı R Paketleri Oluşturma: Friedrich Leisch'in Öğreticisine bir göz atmanızı tavsiye ederim.


6
Paketler ilgi çekici görünüyor. Ancak, aşırıya kaçmaları konusunda endişelendim. Genel amaçlı kod yazmıyorum. Yaptığım şeylerin çoğu bu hipotezi test etmek, bu hipotezi test etmek, bunu çizmek, çizim parametrelerini ayarlamak, bunu çizmek, verileri yeniden şekillendirmek, çizmek. İşiniz bittiğinde, muhtemelen asla tekrar çalıştırılmayacak şeyler yapıyorum.
Dan Goldstein

1
Bu durumda Sweave'ye bir göz atmalısınız. R kodunu LaTeX ile birleştirir. Böylece analiz ve rapor kaynağını birlikte elde edersiniz.
Thierry

15

Kısa cevabım:

  1. Yeterli genel çıkış ve girişleri tanımlayarak işlevlerinizi dikkatlice yazın;
  2. Global değişkenlerin kullanımını sınırlamak;
  3. S3 nesnelerini ve uygun olduğunda S4 nesnelerini kullanın;
  4. İşlevleri, özellikle işlevleriniz C / Fortran'ı çağırırken, paketlere koyun.

R'nin üretimde gittikçe daha fazla kullanıldığına inanıyorum, bu nedenle yeniden kullanılabilir koda olan ihtiyaç öncekinden daha fazla. Tercümanı öncekinden çok daha sağlam buluyorum. R'nin C'den 100-300x daha yavaş olduğuna şüphe yoktur, ancak genellikle darboğaz C / C ++ 'ya devredilebilen birkaç kod satırı etrafında yoğunlaşmıştır. Veri manipülasyonu ve istatistiksel analizdeki R'nin güçlü yönlerini başka bir dile devretmenin bir hata olacağını düşünüyorum. Bu durumlarda, performans cezası düşüktür ve her durumda geliştirme çabasındaki tasarruflara değer. Mesele sadece yürütme zamanı olsaydı hepimiz meclis yazarıydık.


11

Paketleri nasıl yazacağımı anlamaya çalışıyordum ama zaman ayırmadım. Mini projelerimin her biri için tüm alt düzey işlevlerimi 'function /' adlı bir klasörde saklıyorum ve bunları açıkça oluşturduğum ayrı bir ad alanına kaynak alıyorum.

Aşağıdaki kod satırları, zaten yoksa (attach kullanarak) arama yolunda "myfuncs" adında bir ortam oluşturur ve bunu 'function /' dizinindeki .r dosyalarında bulunan işlevlerle doldurur ( sys.source). Genellikle bu satırları, üst düzey işlevlerin (alt düzey işlevleri çağıran) çağrıldığı "kullanıcı arabirimi" için kullanılan ana komut dizimin üstüne koydum.

if( length(grep("^myfuncs$",search()))==0 )
  attach("myfuncs",pos=2)
for( f in list.files("functions","\\.r$",full=TRUE) )
  sys.source(f,pos.to.env(grep("^myfuncs$",search())))

Değişiklik yaptığınızda, her zaman aynı satırlarla yeniden kaynak yapabilir veya

evalq(f <- function(x) x * 2, pos.to.env(grep("^myfuncs$",search())))

oluşturduğunuz ortamdaki eklemeleri / değişiklikleri değerlendirmek için.

Biliyorum kludgey, ama bu konuda çok resmi olmaktan kaçınıyor (ancak eğer şansınız olursa paket sistemini teşvik ediyorum - umarım gelecekte bu şekilde göç edeceğim).

Kodlama kurallarına gelince, bu estetik ile ilgili gördüğüm tek şey (onları seviyorum ve gevşek takip ediyorum ama R'de çok fazla kıvırcık parantez kullanmıyorum):

http://www1.maths.lth.se/help/R/RCC/

UseR'de çeşitli sunumlarda (genellikle açılış konuşması) önerilen atama operatörü olarak [, drop = FALSE] ve <- kullanımına ilişkin başka "kurallar" vardır. (ancak [, drop = FALSE] beklediğiniz girdiden emin olmadığınız programlar için yararlı olsa da) bunlardan herhangi birinin katı olduğunu düşünmüyorum.


6

Beni paketler lehine başka biri olarak say. Ben (yani serbest bırakılmak zorunda) kadar / zaman kadar adam sayfaları ve vinyet yazma konusunda oldukça fakir olduğunu kabul edeceğim, ama kaynak doe paketlemek için gerçekten kullanışlı bir yol yapar. Ayrıca, kodunuzu korumak konusunda ciddiyseniz, Dirk'in getirdiği noktalar plyaya dönüşür.


4

Ben de katılıyorum. Başlamak için package.skeleton () işlevini kullanın. Kodunuzun bir daha asla çalıştırılmayacağını düşünseniz bile, daha sonra size zaman kazandırabilecek daha genel bir kod oluşturmanıza yardımcı olabilir.

Küresel ortama erişmeye gelince, cesaret kırılmış olsa da, << operatör ile bu kolaydır.


3

Henüz nasıl paket yazılacağını öğrenemedikten sonra, her zaman alt komut dosyaları sağlayarak organize oldum. Yazma sınıflarına benzer, ancak dahil olduğu gibi değil. Programlı olarak zarif değil ama zaman içinde analizler oluşturduğumu görüyorum. Bir kez çalışan büyük bir bölüm var sık ​​sık farklı bir komut dosyasına taşıyın ve sadece çalışma alanı nesneleri kullanacağı için kaynak. Belki birkaç kaynaktan veri almam, hepsini sıralamam ve kavşakları bulmam gerekiyor. Bu bölümü ek bir senaryoya koyabilirim. Ancak, "uygulamanızı" başka kişiler için dağıtmak veya bazı etkileşimli girdiler kullanmak istiyorsanız, paket muhtemelen iyi bir yoldur. Bir araştırmacı olarak analiz kodumu nadiren dağıtmam gerekiyor, ancak sık sık artırmam ya da değiştirmem gerekiyor.


Ben bu yöntemi kullandım ama o zamandan beri fonksiyonları ve paketleri kaynak ("next_script.R") daha iyi olduğunu fark var. Burada yazdım: stackoverflow.com/questions/25273166/…
Arthur Yip

1

Ayrıca R büyük bir projeyi bir araya getirmek için doğru iş akışının kutsal kasesini de arıyordum. Geçen yıl rsuite adı verilen bu paketi buldum ve kesinlikle aradığım şey buydu. Bu R paketi, büyük R projelerinin konuşlandırılması için açıkça geliştirildi, ancak daha küçük, orta boy ve büyük boyutlu R projeleri için kullanılabileceğini buldum. Bir dakika içinde (aşağıda) gerçek dünya örneklerine bağlantılar vereceğim, ancak önce R projeleri inşa etmenin yeni paradigmasını açıklamak istiyorum rsuite.

Not. Ben yaratıcısı ya da geliştiricisi değilim rsuite.

  1. RStudio ile tamamen yanlış projeler yapıyoruz; amaç, bir proje veya paket oluşturmak değil, daha geniş bir kapsam oluşturmak olmalıdır. Rsuite'de, mümkün olan tüm kombinasyonlarda standart R projelerini ve R paketlerini barındıran bir süper proje veya ana proje yaratırsınız.

  2. Bir R süper projesine sahipken, makealtındaki R projelerinin daha düşük seviyelerini yönetmek için artık Unix'e ihtiyacınız yok ; üstte R komut dosyaları kullanırsınız. Sana göstereyim. Bir rsuite ana projesi oluşturduğunuzda, bu klasör yapısını alırsınız:

resim açıklamasını buraya girin

  1. Klasör R, yerini alacak olan proje yönetimi komut dosyalarınızı koyduğunuz yerdir make.

  2. Klasör packages, rsuitesüper projeyi oluşturan tüm paketleri içeren klasördür . Ayrıca internetten erişilemeyen bir paketi kopyalayıp yapıştırabilirsiniz ve rsuite de oluşturacaktır.

  3. klasör deployment, rsuitepaketler DESCRIPTIONdosyasında belirtilen tüm paket ikili dosyalarını yazacağı yerdir . Yani, bu, kendi başına, tamamen tekrarlanabilir accros zamanını yansıtır.

  4. rsuitetüm işletim sistemleri için bir istemci ile birlikte gelir. Hepsini test ettim. Ancak addinRStudio için bir olarak da yükleyebilirsiniz .

  5. rsuiteayrıca condakendi klasöründe yalıtılmış bir kurulum oluşturmanıza izin verir conda. Bu bir ortam değil, makinenizdeki Anaconda'dan türetilen fiziksel bir Python kurulumu. Bu SystemRequirements, istediğiniz tüm Python paketlerini istediğiniz herhangi bir conda kanalından yükleyebileceğiniz R'lerle birlikte çalışır.

  6. Çevrimdışı olduğunuzda veya her şeyi daha hızlı oluşturmak istediğinizde, R paketlerini çekmek için yerel depolar da oluşturabilirsiniz.

  7. İsterseniz, R projesini bir zip dosyası olarak da oluşturabilir ve iş arkadaşlarınızla paylaşabilirsiniz. İş arkadaşlarınıza aynı R sürümünün yüklü olması koşuluyla çalışır.

  8. Başka bir seçenek, Ubuntu, Debian veya CentOS'ta tüm projenin bir konteynerini oluşturmaktır. Böylece, bir zip dosyasını proje yapınızla paylaşmak yerine, tüm Dockerkapsayıcıyı projenizle çalışmaya hazır olarak paylaşırsınız .

rsuiteTam tekrarlanabilirlik aramak için çok şey deniyorum ve küresel ortamda yüklediği paketlere bağlı kalmaktan kaçınıyorum. Bu yanlıştır, çünkü bir paket güncellemesini kurar kurmaz, proje, çoğu zaman, çalışmayı durdurur, özellikle belirli parametrelere sahip bir fonksiyona çok özel çağrıları olan paketler.

Denemeye başladığım ilk şey bookdowne-kitaplarla oldu. Altı aydan daha uzun bir süre testten kurtulmak için bir rezervasyon yaptırdığım kadar şanslı olmamıştım. Yaptığım şey orijinal kayıt projesini rsuiteçerçeveyi takip edecek şekilde dönüştürmek . Şimdi, global R ortamımı güncelleme konusunda endişelenmem gerekmiyor, çünkü projenin deploymentklasörde kendi paketleri var .

Yaptığım bir sonraki şey makine öğrenim projeleri oluşturmaktı ama bu rsuiteşekilde oldu. Üstte bir master, orkestrasyon projesi ve master'ın kontrolü altında olacak tüm alt projeler ve paketler. R ile kodlama şeklinizi gerçekten değiştirerek sizi daha üretken hale getirir.

Ondan sonra yeni bir paketimde çalışmaya başladım rTorch. Bu, büyük olasılıkla rsuite; düşünmenizi ve büyümenizi sağlar.

Bir parça tavsiye olsa. Öğrenmek rsuitekolay değil. R projeleri yaratmanın yeni bir yolunu sunduğu için zor geliyor. İlk denemelerde dehşete düşmeyin, yokuşa kadar tırmanmaya devam edin. İşletim sisteminiz ve dosya sisteminiz hakkında ileri düzeyde bilgi gerektirir.

Bir gün menüden olduğu RStudiogibi orkestrasyon projeleri üretmemize izin veriyor rsuite. Harika olurdu.

Bağlantılar:

RSuite GitHUb repo

r4ds bookdown

keras ve parlak öğretici

moderndive-kitap-rsuite

interpretable_ml-rsuite

IntroMachineLearningWithR-rsuite

Clark-intro_ml-rsuite

Hyndman-bookdown-rsuite

statistical_rethinking-rsuite

fread-kriterler-rsuite

dataviz-rsuite

perakende segmentasyon-h2o-öğretici

telekom-müşteri müşteri kaybı-öğretici

sclerotinia_rsuite


-7

R, etkileşimli kullanım ve küçük komut dosyaları için sorun değil, ancak büyük bir program için kullanmam. Çoğu programlama için genel bir dil kullanır ve onu bir R arayüzüne sararım.


1
Orada çok büyük paketler (yani programlar) var. Başka bir dilde yeniden yazılmaları gerektiğini ciddiye alıyor musunuz? Neden???
Eduardo Leoni

4
Bunlardan biri verimliliktir. Sık sık R kodu C ++ kodu olarak yeniden yazdım ve 100 kat daha hızlı yaptım. Bir diğeri araç desteğidir. R'nin Eclipse veya Visual Studio gibi IDE'lerle karşılaştırılabilir hiçbir şeyi yoktur. Son olarak, bir program çok büyükse, R'nin uygun olmadığı istatistiksel olmayan görevler yapıyor olması muhtemeldir.
John D. Cook

2
Eclipse'in R ile etkileşime girmesine izin veren bir eklenti (Stat-ET) var. C ++ 'nın R'den daha hızlı çalışabileceğini kabul ediyorum. Kodu sık sık tekrar kullanamazsanız, daha hızlı kodun faydası, C ++ 'da yeniden kodlama çabasına kıyasla çok fazla değmez.
Thierry

2
Evet, bir değiş tokuş var (verimlilik v performans). Ve tamamen veri analizi / istatistiksel çalışma için, R genellikle kazanır. Ancak GUI, web vb.Gibi diğer görevleri yazmak için durumun bu olduğundan emin değilim. Genellikle R'de prototip üretir ve çalışırız, ancak üretim kodunu Python / C ++ 'da kullanırız. İkincisi ile çeşitli görevler için performans ve çok olgun ve yeniden kullanılabilir kütüphaneler / çerçeveler elde edersiniz . Ancak, bu akışkan bir durumdur ve R ekosistemi sürekli olarak gelişmektedir.
ars

RcppR programlarında C ++ kodu da dahil olmak üzere paketi kullanmak oldukça kolaylaşır. Bu nedenle, R kodunun belirli bölümlerinin yeniden yazılması R'ye kolayca entegre edilebilir. Buna ek olarak, RStudio'nun ortaya çıkışı, henüz Visual Studio kadar güçlü olmasa da, R için bir IDE tanıttı.
Paul Hiemstra
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.