R-使用分组数据中的因子级别重新编码NA

R-使用分组数据中的因子级别重新编码NA,r,na,recode,R,Na,Recode,我有一个纵向结构的数据框,如下所示: df = structure(list(oslaua = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L), .Label = c("E06000001", "E06000002", "E06000003", "E06000004"), class = "factor"), wave = structure(c(1L, 2L, 3L, 4L, 1L, 2

我有一个纵向结构的数据框,如下所示:

df = structure(list(oslaua = structure(c(1L, 1L, 1L, 1L, 2L, 2L, 2L, 
 2L, 3L, 3L, 3L, 3L, 4L, 4L, 4L), .Label = c("E06000001", "E06000002", 
 "E06000003", "E06000004"), class = "factor"), wave = structure(c(1L, 
 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L, 4L, 1L, 2L, 3L), .Label = c("0", 
 "1", "2", "3"), class = "factor"), old.la = structure(c(1L, 1L, 
 NA, 1L, 2L, 2L, 2L, NA, 3L, 3L, 3L, 3L, 4L, 4L, NA), .Label = c("00EB", 
 "00EC", "00EE", "00EF"), class = "factor"), la = structure(c(1L, 
 1L, NA, 1L, 2L, 2L, 2L, NA, 3L, 3L, 3L, 3L, 4L, 4L, NA), .Label = c("Hartlepool UA", 
 "Middlesbrough UA", "Redcar and Cleveland UA", "Stockton-on-Tees UA"
 ), class = "factor"), dclg.code = structure(c(1L, 1L, NA, 1L, 
 4L, 4L, 4L, NA, 3L, 3L, 3L, 3L, 2L, 2L, NA), .Label = c("H0724", 
 "H0738", "V0728", "W0734"), class = "factor"), novo_entries = c(24L, 
 4L, 0L, 1L, 35L, 15L, 1L, 0L, 49L, 7L, 2L, 2L, 40L, 14L, 0L)), .Names = c("oslaua", 
 "wave", "old.la", "la", "dclg.code", "novo_entries"), row.names = c(NA, 
 15L), class = "data.frame")
我的标识符变量是oslaua,时间变量是wave。old.la、la和dclg.code是具有NA的因子变量。我的 目标包括使用与每个标识符oslaua关联的每个变量的级别对我的NA进行重新编码。我已尝试使用以下方法对old.la进行此操作:

df = df %>% group_by(oslaua) %>% mutate(old.la.1 = ifelse(is.na(old.la), unique(old.la), old.la)) %>% as.data.frame()
我部分实现了我的目标,但正如你所看到的,存在一些问题:

> df
      oslaua wave old.la                      la dclg.code novo_entries old.la.1
1  E06000001    0   00EB           Hartlepool UA     H0724           24        1
2  E06000001    1   00EB           Hartlepool UA     H0724            4        1
3  E06000001    2   <NA>                    <NA>      <NA>            0        2
4  E06000001    3   00EB           Hartlepool UA     H0724            1        1
5  E06000002    0   00EC        Middlesbrough UA     W0734           35        2
6  E06000002    1   00EC        Middlesbrough UA     W0734           15        2
7  E06000002    2   00EC        Middlesbrough UA     W0734            1        2
8  E06000002    3   <NA>                    <NA>      <NA>            0        2
9  E06000003    0   00EE Redcar and Cleveland UA     V0728           49        3
10 E06000003    1   00EE Redcar and Cleveland UA     V0728            7        3
11 E06000003    2   00EE Redcar and Cleveland UA     V0728            2        3
12 E06000003    3   00EE Redcar and Cleveland UA     V0728            2        3
13 E06000004    0   00EF     Stockton-on-Tees UA     H0738           40        4
14 E06000004    1   00EF     Stockton-on-Tees UA     H0738           14        4
15 E06000004    2   <NA>                    <NA>      <NA>            0        4
具体而言,因子的水平改变了其格式,并且在某些情况下,观测值被错误地记录,例如oslaua=E06000001-第3行

我不明白为什么级别会更改其格式,以及如何保持其原始字母数字格式。还有,为什么一些观察结果没有正确记录

任何解决这些问题的建议都非常感谢


谢谢

这应该适合您:

library(zoo)

df %>%
  group_by(oslaua) %>%
  mutate(old.la.1 = na.locf(old.la))

它使用zoo的最后一个结转功能来替换NA。这是类型安全的。在代码中,ifelse正在构造两个向量,一个用于测试解析为TRUE的情况,另一个用于测试解析为FALSE的情况。为了确保兼容性,ifelse似乎将它们都简化为最基本、最常见的类型。对于factors,这是一个整数run typeofdf$old.la

这应该适合您:

library(zoo)

df %>%
  group_by(oslaua) %>%
  mutate(old.la.1 = na.locf(old.la))

它使用zoo的最后一个结转功能来替换NA。这是类型安全的。在代码中,ifelse正在构造两个向量,一个用于测试解析为TRUE的情况,另一个用于测试解析为FALSE的情况。为了确保兼容性,ifelse似乎将它们都简化为最基本、最常见的类型。对于factors,这是一个整数run typeofdf$old.la

这里是另一个使用data.table的选项

对于多列

nm1 <-  c("old.la", "la", "dclg.code")
df1 <-  setDT(df)[, lapply(.SD, function(x) levels(droplevels(x))[1]) , 
       by = oslaua, .SDcols = nm1][df,  on = "oslaua"]
df1[, !grepl("i\\.", names(df1)), with = FALSE]

但由于某些原因,使用v1.10.0将每个组转换为因子会得到一些奇怪的输出,输出中的每列只有一个级别

对于多列

nm1 <-  c("old.la", "la", "dclg.code")
df1 <-  setDT(df)[, lapply(.SD, function(x) levels(droplevels(x))[1]) , 
       by = oslaua, .SDcols = nm1][df,  on = "oslaua"]
df1[, !grepl("i\\.", names(df1)), with = FALSE]

但由于某些原因,使用v1.10.0将每个组内的因子转换为某个奇怪的输出,输出中的每列只有一个级别。或者,避免创建新变量的更优雅的解决方案是使用tidyr填充:

这将产生:

> data
Source: local data frame [15 x 6]
Groups: oslaua [4]

      oslaua   wave old.la                      la dclg.code novo_entries
      <fctr> <fctr> <fctr>                  <fctr>    <fctr>        <int>
1  E06000001      0   00EB           Hartlepool UA     H0724           24
2  E06000001      1   00EB           Hartlepool UA     H0724            4
3  E06000001      2   00EB           Hartlepool UA     H0724            0
4  E06000001      3   00EB           Hartlepool UA     H0724            1
5  E06000002      0   00EC        Middlesbrough UA     W0734           35
6  E06000002      1   00EC        Middlesbrough UA     W0734           15
7  E06000002      2   00EC        Middlesbrough UA     W0734            1
8  E06000002      3   00EC        Middlesbrough UA     W0734            0
9  E06000003      0   00EE Redcar and Cleveland UA     V0728           49
10 E06000003      1   00EE Redcar and Cleveland UA     V0728            7
11 E06000003      2   00EE Redcar and Cleveland UA     V0728            2
12 E06000003      3   00EE Redcar and Cleveland UA     V0728            2
13 E06000004      0   00EF     Stockton-on-Tees UA     H0738           40
14 E06000004      1   00EF     Stockton-on-Tees UA     H0738           14
15 E06000004      2   00EF     Stockton-on-Tees UA     H0738            0

或者,避免创建新变量的更优雅的解决方案是使用tidyr填充:

这将产生:

> data
Source: local data frame [15 x 6]
Groups: oslaua [4]

      oslaua   wave old.la                      la dclg.code novo_entries
      <fctr> <fctr> <fctr>                  <fctr>    <fctr>        <int>
1  E06000001      0   00EB           Hartlepool UA     H0724           24
2  E06000001      1   00EB           Hartlepool UA     H0724            4
3  E06000001      2   00EB           Hartlepool UA     H0724            0
4  E06000001      3   00EB           Hartlepool UA     H0724            1
5  E06000002      0   00EC        Middlesbrough UA     W0734           35
6  E06000002      1   00EC        Middlesbrough UA     W0734           15
7  E06000002      2   00EC        Middlesbrough UA     W0734            1
8  E06000002      3   00EC        Middlesbrough UA     W0734            0
9  E06000003      0   00EE Redcar and Cleveland UA     V0728           49
10 E06000003      1   00EE Redcar and Cleveland UA     V0728            7
11 E06000003      2   00EE Redcar and Cleveland UA     V0728            2
12 E06000003      3   00EE Redcar and Cleveland UA     V0728            2
13 E06000004      0   00EF     Stockton-on-Tees UA     H0738           40
14 E06000004      1   00EF     Stockton-on-Tees UA     H0738           14
15 E06000004      2   00EF     Stockton-on-Tees UA     H0738            0

这仅在NA值永远不是其组的第一个值时有效,否?您是正确的。这可以通过将NA强制到末尾来缓解,但可能不是理想的解决方案。akrun的解决方案也可以在dplyr框架中实现。这可以通过使用na.aggregate而不是na.locf来解决。这只有在na值永远不是其组的第一个时才有效,不是吗?你是正确的。这可以通过将NA强制到末尾来缓解,但可能不是理想的解决方案。akrun的解决方案也可以在dplyr框架中实现。这可以通过使用na.aggregate而不是na.locf来解决。非常感谢@akrun,这正是我所需要的。我仍然不明白为什么在我应用我的解决方案时它改变了因子的格式。@Edu它变为字符,但在df1之后,您可以将列重新转换为因子,即df2。非常感谢@akrun,这正是我需要的。我仍然不明白为什么在我应用我的解决方案时它更改了因子的格式。@Edu它更改为字符,但在df1之后,您可以将列重新转换为因子,即df2