Not sure what am I missing here but ifelse
is not changing a value as I would expect. I am trying to change a week value if the month and day meet a certain criteria. Instead I am getting "FALSE"
where it should be 52
. Example below:
我不确定我在这里遗漏了什么,但如果其他值没有像我预期的那样改变值。如果月和日满足特定条件,我会尝试更改周的值。相反,我在应该是52的地方得到了“假”。示例如下:
> a
SampleDate year month week day
1 2013-01-05 2013 January 01 05
2 2013-01-08 2013 January 02 08
3 2013-01-08 2013 January 02 08
4 2013-01-05 2013 January 01 05
5 2013-01-05 2013 January 01 05
6 2013-01-08 2013 January 02 08
7 2013-01-08 2013 January 02 08
8 2013-01-05 2013 January 01 05
9 2013-01-03 2013 January 01 03
10 2013-01-08 2013 January 02 08
11 2013-01-07 2013 January 02 07
12 2013-01-03 2013 January 01 03
13 2013-01-03 2013 January 01 03
14 2013-01-08 2013 January 02 31
15 2013-01-07 2013 January 02 07
16 2013-01-03 2013 January 01 31
>
> ## "FALSE" should be 52
> with(a, ifelse(month == 'January' & day == 31, week == 52, week))
[1] "01" "02" "02" "01" "01" "02" "02" "01" "01"
[10] "02" "02" "01" "01" "FALSE" "02" "FALSE"
data
a <- structure(list(SampleDate = structure(c(15710, 15713, 15713,
15710, 15710, 15713, 15713, 15710, 15708, 15713, 15712, 15708,
15708, 15713, 15712, 15708), class = "Date"), year = c("2013",
"2013", "2013", "2013", "2013", "2013", "2013", "2013", "2013",
"2013", "2013", "2013", "2013", "2013", "2013", "2013"), month = c("January",
"January", "January", "January", "January", "January", "January",
"January", "January", "January", "January", "January", "January",
"January", "January", "January"), week = c("01", "02", "02",
"01", "01", "02", "02", "01", "01", "02", "02", "01", "01", "02",
"02", "01"), day = c("05", "08", "08", "05", "05", "08", "08",
"05", "03", "08", "07", "03", "03", "31", "07", "31")), row.names = c(NA,
-16L), class = "data.frame")
更多回答
week==52
seems out of place, and here is one great example of how "ifelse
is not class-safe is breaking for you. This effectively says "if month is january and day is 31 then return a logical vector else return a character vector". Clearly not what should be happening.
Week==52似乎不合时宜,这里有一个很好的例子来说明“如果不是类安全的话就不适合你。这实际上是说”如果月是一月,天是31,那么返回一个逻辑向量,否则返回一个字符向量“。显然不应该发生这样的事情。
week==52
is filling the yes=
argument, which means its values are returned when the test=
(first) argument is true. If the test=
vector were all TRUE
, then the return value from this ifelse
would be a logical
vector. However, since at least one of the test
conditions are false, the fact that day
is a character string casts all of the return values to string, which means TRUE
-> "TRUE"
(or "FALSE"
). Please explain what you intend the week==52
to really mean.
Week==52填充了yes=参数,这意味着当test=(第一个)参数为真时返回它的值。如果TEST=VECTOR都为真,则该IF的返回值将是一个逻辑向量。然而,由于至少有一个测试条件为假,因此day is a字符串将所有返回值转换为字符串,这意味着真->“真”(或“假”)。请解释一下你打算这一周的真正含义。
Because of this, btw, I suggest you switch from using base::ifelse
to dplyr::if_else
: it will fail but fail unambiguously (more clearly) and explain why what you tried to do is likely a mistake. There are rare times when I think ifelse
is adequate.
由于这个原因,顺便说一句,我建议您从使用base::ifElse切换到dplyr::if_Else:它将失败,但会明确地(更清楚地)失败,并解释为什么您尝试做的事情可能是错误的。我认为如果其他条件足够的话,这种情况很少见。
I want tne numeric value of week to be 52 if month is january and day is 31. Not sure how else to explain it.
如果月是一月,天是31,我希望周的数值是52。不知道还能怎么解释。
The issue is that you were testing equality with ==
. You wanted to assign to week inside of ifelse
which cannot be done, the assignment must be done using =
(single) (or optionally <-
if not inside mutate
) and must be outside of the ifelse
.
问题是您测试的是==的等价性。您想要在If Else中为Week赋值,但无法完成,则必须使用=(Single)(或可选的<-如果不在Mariate中)来完成赋值,并且必须在If Else之外。
You want to change the value of week
, based on the values of month
and day
. Here's one way to do that:
您希望根据月和日的值更改Week的值。有一种方法可以做到这一点:
library(dplyr)
a |> mutate(week = if_else(month == 'January' & day == 31, '52', week))
SampleDate year month week day
1 2013-01-05 2013 January 01 05
2 2013-01-08 2013 January 02 08
3 2013-01-08 2013 January 02 08
4 2013-01-05 2013 January 01 05
5 2013-01-05 2013 January 01 05
6 2013-01-08 2013 January 02 08
7 2013-01-08 2013 January 02 08
8 2013-01-05 2013 January 01 05
9 2013-01-03 2013 January 01 03
10 2013-01-08 2013 January 02 08
11 2013-01-07 2013 January 02 07
12 2013-01-03 2013 January 01 03
13 2013-01-03 2013 January 01 03
14 2013-01-08 2013 January 52 31
15 2013-01-07 2013 January 02 07
16 2013-01-03 2013 January 52 31
Note that because your values for week
can begin with 0, they are characters and not integers. That's why you need '52'
instead of the numeric value 52.
请注意,因为Week的值可以从0开始,所以它们是字符而不是整数。这就是为什么您需要‘52’而不是数值52的原因。
Avoid using ifelse
in this context, as it degrades performance significantly. You can instead subset with brackets and replace with operator <-
, either directly
避免在此上下文中使用ifElse,因为它会显著降低性能。您可以用方括号替换子集,并用运算符<-替换,或者直接
a$week[with(a, month == 'January' & day == 31)] <- 52
tail(a, 3)
# SampleDate year month week day
# 14 2013-01-08 2013 January 52 31
# 15 2013-01-07 2013 January 02 07
# 16 2013-01-03 2013 January 52 31
or using within
.
或在内部使用。
within(a, week[month == 'January' & day == 31] <- 52)
# SampleDate year month week day
# ...
# 14 2013-01-08 2013 January 52 31
# 15 2013-01-07 2013 January 02 07
# 16 2013-01-03 2013 January 52 31
Benchmark
set.seed(42)
a_big <- a[sample.int(nrow(a), 1e5, replace=TRUE), ]
microbenchmark::microbenchmark(
`$<-`= {a_big$week[with(a_big, month == 'January' & day == 31)] <- 52; a_big},
`[<-`= {a_big[with(a_big, month == 'January' & day == 31), 'week'] <- 52; a_big},
within= within(a_big, week[month == 'January' & day == 31] <- 52),
replace=transform(a_big, week=replace(week, month == 'January' & day == 31, 52)),
ifelse= transform(a_big, week=ifelse(month == 'January' & day == 31, 52, week)),
check='equivalent'
)
# Unit: milliseconds
# expr min lq mean median uq max neval cld
# $<- 3.001781 3.081027 3.365160 3.145184 3.226759 8.168592 100 a
# [<- 16.257779 16.576023 17.014410 16.722306 16.929968 22.539319 100 b
# within 3.241322 3.349472 3.644337 3.408018 3.492567 9.169648 100 a
# replace 19.235649 19.529915 20.830925 19.795184 20.622298 53.269445 100 c
# ifelse 91.503930 92.620180 95.014174 93.657719 97.400140 105.806779 100 d
Data:
数据:
a <- structure(list(SampleDate = structure(c(15710, 15713, 15713,
15710, 15710, 15713, 15713, 15710, 15708, 15713, 15712, 15708,
15708, 15713, 15712, 15708), class = "Date"), year = c("2013",
"2013", "2013", "2013", "2013", "2013", "2013", "2013", "2013",
"2013", "2013", "2013", "2013", "2013", "2013", "2013"), month = c("January",
"January", "January", "January", "January", "January", "January",
"January", "January", "January", "January", "January", "January",
"January", "January", "January"), week = c("01", "02", "02",
"01", "01", "02", "02", "01", "01", "02", "02", "01", "01", "02",
"02", "01"), day = c("05", "08", "08", "05", "05", "08", "08",
"05", "03", "08", "07", "03", "03", "31", "07", "31")), row.names = c(NA,
-16L), class = "data.frame")
Another option if you want to stay in base R:
如果你想留在R基地,另一个选择是:
transform(a, week = ifelse(month == 'January' & day == 31, '52', week))
#> SampleDate year month week day
#> 1 2013-01-05 2013 January 01 05
#> 2 2013-01-08 2013 January 02 08
#> 3 2013-01-08 2013 January 02 08
#> 4 2013-01-05 2013 January 01 05
#> 5 2013-01-05 2013 January 01 05
#> 6 2013-01-08 2013 January 02 08
#> 7 2013-01-08 2013 January 02 08
#> 8 2013-01-05 2013 January 01 05
#> 9 2013-01-03 2013 January 01 03
#> 10 2013-01-08 2013 January 02 08
#> 11 2013-01-07 2013 January 02 07
#> 12 2013-01-03 2013 January 01 03
#> 13 2013-01-03 2013 January 01 03
#> 14 2013-01-08 2013 January 52 31
#> 15 2013-01-07 2013 January 02 07
#> 16 2013-01-03 2013 January 52 31
更多回答
我是一名优秀的程序员,十分优秀!