gpt4 book ai didi

r - 一个r项目的文件和目录结构

转载 作者:行者123 更新时间:2023-12-04 16:31:43 26 4
gpt4 key购买 nike

在像 java 这样的通用编程语言中,每个文件通常对应一个类。

我刚开始使用 R。我想构建一个小程序,我想创建一个这样的特定文件和目录结构

Main.R # the main control script 
MyClass.R # A class that is referenced from within Main.R
ProcessData.R # Another class that uses an object of MyClass.R as input


所以我想做这样的事情(伪代码):

主R

myc <- new MyClass # create a new instance of MyClass from within Main.R
pd <- new ProcessData
pd$processMyClass( myc ) # call a method in ProcessData that processes the myc object in some way


所以这是相当抽象的,但我只是想知道这在 R 中原则上是否可行。

更新:我需要更具体。因此问题是:如何通过维护以下玩具程序的相同数量的文件和结构将以下 java 程序转换为 R 程序?

主.java:
public static void main( String[] args ) {
MyClass myc = new MyClass("SampleWord");
ProcessData pd = new ProcessData();
pd.processData( myc );
}

我的类
class MyClass {

public String word;

public MyClass( String word ) {
this.word = word;
}
}

进程数据.java
class ProcessData.java {

public void processData( MyClass myc ) {
System.out.println( "pd.processData = " + myc.word );
}

}

最佳答案

类(class)制度

查看 R、S3、S4 和引用类中的三个类系统。

## S3 methods, Section 5 of
RShowDoc("R-lang")

## S4 classes
?Classes
?Methods

## Reference classes
?ReferenceClasses

拥有 Java 背景,您会倾向于使用引用类,但这些类具有“引用语义”和远距离 Action (更改一个对象会更改另一个引用相同数据的对象),而大多数 R 用户期望“更改时复制” ' 语义。一个人可以在 S3 类(class)上取得很大进步,但在我看来,一种更有纪律的方法会采用 S4。 S4 的特性会让你大吃一惊,部分原因是类系统更接近普通的 lisp 对象系统而不是 java。

other opinions and options .

基本实现

我不太确定您对“ProcessData”的设计目标是什么;我会将您的两个类实现为一个类、一个泛型和一个对 MyClass 类进行操作的泛型方法。
## definition and 'low-level' constructor
.MyClass <- setClass("MyClass", representation(word="character"))

## definition of a generic
setGeneric("processData", function(x, ...) standardGeneric("processData"))

setMethod("processData", "MyClass", function(x, ...) {
cat("processData(MyClass) =", x@word, "\n")
})

这是完整且功能齐全的
> myClass <- .MyClass(word="hello world")
> processData(myClass)
processData(MyClass) = hello world

三个代码行可能放在两个文件中,“AllGenerics.R”和“MyClass.R”(包括方法)或三个文件“AllGenerics.R”、“AllClasses.R”、“processData-methods.R”(请注意,方法与泛型相关联,并在类上调度)。

额外的实现

通常会添加一个更用户友好的构造函数,例如,向用户提供有关预期数据类型或执行复杂参数初始化步骤的提示
MyClass <- function(word=character(), ...)
{
.MyClass(word=word, ...)
}

通常人们想要一个槽访问器,而不是直接的槽访问。这可以是一个简单的函数(如图所示)或一个通用的 + 方法。
word <- function(x, ...) x@word

如果要更新插槽,则编写一个替换函数或方法。函数或方法通常具有三个参数,要更新的对象、可能的附加参数以及用于更新对象的值。这是一个通用的+方法实现
setGeneric("word<-", function(x, ..., value) standardGeneric("word<-"))

setReplaceMethod("word", c("MyClass", "character"), function(x, ..., value) {
## note double dispatch on x=MyClass, value=character
x@word <- value
x
})

一个有点棘手的替代实现是
setReplaceMethod("word", c("MyClass", "character"), function(x, ..., value) {
initialize(x, word=value)
})

它使用 initialize泛型和默认方法作为复制构造函数;如果同时更新多个插槽,这会很有效。

由于用户可以看到该类,因此希望使用“show”方法以用户友好的方式显示它,该方法已经存在泛型 ( getGeneric("show") )
setMethod("show", "MyClass", function(object) {
cat("class:", class(object), "\n")
cat("word:", word(object), "\n")
})

现在我们的用户 session 看起来像
> myClass
class: MyClass
word: hello world
> word(myClass)
[1] "hello world"
> word(myClass) <- "goodbye world"
> processData(myClass)
processData(MyClass) = goodbye world

效率

R 对向量有效; S4类也不异常(exception)。所以设计是一个类的每个槽代表一个跨越多行的列,而不是单行的元素。我们期望槽“词”通常包含一个长度远大于 1 的向量,并且操作对向量的所有元素起作用。因此,人们会考虑到这一点来编写方法,例如,将 show 方法修改为
setMethod("show", "MyClass", function(object) {
cat("class:", class(object), "\n")
cat("word() length:", length(word(object)), "\n")
})

这是更大的数据对象(使用我的 Linux 系统上的文件)
> amer <- MyClass(readLines("/usr/share/dict/american-english"))
> brit <- MyClass(readLines("/usr/share/dict/british-english"))
> amer
class: MyClass
word() length: 99171
> brit
class: MyClass
word() length: 99156
> sum(word(amer) %in% word(brit))
[1] 97423
> amer_uc <- amer ## no copy, but marked to be copied if either changed
> word(amer_uc) <- toupper(word(amer_uc)) ## two distinct objects

所有这些都非常高效。

引用类别“远距离 Action ”的危害

让我们回到 S4 类的一个更简单的实现,直接访问插槽并且没有花哨的构造函数。这是美国词典和副本,已转换为大写
.MyClass <- setClass("MyClass", representation(word="character"))
amer <- .MyClass(word=readLines("/usr/share/dict/american-english"))
amer_uc <- amer
amer_uc@word <- toupper(amer_uc@word)

请注意,我们使用了大写 amer_uc但不是 amer :
> amer@word[99 + 1:10]
[1] "Adana" "Adar" "Adar's" "Addams" "Adderley"
[6] "Adderley's" "Addie" "Addie's" "Addison" "Adela"
> amer_uc@word[99 + 1:10]
[1] "ADANA" "ADAR" "ADAR'S" "ADDAMS" "ADDERLEY"
[6] "ADDERLEY'S" "ADDIE" "ADDIE'S" "ADDISON" "ADELA"

这正是 R 用户所期望的——我已经创建了一个单独的对象并对其进行了修改;原始对象未修改。这是我的断言;也许我不知道 R 用户期望什么。我假设 R 用户并没有真正注意这是一个引用类这一事实,而是认为它只是另一个 R 对象,如 integer()矢量或 data.framelm() 的返回值.

相比之下,这是一个引用类的最小实现,以及类似的操作
.MyRefClass <- setRefClass("MyRefClass", fields = list(word="character"))
amer <- .MyRefClass(word=readLines("/usr/share/dict/american-english"))
amer_uc <- amer
amer_uc$word <- toupper(amer_uc$word)

但现在我们已经改变了 ameramer_uc ! C 或 Java 程序员完全期望,但 R 用户不期望。
> amer$word[99 + 1:10]
[1] "ADANA" "ADAR" "ADAR'S" "ADDAMS" "ADDERLEY"
[6] "ADDERLEY'S" "ADDIE" "ADDIE'S" "ADDISON" "ADELA"
> amer_uc$word[99 + 1:10]
[1] "ADANA" "ADAR" "ADAR'S" "ADDAMS" "ADDERLEY"
[6] "ADDERLEY'S" "ADDIE" "ADDIE'S" "ADDISON" "ADELA"

关于r - 一个r项目的文件和目录结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16120652/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com