【问题标题】:writing user defined functions编写用户定义的函数
【发布时间】:2013-04-24 13:53:38
【问题描述】:

我是编写函数的新手,我不确定从哪里开始。下面是此示例中名为 m1 的数据框的子集。我想编写一个函数来遍历数据集并按数字提取长度和深度信息。例如,如果它遇到数字 1,它会获取长度和深度并将它们插入到新数据帧或向量的第一行中。如果数字等于 2,它会执行相同的操作,依此类推。

       length number depth
 [1,]    109      1    10
 [2,]    109      1    10
 [3,]    109      1    10
 [4,]    109      1    10
 [5,]    109      1    10
 [6,]    109      1    10
 [7,]    109      1    10
 [8,]    109      1    10
 [9,]    109      1    10
[10,]    109      1    10
[11,]    109      1    10
[12,]    109      1    10
[13,]    107      2    10
[14,]    107      2    10
[15,]    107      2    10
[16,]    107      2    10
[17,]    107      2    10
[18,]    107      2    10
[19,]    107      2    10
[20,]    107      2    10

如果数字等于 1,则尝试编写一个函数来获得上述输出。

length.fun=function(x)
{
  lengths=numeric()
  depth=numeric()
  if (x[2]==1)
  {
    lengths=x[1]
    depth=x[3]
  }
  return(cbind(depth,lengths))
}

length.fun(m1)

但是,我得到的输出是这样的:

length.fun(m1)
   depth lengths

非常感谢任何帮助。 谢谢

【问题讨论】:

  • 它看起来不像 data.frame。 class(m1) 的输出是什么?
  • 你的目标是什么?一个data.frame,有两行,一行用于depth,一行用于lengths。或多行,number 中的每个唯一元素一个。或者有多行,number 中的每个唯一元素两个,lengths 一个,depth 一个?请详细一点。
  • user1997414,据我了解,您希望为每个数字值创建单独的数据框(或矩阵)。这是真的。如果这是真的,也许您可​​以提供一些背景信息来说明您为什么要这样做?
  • 我的目标是拥有一个由@PaulHiemstra 建议的包含两列的数据框,深度和长度。每个数字在此数据框中应该只有一行。 10 10910 107
  • 每个数字应该只有一行是什么意思?鉴于你上面的例子,你能告诉我们输出应该是什么吗?这将使找到合适的解决方案变得更加容易。

标签: r function user-defined-functions


【解决方案1】:

编辑:

从您的评论中,我了解到您想要获得唯一的行。幸运的是,有一个专门用于此的功能:

unique(m1)

#       length number depth
# [1,]     109      1    10
# [13,]    107      2    10

unique(m1)[,-2] 只会给你两列。使用as.data.frame 将矩阵转换为data.frame。


m1 是一个矩阵。矩阵只是具有维度属性的向量。 m1[2] 为您提供向量中的第二个值,即109。因此,您的 if 条件是 FALSE,而您的函数中的 cbind 为空向量。

这就是你想要的:

m1[m1[,2]==1,c(1,3)]

您应该阅读 R 中的矩阵子集。

您可以使用调试功能来检查发生的情况。这是一个例子:

首先使用browser 在函数中插入断点。

length.fun=function(x)
{
  lengths=numeric()
  depth=numeric()
  if (x[2]==1)
  {browser("1")
    lengths=x[1]
    depth=x[3]
  }
  browser("2")
  return(cbind(depth,lengths))
}

现在使用trace调用函数。

trace(length.fun(m1))

你会得到一个提示,允许你检查变量的状态。

> trace(length.fun(m1))
Called from: length.fun(m1)
Browse[1]> browserText()
[1] "2"
Browse[1]> lengths
numeric(0)
Browse[1]> Q

如您所见,到达的第一个断点是第二个断点。因此,if 构造的条件是FALSE,并且其中的代码从未执行过。 lengths 的值也证实了这一点。

【讨论】:

    【解决方案2】:

    编辑:从问题中不清楚数据是矩阵形式还是数据框形式。

    如果它是一个数据框,那么 x[2] 是一个长度 > 1 的向量。因此,您的条件将只测试第一个元素。如果是矩阵,请看@Roland的解释。

    作为初学者,在编写函数时,建议从“内向外”进行。即,不要先编写函数。从简单的代码片段开始。看看m1[2] 给出了什么。查看m1[2]==1 给出了哪些布尔值(这个表达式是 TRUE 还是 FALSE)。然后尝试运行条件。只有当代码的主要/关键部分按预期工作时,手头有特定的数据,才将函数包装在该代码周围。

    您尝试实现的特定功能必须循环遍历第 2 列中的所有值。因此,需要某种循环,例如forapply

    【讨论】:

    • (-1) x[2] 是一个长度为 1 的向量。
    • @Roland 在矩阵中,是的。在 data.frame 中,没有。 m1 是一个数据帧。自己去看看吧。
    • 根据显示的输出,m1 是一个矩阵。如果它是一个 data.frame,他们会从函数中得到一个警告。
    • @Roland 没错。但是,请参阅问题的第二句话。它清楚地指定了类。 OP是否有可能省略了警告?
    • 让我们看看,他们怎么说。现在我还给你 2 分。
    【解决方案3】:

    您可以使用拆分功能将数据框拆分为单独的数据框列表。如果您的数据框被称为 foo 那么:

    foo.split<-split(foo[,c('length','depth')],foo$number)
    

    给定这个列表,您可以命名列表中的每个元素,提取元素等。

    注意,这仅适用于数据帧。如果您有一个矩阵,您可以使用 data.frame() 函数将其转换为数据框。

    【讨论】:

    • Roland,他写道:“下面是此示例中名为 m1 的数据框的子集”。
    • 他们显然是初学者,现在可能还不是,他们实际拥有的东西。
    • 没错,在这种情况下,他们可以使用 data.frame 函数将他们的矩阵转换为数据框。我会编辑它。
    猜你喜欢
    • 2016-03-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-08
    • 1970-01-01
    • 1970-01-01
    • 2015-10-23
    • 1970-01-01
    相关资源
    最近更新 更多