我是编写函数的新手,我不确定从哪里开始。下面是此示例中名为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
非常感谢任何帮助。 感谢
答案 0 :(得分:3)
从你发表评论我明白你想获得独特的行。幸运的是,这里有一个功能:
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
。
答案 1 :(得分:2)
编辑:从问题中不清楚数据是以矩阵还是以数据帧形式。
如果是数据帧,则x [2]是长度> 1的向量。因此,你的病情只会测试第一个因素。如果是矩阵,请参阅@Roland的解释。
作为初学者,在写作时,建议从“里里外外”开始。即,不要先写功能。从简单的代码片开始。查看m1[2]
给出的内容。查看m1[2]==1
给出的布尔值(表达式是TRUE还是FALSE)。然后尝试运行条件。只有当代码的主/键部分按预期工作时,手头有特定数据,才能围绕该代码包装函数。
您尝试实现的特定功能必须遍历第2列中的所有值。因此,需要某种循环,例如, for
或apply
。
答案 2 :(得分:1)
您可以使用拆分功能将数据框拆分为单独的数据框列表。如果您的数据框被称为foo,那么:
foo.split<-split(foo[,c('length','depth')],foo$number)
根据此列表,您可以命名列表的每个元素,提取元素等。
注意,这仅适用于数据帧。如果您有矩阵,可以使用data.frame()函数将其转换为数据框。