【问题标题】:Create New Categorical Variable (high, mid, low)创建新的分类变量(高、中、低)
【发布时间】:2021-02-14 06:45:37
【问题描述】:

我有这个数据框,我想创建一个新的分类变量“life.cat”,用于表示每个国家每年的“高”(> = 高于平均值 1 个标准差); “低”(

structure(list(country = c("Afghanistan", "Afghanistan", "Afghanistan", 
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", 
"Afghanistan", "Afghanistan", "Afghanistan", "Afghanistan", "Albania", 
"Albania", "Albania", "Albania", "Albania", "Albania", "Albania", 
"Albania", "Albania", "Albania", "Albania", "Albania", "Algeria", 
"Algeria", "Algeria", "Algeria", "Algeria", "Algeria"), continent = c("Asia", 
"Asia", "Asia", "Asia", "Asia", "Asia", "Asia", "Asia", "Asia", 
"Asia", "Asia", "Asia", "Europe", "Europe", "Europe", "Europe", 
"Europe", "Europe", "Europe", "Europe", "Europe", "Europe", "Europe", 
"Europe", "Africa", "Africa", "Africa", "Africa", "Africa", "Africa"
), year = c(1952L, 1957L, 1962L, 1967L, 1972L, 1977L, 1982L, 
1987L, 1992L, 1997L, 2002L, 2007L, 1952L, 1957L, 1962L, 1967L, 
1972L, 1977L, 1982L, 1987L, 1992L, 1997L, 2002L, 2007L, 1952L, 
1957L, 1962L, 1967L, 1972L, 1977L), lifeExp = c(28.801, 30.332, 
31.997, 34.02, 36.088, 38.438, 39.854, 40.822, 41.674, 41.763, 
42.129, 43.828, 55.23, 59.28, 64.82, 66.22, 67.69, 68.93, 70.42, 
72, 71.581, 72.95, 75.651, 76.423, 43.077, 45.685, 48.303, 51.407, 
54.518, 58.014), pop = c(8425333L, 9240934L, 10267083L, 11537966L, 
13079460L, 14880372L, 12881816L, 13867957L, 16317921L, 22227415L, 
25268405L, 31889923L, 1282697L, 1476505L, 1728137L, 1984060L, 
2263554L, 2509048L, 2780097L, 3075321L, 3326498L, 3428038L, 3508512L, 
3600523L, 9279525L, 10270856L, 11000948L, 12760499L, 14760787L, 
17152804L), gdpPercap = c(779.4453145, 820.8530296, 853.10071, 
836.1971382, 739.9811058, 786.11336, 978.0114388, 852.3959448, 
649.3413952, 635.341351, 726.7340548, 974.5803384, 1601.056136, 
1942.284244, 2312.888958, 2760.196931, 3313.422188, 3533.00391, 
3630.880722, 3738.932735, 2497.437901, 3193.054604, 4604.211737, 
5937.029526, 2449.008185, 3013.976023, 2550.81688, 3246.991771, 
4182.663766, 4910.416756)), row.names = c(NA, 30L), class = "data.frame")

到目前为止,我已经尝试过这段代码:

library(dplyr)
df1 %>%
    group_by(continent, year) %>% 
    mutate(Mean = mean(lifeExp), 
           SD = sd(lifeExp),
           life.cat = case_when(Mean > (Mean + SD) ~ 'High',     
                                Mean < (Mean - SD) ~ 'Low', 
          TRUE ~ 'Mid'  ), Mean = NULL, SD = NULL) %>%
    ungroup

但是新列的输出都是“mid”,这是不可能的。谁能告诉我出了什么问题?

【问题讨论】:

标签: r dataframe categorical-data


【解决方案1】:

由于阿富汗、阿尔巴尼亚和阿尔及利亚位于不同的大陆,因此您在此处共享的数据子集中每个大陆年份只有一个值。 SD 会在该示例数据上生成一个 NA,因为每个组只有一个元素。如果每个组中有多个元素,它应该可以正常工作。 SD 中的 NA 表示 case_when 的前两项为假(在 R 中,没有数字大于或小于 NA),因此都是“中”。

如果您无法提前知道每个组中会有多个元素,您可以将sd(lifeExp) 更改为coalesce(sd(lifeExp, 0),以便 SD 的任何 NA 都变为零。

您可能还想更改此处的代码,以便将当前行的lifeExp 与其组的Mean+SD 进行比较。比较Mean &gt; Mean + SD 总是假的,Mean &lt; Mean - SD 也总是假的。

【讨论】:

    【解决方案2】:

    您可以使用within 和ave 并使用括号进行简单的大小写处理。 (你的数据不适合演示,我已经新建了。)

    e <- within(e, {
        le.mn <- ave(lifeExp, continent, year, FUN=mean)
        le.sd <- ave(lifeExp, continent, FUN=sd)
        life.cat <- NA
        life.cat[lifeExp < le.mn - le.sd] <- "lo"
        life.cat[lifeExp >= le.mn - le.sd] <- "mid"
        life.cat[lifeExp > le.mn + le.sd] <- "hi"
        rm(le.mn, le.sd)
    })
    e
    #    country year continent  lifeExp life.cat
    # 1        a 2015         A 29.14806      mid
    # 2        a 2016         A 29.37075       hi
    # 3        a 2017         A 22.86140      mid
    # 4        a 2018         A 28.30448      mid
    # 5        a 2019         A 26.41746      mid
    # 6        a 2020         A 25.19096      mid
    # 7        b 2015         A 27.36588      mid
    # 8        b 2016         A 21.34667       lo
    # 9        b 2017         A 26.56992      mid
    # 10       b 2018         A 27.05065      mid
    # 11       b 2019         A 24.57742      mid
    # 12       b 2020         A 27.19112      mid
    # 13       c 2015         B 29.34672      mid
    # 14       c 2016         B 22.55429      mid
    # 15       c 2017         B 24.62293      mid
    # 16       c 2018         B 29.40015       hi
    # 17       c 2019         B 29.78226      mid
    # 18       c 2020         B 21.17487       lo
    # 19       d 2015         B 24.74997      mid
    # 20       d 2016         B 25.60333      mid
    # 21       d 2017         B 29.04031      mid
    # 22       d 2018         B 21.38710       lo
    # 23       d 2019         B 29.88892      mid
    # 24       d 2020         B 29.46668       hi
    

    数据:

    e <- structure(list(country = structure(c(1L, 1L, 1L, 1L, 1L, 1L,
    2L, 2L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 3L, 3L, 4L, 4L, 4L, 4L,
    4L, 4L), .Label = c("a", "b", "c", "d"), class = "factor"), year = c(2015L,
    2016L, 2017L, 2018L, 2019L, 2020L, 2015L, 2016L, 2017L, 2018L,
    2019L, 2020L, 2015L, 2016L, 2017L, 2018L, 2019L, 2020L, 2015L,
    2016L, 2017L, 2018L, 2019L, 2020L), continent = c("A", "A", "A",
    "A", "A", "A", "A", "A", "A", "A", "A", "A", "B", "B", "B", "B",
    "B", "B", "B", "B", "B", "B", "B", "B"), lifeExp = c(29.1480604349636,
    29.3707541329786, 22.8613953478634, 28.3044762606733, 26.41745518893,
    25.1909594913013, 27.3658831464127, 21.3466659723781, 26.5699229040183,
    27.0506478403695, 24.5774177624844, 27.191122516524, 29.3467224715278,
    22.5542882434092, 24.6229282254353, 29.4001452275552, 29.7822642838582,
    21.1748736165464, 24.7499708156101, 25.6033274624497, 29.0403138729744,
    21.3871016772464, 29.8889172892086, 29.466682325583)), out.attrs = list(
        dim = c(country = 4L, year = 6L), dimnames = list(country = c("country=a",
        "country=b", "country=c", "country=d"), year = c("year=2015",
        "year=2016", "year=2017", "year=2018", "year=2019", "year=2020"
        ))), row.names = c(NA, -24L), class = "data.frame")
    

    【讨论】:

      猜你喜欢
      • 2011-03-24
      • 2021-05-18
      • 1970-01-01
      • 2019-06-28
      • 1970-01-01
      • 2021-12-13
      • 2018-05-22
      • 1970-01-01
      • 2014-12-25
      相关资源
      最近更新 更多