从不同列开始替换数据框中的 NA 值
Replace NA values in dataframe starting in varying columns
这是我无法找到答案的 NA 主题的变体。我每月按列进行观察,并按行进行大量系列。有些缺失值是真实的,但有些应该为零。我想用零替换给定系列的缺失值,但只有在观察到该系列的值之后。
例如,给定:
Mth1 Mth2 Mth3 Mth4
1 1 2 1 3
2 NA 3 2 1
3 NA 2 1 NA
4 NA NA 2 NA
5 2 2 NA 2
我想将其更改为:
Mth1 Mth2 Mth3 Mth4
1 1 2 1 3
2 NA 3 2 1
3 NA 2 1 0
4 NA NA 2 0
5 2 2 0 2
我想要类似 locf
函数的东西,它能够在第一次正观察之前留下缺失值,但我想用零填充而不是使用最后一次观察。
我们可以将 apply
与 MARGIN = 1
一起使用,找到第一个非 NA 元素的位置,获取从该元素到最后一个元素的序列,对行和 replace
进行子集化NA 元素为 0.
df1[] <- t(apply(df1, 1, function(x) {
i1 <- which(!is.na(x))[1]:length(x)
x[i1] <- replace(x[i1], is.na(x[i1]), 0)
x}))
df1
# Mth1 Mth2 Mth3 Mth4
#1 1 2 1 3
#2 NA 3 2 1
#3 NA 2 1 0
#4 NA NA 2 0
#5 2 2 0 2
另一个选项是基于正则表达式的。我们 paste
将行放在一起,将数字和 space 后面的 NA 元素替换为 0 并用 read.table
读取它
read.table(text=gsub("(?<=[0-9])\s+NA", " 0",
do.call(paste, df1), perl = TRUE), header=FALSE, col.names = names(df1))
# Mth1 Mth2 Mth3 Mth4
#1 1 2 1 3
#2 NA 3 2 1
#3 NA 2 1 0
#4 NA NA 2 0
#5 2 2 0 2
数据
df1 <- structure(list(Mth1 = c(1L, NA, NA, NA, 2L), Mth2 = c(2L, 3L,
2L, NA, 2L), Mth3 = c(1L, 2L, 1L, 2L, NA), Mth4 = c(3L, 1L, NA,
NA, 2L)), .Names = c("Mth1", "Mth2", "Mth3", "Mth4"), class = "data.frame",
row.names = c("1", "2", "3", "4", "5"))
这是另一种使用矩阵索引的基本 R 方法:
df[is.na(df) & t(apply(!is.na(df), 1, cummax))] <- 0
df
Mth1 Mth2 Mth3 Mth4
1 1 2 1 3
2 NA 3 2 1
3 NA 2 1 0
4 NA NA 2 0
5 2 2 0 2
is.na(df)
returns 指示 NA 值位置的逻辑矩阵。这(逻辑上)链接到 t(apply(!is.na(df), 1, cummax))
,它指示前一个行元素中是否出现非 NA 值。 data.frame 中两者都为 TRUE 的元素将替换为 0.
这是我无法找到答案的 NA 主题的变体。我每月按列进行观察,并按行进行大量系列。有些缺失值是真实的,但有些应该为零。我想用零替换给定系列的缺失值,但只有在观察到该系列的值之后。
例如,给定:
Mth1 Mth2 Mth3 Mth4
1 1 2 1 3
2 NA 3 2 1
3 NA 2 1 NA
4 NA NA 2 NA
5 2 2 NA 2
我想将其更改为:
Mth1 Mth2 Mth3 Mth4
1 1 2 1 3
2 NA 3 2 1
3 NA 2 1 0
4 NA NA 2 0
5 2 2 0 2
我想要类似 locf
函数的东西,它能够在第一次正观察之前留下缺失值,但我想用零填充而不是使用最后一次观察。
我们可以将 apply
与 MARGIN = 1
一起使用,找到第一个非 NA 元素的位置,获取从该元素到最后一个元素的序列,对行和 replace
进行子集化NA 元素为 0.
df1[] <- t(apply(df1, 1, function(x) {
i1 <- which(!is.na(x))[1]:length(x)
x[i1] <- replace(x[i1], is.na(x[i1]), 0)
x}))
df1
# Mth1 Mth2 Mth3 Mth4
#1 1 2 1 3
#2 NA 3 2 1
#3 NA 2 1 0
#4 NA NA 2 0
#5 2 2 0 2
另一个选项是基于正则表达式的。我们 paste
将行放在一起,将数字和 space 后面的 NA 元素替换为 0 并用 read.table
read.table(text=gsub("(?<=[0-9])\s+NA", " 0",
do.call(paste, df1), perl = TRUE), header=FALSE, col.names = names(df1))
# Mth1 Mth2 Mth3 Mth4
#1 1 2 1 3
#2 NA 3 2 1
#3 NA 2 1 0
#4 NA NA 2 0
#5 2 2 0 2
数据
df1 <- structure(list(Mth1 = c(1L, NA, NA, NA, 2L), Mth2 = c(2L, 3L,
2L, NA, 2L), Mth3 = c(1L, 2L, 1L, 2L, NA), Mth4 = c(3L, 1L, NA,
NA, 2L)), .Names = c("Mth1", "Mth2", "Mth3", "Mth4"), class = "data.frame",
row.names = c("1", "2", "3", "4", "5"))
这是另一种使用矩阵索引的基本 R 方法:
df[is.na(df) & t(apply(!is.na(df), 1, cummax))] <- 0
df
Mth1 Mth2 Mth3 Mth4
1 1 2 1 3
2 NA 3 2 1
3 NA 2 1 0
4 NA NA 2 0
5 2 2 0 2
is.na(df)
returns 指示 NA 值位置的逻辑矩阵。这(逻辑上)链接到 t(apply(!is.na(df), 1, cummax))
,它指示前一个行元素中是否出现非 NA 值。 data.frame 中两者都为 TRUE 的元素将替换为 0.