在R中为数据框编写ifelse语句

4

我希望有人能帮助我解决如何编写if-else语句来处理我的数据集的问题。我有一些关于树木生长速率的数据,需要计算生长速率是否从一年到下一年下降了50%以上。我在应用ifelse语句计算最终结果时遇到了麻烦。我对R相对较新,所以我的代码可能不是很高效,但这是我目前的一个示例数据集:

test<-data.frame(year=c("1990","1991","1992","1993"),value=c(50,25,20,5))
  year value
1 1990    50
2 1991    25
3 1992    20
4 1993     5

然后我计算当前年份和上一年增长率之间的差异(“value”):

test[-1,"diff"]<-test[-1,"value"]-test[-nrow(test),"value"]
  year value diff
1 1990    50   NA
2 1991    25  -25
3 1992    20   -5
4 1993     5  -15

然后计算每年增长的50%:

test$chg<-test$value * 0.5
  year value diff  chg
1 1990    50   NA 25.0
2 1991    25  -25 12.5
3 1992    20   -5 10.0
4 1993     5  -15  2.5

我试图使用ifelse语句计算一个字段"abrupt",当从一年到下一年的下降幅度大于50%时,它将为"1"。这是我尝试使用的代码,但我不确定如何正确引用前一年的"chg"字段,因为我得到了一个错误(如下所示):

test$abrupt<-ifelse(test$diff<0 && abs(test$diff)>=test[-nrow(test),"chg"],1,0)
Warning message:
In abs(test$diff) >= test[-nrow(test), "chg"] :
longer object length is not a multiple of shorter object length
> test
  year value diff  chg abrupt
1 1990    50   NA 25.0     NA
2 1991    25  -25 12.5     NA
3 1992    20   -5 10.0     NA
4 1993     5  -15  2.5     NA

类似的ifelse语句已在我分配几个数字时进行了测试,但我不确定如何使其在datframe的情况下工作。以下是它在仅有几个值时工作的示例:

prevyear<-50
curryear<-25
chg<-prevyear*0.5
> chg
[1] 25
> diff<-curryear-prevyear
> diff
[1] -25
> abrupt<-ifelse(diff<0 && abs(diff)>= chg,1,0)
> abrupt
[1] 1

如果有人能帮我弄清如何将类似的ifelse语句应用到我的数据框中,我将非常感激!谢谢您提供的任何帮助。
谢谢, Katie

在另一个无关的问题上,您是否有其他编写此代码行的替代方法? test[-1, "diff"] <- test[-1, "value"] - test[-nrow(test), "value"] - kRazzy R
2个回答

4

出现警告是因为比较的两个向量 abs(test$diff) >= test[-nrow(test),"chg"] 长度不同。此外,对于逻辑与,你使用了 &&(只返回一个TRUE或FALSE),而应该使用 &(它是向量化的:在两个向量上进行按元素操作,并返回相同长度的向量)。尝试这样做:

test$abrupt<-ifelse(test$diff<0 & abs(test$diff)>=test$chg,1,0)

2
这比较了错误的 diffchg,除非 chg 被计算方式不同(请参见我的答案),但是因为显示了错误的来源而加1分。 - Jonathan Christensen
我有一个后续问题:我正在尝试将Jonathan的代码应用于我的真实数据。 我的真实数据中有合法的“NA”值,这阻止了最终ifelse语句中的“abs”函数运行。 当我尝试将该语句应用于我的真实数据时,我会收到以下错误消息:Error in abs(test$diff) : Non-numeric argument to mathematical function. 有人有建议如何在使用此语句中的“abs”函数时忽略“NA”值吗? 我认为我需要使用na.omit,但不确定它在ifelse语句中的位置。 感谢任何帮助!Katie - user1913921
@user1913921 abs(NA) 对我而言正确返回了 NAclass(test$diff)mode(test$diff) 是什么? - Blue Magister

3

我建议你把chg放在与你想要进行比较的diff对齐的位置:

test$chg[2:nrow(test)] <- test$value[1:(nrow(test)-1)] * 0.5

那么,按照 Blue Magister 的建议,更正你的逻辑运算符:
test$abrupt<-ifelse(test$diff<0 & abs(test$diff)>=test$chg,1,0)

然后您就可以得到结果:

  year value diff  chg abrupt
1 1990    50   NA   NA     NA
2 1991    25  -25 25.0      1
3 1992    20   -5 12.5      0
4 1993     5  -15 10.0      1

此外,您可能会发现函数diff很有帮助:不必执行以下操作:
test[-1,"value"]-test[-nrow(test),"value"]

你可以直接这样做

diff(test$value)

感谢所有回答我的问题的人。我选择了Jonathan的答案,因为它完美地解决了问题,但是还要感谢Blu Magister指出了我的ifelse语句中的错误,以及Arun向我展示了一种更有效的计算两年之间值差异的方法。再次感谢大家的帮助。 - user1913921
我有一个跟进问题。我现在正在尝试将Jonathan的答案中的代码应用到我的真实数据上。我的真实数据中有一些合法的“NA”值,因此在我的最终ifelse语句中“abs”语句无法工作。因此,我尝试使用这段代码: - user1913921

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接