1

更新(下面的初始问题)

感谢@akrun@ulfelder ,我意识到我最初的例子还不够复杂,因为我只有一年的时间。涵盖几年的数据可能更现实,对其他人更有用。

说我的数据是,

df <- structure(list(yr_month = structure(1:7, .Label = c("2014-1", "2014-2", 
"2014-3", "2015-4", "2016-4", "2016-6", "2017-7"), class = "factor"), 
    a = c(4.14, 2.83, 3.71, 4.15, 4.63, 4.91, 5.31), b = c(4.25, 
    3.5, 3.5, 3.5, 3.5, 3.5, 5)), .Names = c("yrQ", "a", "b"
), row.names = c(NA, 7L), class = "data.frame")
df
#      yrQ    a    b
# 1 2014-1 4.14 4.25
# 2 2014-2 2.83 3.50
# 3 2014-3 3.71 3.50
# 4 2015-4 4.15 3.50
# 5 2016-4 4.63 3.50
# 6 2016-6 4.91 3.50
# 7 2017-7 5.31 5.00

我想在 2014 年 3 月之前、2014 年 3 月之前、2014 年 3 月和 2016 年 4 月之间以及 2016 年 4 月之后创建一个类别。所以我得到了这样的东西,

#   yr.cat    yrQ    a    b
# 1    "A" 2014-1 4.14 4.25
# 2    "A" 2014-2 2.83 3.50
# 3    "B" 2014-3 3.71 3.50
# 4    "B" 2015-4 4.15 3.50
# 5    "B" 2016-4 4.63 3.50
# 6    "C" 2016-6 4.91 3.50
# 7    "C" 2017-7 5.31 5.00

最初的问题

假设我有一个这样的数据集,

df <- structure(list(yr_month = structure(1:7, .Label = c("2016-1", "2016-2", 
"2016-3", "2016-4", "2016-5", "2016-6", "2016-7"), class = "factor"), 
    a = c(4.14, 2.83, 3.71, 4.15, 4.63, 4.91, 5.31), b = c(4.25, 
    3.5, 3.5, 3.5, 3.5, 3.5, 5)), .Names = c("yrQ", "a", "b"
), row.names = c(NA, 7L), class = "data.frame")
df
#      yrQ    a    b
# 1 2016-1 4.14 4.25
# 2 2016-2 2.83 3.50
# 3 2016-3 3.71 3.50
# 4 2016-4 4.15 3.50
# 5 2016-5 4.63 3.50
# 6 2016-6 4.91 3.50
# 7 2016-7 5.31 5.00

现在,我可以用来对数值变量ifelse()进行分类。a像这样,

df$a.cat <- ifelse(df$a < 3.8, c("tiny"), ifelse(df$a < 4.8, c("medium"), c("huge")) )
df
#      yrQ    a    b  a.cat
# 1 2016-1 4.14 4.25 medium
# 2 2016-2 2.83 3.50   tiny
# 3 2016-3 3.71 3.50   tiny
# 4 2016-4 4.15 3.50 medium
# 5 2016-5 4.63 3.50 medium
# 6 2016-6 4.91 3.50   huge
# 7 2016-7 5.31 5.00   huge

但是,如果我想创建一个表示某些时间段的变量怎么办。说在 2016 年 3 月之前, ,和2016-3之间, 和 之后。我意识到我可以将数据转换为然后用于将其剪切然后将其重新组合在一起,但是没有更聪明的方法可以使用 if else on 来获得类似的东西吗?2016-32016-52016-5tswindow()yrQ

我想要达到的就是这样的事情,

  yr.cat    yrQ    a    b
1    "A" 2016-1 4.14 4.25
2    "A" 2016-2 2.83 3.50
3    "B" 2016-3 3.71 3.50
4    "B" 2016-4 4.15 3.50
5    "B" 2016-5 4.63 3.50
6    "C" 2016-6 4.91 3.50
7    "C" 2016-7 5.31 5.00
4

2 回答 2

1

我们可以cut在从 'yrQ' 中提取月份子字符串后使用

df$yr.cat <- cut(as.numeric(sub(".*-", "", df$yrQ)), 
               breaks = c(-Inf,2, 5, Inf), labels = LETTERS[1:3])
df$yr.cat
#[1] A A B B B C C
#Levels: A B C

基于更新的示例

cut(as.numeric(sub("-", ".", df$yrQ)),
       breaks = c(-Inf, 2014.2, 2016.5, Inf), labels = LETTERS[1:3])
#[1] A A B B B C C
#Levels: A B C
于 2016-12-03T10:26:51.110 回答
1

问题中提供的输入数据似乎不一致,指的是同一列yrQyr_month数据结构中的不同点。我们假设这个输入是相同的,除了我们将yrQin .Names(暗示年/季度而不是年/月)替换yr_month为与 中显示的相同名称保持一致list()

df <- structure(list(yr_month = structure(1:7, .Label = c("2014-1", "2014-2", 
"2014-3", "2015-4", "2016-4", "2016-6", "2017-7"), class = "factor"), 
    a = c(4.14, 2.83, 3.71, 4.15, 4.63, 4.91, 5.31), b = c(4.25, 
    3.5, 3.5, 3.5, 3.5, 3.5, 5)), .Names = c("yr_month", "a", "b"
), row.names = c(NA, 7L), class = "data.frame")

问题中的示例数据只有一位数字的月份,但我们假设它需要工作,即使混合有 1 位数字(1 月、2 月、...、9 月)和 2 位数字(10 月、11 月、12 月)月份。

1)转换为"yearmon"类(如果我们需要对这一列做其他事情,这也可能会有所帮助)并对每个切割点进行比较,并将它们相加,分别给出代表之前、之间和之后的数字 0、1 或 2。然后添加 1 并将其用作类别名称向量的下标(此处LETTERS)。只需添加更多比较项,就可以将其扩展到更多类别。

library(zoo)

df$yr_month <- as.yearmon(df$yr_month) ##
transform(df, yr.cat = LETTERS[ (yr_month >= "2014-03") + (yr_month > "2016-04") + 1])

给予:

  yr_month    a    b yr.cat
1 Jan 2014 4.14 4.25      A
2 Feb 2014 2.83 3.50      A
3 Mar 2014 3.71 3.50      B
4 Apr 2015 4.15 3.50      B
5 Apr 2016 4.63 3.50      B
6 Jun 2016 4.91 3.50      C
7 Jul 2017 5.31 5.00      C

2) 要在没有任何包的情况下执行此操作,请将 (1) 中标记为 ## 的行更改为下面的代码行。在这里,我们转换yr_month"Date"类,然后删除其字符表示的日部分。这会为月份留下 2 位数,以便 1 和 2 位数月份之间的比较正常工作。(在 (1)"yearmon"类中自动处理。)

df$yr_month <- sub("...$", "", as.Date(paste0(df$yr_month, -1)))

已修订进行了多次修订。

于 2016-12-03T12:58:15.177 回答