ifelse 和 POSIXct:NA 的强制和默认 class
ifelse and POSIXct: coercion and default class of NA
这是我的例子:
library(dplyr)
my_df <- data.frame(col_1 = c(1,2,4), col_2 = c('2017-12-1', '2015-11-2', '2011-2-5'))
my_df$col_2 <- as.POSIXct(my_df$col_2)
out <- ifelse(my_df$col_1 ==2, my_df$col_2+ as.difftime(3, units = 'days'), NA)
print(out)
它产生:
NA 1446703200 NA
所以强制转换是由于不同的数据类型而发生的。我应该使用什么 NA
数据类型来防止它:NA_date_
或 NA_POSIX_
或...?
使用赋值逐步执行此操作可能比 ifelse
更好。
1) 创建索引
i1 <- my_df$col_1 == 2
2) 根据索引赋值
my_df$col_2[i1] <- my_df$col_2[i1] + as.difftime(3, units = 'days')
3) 将其他元素改为NA
my_df$col_2[!i1] <- NA
my_df
# col_1 col_2
#1 1 <NA>
#2 2 2015-11-05
#3 4 <NA>
原因是 POSIXct
存储模式是 numeric
,在 ifelse
中它被强制转换为 numeric
形式
如果我们使用 tidyverse
,那么
library(tidyverse)
my_df %>%
mutate(col_2 = col_2 + days(3),
col_2 = replace(col_2, col_1 != 2, NA))
data.table
可以轻松修改特定行
require(data.table)
my_df <- data.frame(col_1 = c(1,2,4), col_2 = c('2017-12-1', '2015-11-2', '2011-2-5'))
setDT(my_df)
my_df[, col_2 := as.POSIXct(col_2)
][col_1 == 2, col_2 := col_2 + as.difftime(3, units = 'days')
][col_1 != 2, col_2 := NA]
因为您(出于某种原因 ;))已经加载了 dplyr
,您可以使用 if_else
并将 false
NA
包装在 as.POSIXct
* :
if_else(my_df$col_1 == 2, my_df$col_2 + as.difftime(3, units = 'days'), as.POSIXct(NA))
# [1] NA "2015-11-05 CET" NA
*参见?as.POSIXct
:
Logical NA
s can be converted to either of the classes [POSIXlt
and POSIXct
]
相关问题:
How to prevent ifelse() from turning Date objects into numeric objects. See also the comment by @roarkz 和我的回答。
这是我的例子:
library(dplyr)
my_df <- data.frame(col_1 = c(1,2,4), col_2 = c('2017-12-1', '2015-11-2', '2011-2-5'))
my_df$col_2 <- as.POSIXct(my_df$col_2)
out <- ifelse(my_df$col_1 ==2, my_df$col_2+ as.difftime(3, units = 'days'), NA)
print(out)
它产生:
NA 1446703200 NA
所以强制转换是由于不同的数据类型而发生的。我应该使用什么 NA
数据类型来防止它:NA_date_
或 NA_POSIX_
或...?
使用赋值逐步执行此操作可能比 ifelse
更好。
1) 创建索引
i1 <- my_df$col_1 == 2
2) 根据索引赋值
my_df$col_2[i1] <- my_df$col_2[i1] + as.difftime(3, units = 'days')
3) 将其他元素改为NA
my_df$col_2[!i1] <- NA
my_df
# col_1 col_2
#1 1 <NA>
#2 2 2015-11-05
#3 4 <NA>
原因是 POSIXct
存储模式是 numeric
,在 ifelse
中它被强制转换为 numeric
形式
如果我们使用 tidyverse
,那么
library(tidyverse)
my_df %>%
mutate(col_2 = col_2 + days(3),
col_2 = replace(col_2, col_1 != 2, NA))
data.table
可以轻松修改特定行
require(data.table)
my_df <- data.frame(col_1 = c(1,2,4), col_2 = c('2017-12-1', '2015-11-2', '2011-2-5'))
setDT(my_df)
my_df[, col_2 := as.POSIXct(col_2)
][col_1 == 2, col_2 := col_2 + as.difftime(3, units = 'days')
][col_1 != 2, col_2 := NA]
因为您(出于某种原因 ;))已经加载了 dplyr
,您可以使用 if_else
并将 false
NA
包装在 as.POSIXct
* :
if_else(my_df$col_1 == 2, my_df$col_2 + as.difftime(3, units = 'days'), as.POSIXct(NA))
# [1] NA "2015-11-05 CET" NA
*参见?as.POSIXct
:
Logical
NA
s can be converted to either of the classes [POSIXlt
andPOSIXct
]
相关问题:
How to prevent ifelse() from turning Date objects into numeric objects. See also the comment by @roarkz 和我的回答。