R 如何修复一个简单的代码进行条件变异

R 如何修复一个简单的代码进行条件变异,r,conditional-statements,mutate,R,Conditional Statements,Mutate,我需要根据数据框中旧列中的值创建一个新变量。如果现有值以.0结尾,则新列中的新值将为0/但如果现有值以.1结尾,则新列中的新值将为1/但我使用的小代码不区分11.0和11.1(以及具有类似模式的其他对) 我附上一个例子和不成功的解决方案 c<-c(1.1,1.0, 0.1, 0.0, 80.1, 80.0, 91.1, 91.0, 11.1,11.0) b<-c(1,1,0,0,80,80,91,91,11,11) cb<-data.frame(b,c) #this is e

我需要根据数据框中旧列中的值创建一个新变量。如果现有值以.0结尾,则新列中的新值将为0/但如果现有值以.1结尾,则新列中的新值将为1/但我使用的小代码不区分11.0和11.1(以及具有类似模式的其他对)

我附上一个例子和不成功的解决方案

c<-c(1.1,1.0, 0.1, 0.0, 80.1, 80.0, 91.1, 91.0, 11.1,11.0)
b<-c(1,1,0,0,80,80,91,91,11,11)

cb<-data.frame(b,c) #this is exaple to my data

cb<-mutate(cb, a = ifelse(grepl( ".1" ,   cb$c ), 1, 0 )) #this is my unsuccessful solution

a<-c(1,0,1,0,1,0,1,0,1,0)
abc<-data.frame(a,c,b) # This is the desired result

c您的正则表达式可能是错误的,您的
“.1”
应该是
“\\.1”
,以查找文字点

因为你的数据实际上是数字的,你真的应该用数字来测试它。不幸的是(无论是数字还是grepl比较,这都会影响您的
####.1
可能会在内部转换为
####.099999
,这显然会失败。虽然理论上可以生成一个捕捉到这个错误的正则表达式,但它开始变得有点复杂()。所以,你应该用数字来测试它

但由于它是浮点型的,所以

if_else(c%%1==0.1,1,0)
也可能因为同样的原因而失败。一个更大的例子:

seq(0.1,10.1)
#  [1]  0.1  1.1  2.1  3.1  4.1  5.1  6.1  7.1  8.1  9.1 10.1
序号(0.1,10.1)%%1
#  [1] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
###这就是它变得有趣的地方
(序号(0.1,10.1)%%1)=0.1
#[1]真假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假
(序号(0.1,10.1)%%1-0.1)
#[1]0.000000e+00 8.326673e-17 8.326673e-17 8.326673e-17-3.608225e-16-3.608225e-16-3.608225e-16-3.608225e-16-3.608225e-16
#[9]-3.608225e-16-3.608225e-16-3.608225e-16
事实上,任何带有<代码>数字(浮点)的东西都应该专注于不平等性的测试,原因如(和IEEE-754)所述。长话短说:因为数字存储在精度上有一个限制,所以在进行比较时,你永远无法精确地得到你想要的数字。(在99.9%的情况下,您可能会得到正确的结果,但这0.1%的测试结果将不正确,并且没有任何提示。)

考虑一个不平等性测试:

if_else(abs(c%%1-0.1)<1e-8,1,0)
#或者只是
1L*(abs(c%%1-0.1)<1e-8)
###使用上面的演示
资产负债表(序号(0.1,10.1)%%1-0.1)<1e-8
#[1]正确
我对
1e-8
的选择是任意的,只是一个起点,因为它取决于您拥有的数据类型。由于您的比较标度为“0.1”,坦率地说,您可以使用
abs(c%%1-0.1)<0.01
。实际使用中可以得到的最小值是
.Machine$double.eps
(有关其属性的定义,请参阅),尽管我发现在许多应用程序中,更大数量级的东西仍然可以

注意:一般来说,这完全取决于数字的范围,因此请不要在不了解选择错误边界的前提和后果的情况下盲目使用
1e-8


(我支持我的评论:键入并使用名为
c
的变量只会…让我的大脑受伤:-)

你的正则表达式可能是错误的,你的
“.1”
应该是
“\\.1”
来寻找文字点

因为你的数据实际上是数字的,你真的应该用数字来测试它。不幸的是(无论是数字还是grepl比较,这都会影响您的
####.1
可能会在内部转换为
####.099999
,这显然会失败。虽然理论上可以生成一个捕捉到这个错误的正则表达式,但它开始变得有点复杂()。所以,你应该用数字来测试它

但由于它是浮点型的,所以

if_else(c%%1==0.1,1,0)
也可能因为同样的原因而失败。一个更大的例子:

seq(0.1,10.1)
#  [1]  0.1  1.1  2.1  3.1  4.1  5.1  6.1  7.1  8.1  9.1 10.1
序号(0.1,10.1)%%1
#  [1] 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1
###这就是它变得有趣的地方
(序号(0.1,10.1)%%1)=0.1
#[1]真假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假假
(序号(0.1,10.1)%%1-0.1)
#[1]0.000000e+00 8.326673e-17 8.326673e-17 8.326673e-17-3.608225e-16-3.608225e-16-3.608225e-16-3.608225e-16-3.608225e-16
#[9]-3.608225e-16-3.608225e-16-3.608225e-16
事实上,任何带有<代码>数字(浮点)的东西都应该专注于不平等性的测试,原因如(和IEEE-754)所述。长话短说:因为数字存储在精度上有一个限制,所以在进行比较时,你永远无法精确地得到你想要的数字。(在99.9%的情况下,您可能会得到正确的结果,但这0.1%的测试结果将不正确,并且没有任何提示。)

考虑一个不平等性测试:

if_else(abs(c%%1-0.1)<1e-8,1,0)
#或者只是
1L*(abs(c%%1-0.1)<1e-8)
###使用上面的演示
资产负债表(序号(0.1,10.1)%%1-0.1)<1e-8
#[1]正确
我对
1e-8
的选择是任意的,只是一个起点,因为它取决于您拥有的数据类型。由于您的比较标度为“0.1”,坦率地说,您可以使用
abs(c%%1-0.1)<0.01
。实际使用中可以得到的最小值是
.Machine$double.eps
(有关其属性的定义,请参阅),尽管我发现在许多应用程序中,更大数量级的东西仍然可以

注意:一般来说,这完全取决于数字的范围,因此请不要在不了解选择错误边界的前提和后果的情况下盲目使用
1e-8

(我支持我的评论:键入并使用名为
c
的变量只是…让我的大脑受伤:-)

(1)不要在
mutate
内部使用
cb$
,只要使用变量名即可。(2) 用变量重载基R函数是一种非常糟糕的形式,它可能是