如何找到连续的第一个非 NA 值?
How do I find the 1st non-NA value in a row?
假设我有以下内容:
df <- data.frame(dt=c(as.Date('2019-02-02'), as.Date('2019-02-04'), as.Date('2019-02-05'), as.Date('2020-03-04')), v1=c(1,2,NA,NA), v2=c(NA,3,4,NA), v3=c(NA,NA,3,5), v4=c(2, 4, 6, NA))
> read.zoo(df)
v1 v2 v3 v4
2019-02-02 1 NA NA 2
2019-02-04 2 3 NA 4
2019-02-05 NA 4 3 6
2020-03-04 NA NA 5 NA
我想在具有值的列之后的每一行中找到第一个非 NA 值。
例如,对于“2019-02-02”:
v1
中有一个值为 1,v2 有 NA 所以我们跳过,v3
有 NA 所以我们跳过但是 v4
不是 NA 所以我想 return 它的值,第 1 行第 1 列为 2。
- 查看下一列
v2
,在同一行中它是 NA 所以我们跳过它,因为它不是数字
v3
也是 NA 所以我们跳过它。
v4
不是 NA 但后面没有列所以我们 return NA。
因此我们的第一行将是:
c1 c2 c3 c4
2 NA NA NA
遍历此示例中的所有行,我希望输出为:
c1 c2 c3 c4
1 2019-02-02 2 NA NA NA
2 2019-02-04 3 4 NA NA
3 2019-02-05 NA 3 6 NA
4 2020-03-04 NA NA NA NA
看起来我需要做的就是将每行中的列值向左移动,但我似乎不知道该怎么做...
NOTE: I would prefer a base-R solution using zoo
这是应用自定义函数的解决方案:
res = t(apply(df[-1], 1, function(x) {
val = which(!is.na(x))
x[val[-length(val)]] = x[val[-1]]
x[val[length(val)]] = NA
return(x)
}
))
cbind(df[1], res)
# dt v1 v2 v3 v4
# 1 2019-02-02 2 NA NA NA
# 2 2019-02-04 3 4 NA NA
# 3 2019-02-05 NA 3 6 NA
# 4 2020-03-04 NA NA NA NA
我不确定如何使用 base
R 来完成。但是在 tidyverse
:
df %>%
gather(key, value, -dt) %>%
arrange(dt, key) %>%
mutate(key2 = as.numeric(substr(key, 2, 2))) %>%
filter(!is.na(value)) %>% group_by(dt) %>%
mutate(ind = lag(key2, default = NA), index = paste0("c", ind)) %>%
ungroup() %>%
filter(!is.na(ind)) %>%
select(dt, index, value) %>%
spread(index, value)
假设我有以下内容:
df <- data.frame(dt=c(as.Date('2019-02-02'), as.Date('2019-02-04'), as.Date('2019-02-05'), as.Date('2020-03-04')), v1=c(1,2,NA,NA), v2=c(NA,3,4,NA), v3=c(NA,NA,3,5), v4=c(2, 4, 6, NA))
> read.zoo(df)
v1 v2 v3 v4
2019-02-02 1 NA NA 2
2019-02-04 2 3 NA 4
2019-02-05 NA 4 3 6
2020-03-04 NA NA 5 NA
我想在具有值的列之后的每一行中找到第一个非 NA 值。
例如,对于“2019-02-02”:
v1
中有一个值为 1,v2 有 NA 所以我们跳过,v3
有 NA 所以我们跳过但是v4
不是 NA 所以我想 return 它的值,第 1 行第 1 列为 2。- 查看下一列
v2
,在同一行中它是 NA 所以我们跳过它,因为它不是数字 v3
也是 NA 所以我们跳过它。v4
不是 NA 但后面没有列所以我们 return NA。
因此我们的第一行将是:
c1 c2 c3 c4
2 NA NA NA
遍历此示例中的所有行,我希望输出为:
c1 c2 c3 c4
1 2019-02-02 2 NA NA NA
2 2019-02-04 3 4 NA NA
3 2019-02-05 NA 3 6 NA
4 2020-03-04 NA NA NA NA
看起来我需要做的就是将每行中的列值向左移动,但我似乎不知道该怎么做...
NOTE: I would prefer a base-R solution using zoo
这是应用自定义函数的解决方案:
res = t(apply(df[-1], 1, function(x) {
val = which(!is.na(x))
x[val[-length(val)]] = x[val[-1]]
x[val[length(val)]] = NA
return(x)
}
))
cbind(df[1], res)
# dt v1 v2 v3 v4
# 1 2019-02-02 2 NA NA NA
# 2 2019-02-04 3 4 NA NA
# 3 2019-02-05 NA 3 6 NA
# 4 2020-03-04 NA NA NA NA
我不确定如何使用 base
R 来完成。但是在 tidyverse
:
df %>%
gather(key, value, -dt) %>%
arrange(dt, key) %>%
mutate(key2 = as.numeric(substr(key, 2, 2))) %>%
filter(!is.na(value)) %>% group_by(dt) %>%
mutate(ind = lag(key2, default = NA), index = paste0("c", ind)) %>%
ungroup() %>%
filter(!is.na(ind)) %>%
select(dt, index, value) %>%
spread(index, value)