【问题标题】:Mutate and ifelse() fail becase of NA existence in column变异和 ifelse() 失败,因为列中存在 NA
【发布时间】:2016-09-08 03:59:44
【问题描述】:

我在尝试使用 ifelse 创建新列时遇到问题。非常相似的问题是这个dplyr error: strange issue when combining group_by, mutate and ifelse. Is it a bug?

set.seed(101)
time =sort(runif(10,0,10))  
group=rep(c(1,2),each=5)
az=c(sort(runif(5,-1,1),decreasing = T),sort(runif(5,-1,0.2),decreasing = T))

df <- data.frame(time,az,group)

#       time          az group
#1  0.4382482  0.86326886     1
#2  2.4985572  0.75959146     1
#3  3.0005483  0.46394519     1
#4  3.3346714  0.41374948     1
#5  3.7219838 -0.08975881     1
#6  5.4582855 -0.01547669     2
#7  5.8486663 -0.29161632     2
#8  6.2201196 -0.50599980     2
#9  6.5769040 -0.73105782     2
#10 7.0968402 -0.95366733     2

df 中,我正在尝试条件变异clas 列。但是,由于sw_time 内部有NA,因此所有clas 列也变为NA,其中group 1 通常应该是nrm

df1 <- df%>%
  group_by(group)%>%
  mutate(sw_time=abs(time[which(az<=0.8)[1]]-time[which(az>0)[1]]))%>%
  mutate(clas=as.numeric(ifelse(sw_time<3,"nrm","abn")))

Source: local data frame [10 x 5]
Groups: group [2]

        time          az group  sw_time  clas
       (dbl)       (dbl) (dbl)    (dbl) (dbl)
1  0.4382482  0.86326886     1 2.060309    NA
2  2.4985572  0.75959146     1 2.060309    NA
3  3.0005483  0.46394519     1 2.060309    NA
4  3.3346714  0.41374948     1 2.060309    NA
5  3.7219838 -0.08975881     1 2.060309    NA
6  5.4582855 -0.01547669     2       NA    NA
7  5.8486663 -0.29161632     2       NA    NA
8  6.2201196 -0.50599980     2       NA    NA
9  6.5769040 -0.73105782     2       NA    NA
10 7.0968402 -0.95366733     2       NA    NA

提前感谢您的行动!

【问题讨论】:

  • 您将字符强制转换为数字。它肯定会导致NA。也许你需要clas = as.numeric(factor(ifelse(...
  • @akrun 是的,我刚试过,但现在 group 1 clas 变成 1 而不是 nrm
  • 在这种情况下,您只需删除as.numeric

标签: r dplyr


【解决方案1】:

通过将character 类转换为numeric,将得到NA。相反,我们可能需要一个 factor 类来强制转换为 numeric

df %>%
    group_by(group)%>%
     mutate(sw_time=abs(time[which(az<=0.8)[1]]-time[which(az>0)[1]]),
            clas=as.integer(factor(ifelse(sw_time<3,"nrm","abn"))))

如果我们只对获取 'nrm'、'abn' 感兴趣,只需删除 as.integer(factor 包装

df%>%
  group_by(group)%>%
  mutate(sw_time=abs(time[which(az<=0.8)[1]]-time[which(az>0)[1]]),
          clas=ifelse(sw_time<3,"nrm","abn"))
#        time          az group  sw_time  clas
#       <dbl>       <dbl> <dbl>    <dbl> <chr>
#1  0.4382482  0.86326886     1 2.060309   nrm
#2  2.4985572  0.75959146     1 2.060309   nrm
#3  3.0005483  0.46394519     1 2.060309   nrm
#4  3.3346714  0.41374948     1 2.060309   nrm
#5  3.7219838 -0.08975881     1 2.060309   nrm
#6  5.4582855 -0.01547669     2       NA  <NA>
#7  5.8486663 -0.29161632     2       NA  <NA>
#8  6.2201196 -0.50599980     2       NA  <NA>
#9  6.5769040 -0.73105782     2       NA  <NA>
#10 7.0968402 -0.95366733     2       NA  <NA>

我们也可以使用data.table

library(data.table)
setDT(df)[, c("sw_time", "clas") := {
           v1 <- abs(time[which(az <= 0.8)[1]] - time[which(az > 0)[1]])
          .(v1 , c("abn", "nrm")[(v1 < 3) + 1]) },
                      by = group]

如果最终输出不涉及'nrm'、'abn',我们就不需要ifelse部分。我们可以直接使用as.integer(sw_time &lt;3)

【讨论】:

  • 我无法直接使用as.integer(sw_time&lt;3)。如果没有ifelse,应该定义nrmabn在哪里?
  • @Alexander 请检查第二个代码块。最后一个是当我不确定预期的输出时。我以为你想要一个数字索引而不是 'nrm', 'abn'
  • 预期是nrm这样的字符。实际上,当我运行df%&gt;% group_by(group)%&gt;% mutate(sw_time=abs(time[which(az&lt;=0.8)[1]]-time[which(az&gt;0)[1]]), clas=ifelse(sw_time&lt;3,"nrm","abn")) 时,我收到错误Error: incompatible types, expecting a character vector。实际上这是我的原始代码对吗?
  • @Alexander 我正在使用您的示例数据。你有哪个版本的dplyr?我正在使用dplyr_0.5.0
  • 我用的是dplyr_0.4.3,后来改成了dplyr_0.5.0。都修好了!感谢您的建议和大力帮助!问候!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-31
  • 1970-01-01
  • 2016-11-22
  • 1970-01-01
  • 1970-01-01
  • 2017-06-13
  • 1970-01-01
相关资源
最近更新 更多