首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在R中处理丢失的数据

在R中处理丢失的数据
EN

Stack Overflow用户
提问于 2020-08-31 15:44:10
回答 3查看 62关注 0票数 0

我在我目前正在做的一个项目中遇到了这个问题。

我有一个稀疏的数据,在某些条件下,我需要计算每一行第一次和最后一次观察之间的差异:

条件:

如果该行只包含NA,则差异为0。如果该行仅包含1个观测值,则差异为0。如果行元素( 2)为非NA,则差异为

  1. ,则它们的差异为第一行和最后一行(尾头)之间的差异。

我拥有的数据:

代码语言:javascript
复制
  S1 S2 S3 S4 S5
1 NA NA NA NA NA
2 NA 3  NA 5  NA
3 1  NA NA NA 5
4 1  NA 2  NA 7
5 2  NA NA NA NA
6 NA NA 3  4  NA
7 NA NA 3 NA  NA

我需要的数据:

代码语言:javascript
复制
  S1 S2 S3 S4 S5 diff
1 NA NA NA NA NA 0
2 NA 3  NA 5  NA 2
3 1  NA NA NA 5  4
4 1  NA 2  NA 7  6
5 2  NA NA NA NA 0
6 NA NA 3  4  NA 1
7 NA NA 3 NA  NA 0

我到现在为止写的是:

代码语言:javascript
复制
 last_minus_first <- function(x, y = na.omit(x)) tail(y, 1) - y[1]

但是如果行包含所有NA的话,它并不能解决这个问题。

任何帮助都将不胜感激。

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2020-08-31 16:21:06

我建议在apply()中使用已定义的函数。在这里,代码:

代码语言:javascript
复制
#Data
df <- structure(list(S1 = c(NA, NA, 1L, 1L, 2L, NA, NA), S2 = c(NA, 
3L, NA, NA, NA, NA, NA), S3 = c(NA, NA, NA, 2L, NA, 3L, 3L), 
    S4 = c(NA, 5L, NA, NA, NA, 4L, NA), S5 = c(NA, NA, 5L, 7L, 
    NA, NA, NA)), class = "data.frame", row.names = c("1", "2", 
"3", "4", "5", "6", "7"))

代码:

代码语言:javascript
复制
#Function
myown <- function(x)
{
  #Check NA
  i <- sum(!is.na(x))
  #Compute
  if(i<=1)
  {
    y <- 0
  } else
  {
    #Detect positions
    j1 <- max(which(!is.na(x)))
    j2 <- min(which(!is.na(x)))
    #Diff
    y <- x[j1]-x[j2]
  }
  return(y)
}
#Apply function by row
df$NewVar <- apply(df,1,myown)

输出:

代码语言:javascript
复制
  S1 S2 S3 S4 S5 NewVar
1 NA NA NA NA NA      0
2 NA  3 NA  5 NA      2
3  1 NA NA NA  5      4
4  1 NA  2 NA  7      6
5  2 NA NA NA NA      0
6 NA NA  3  4 NA      1
7 NA NA  3 NA NA      0
票数 1
EN

Stack Overflow用户

发布于 2020-08-31 18:02:56

这里有一种(在我看来)更容易处理这一问题的方法,使用来自rowwise包的dplyr按行进行计算。

代码语言:javascript
复制
df %>% 
  dplyr::rowwise() %>% 
  dplyr::mutate(max_pop = max(which(!is.na(dplyr::c_across(S1:S5)))),
                min_pop = min(which(!is.na(dplyr::c_across(S1:S5)))),
                diff = tidyr::replace_na(dplyr::c_across()[max_pop] - dplyr::c_across()[min_pop], 0))

我已经将这个mutate调用分解到各个部分,以显示我们正在做什么,但本质上,它会遍历一行中的所有列,找到最后一个填充的列(max_pop),第一个填充的列(min_pop),然后使用这些值检索其中的值。

您必须为上面的max_popmin_pop指定列,因为创建新的临时列会影响列的索引。但是,c_across()默认使用所有列,因此实际上可以在一个mutate调用中完成这一切,而无需指定任何列。

代码语言:javascript
复制
df %>% 
  rowwise() %>% 
  mutate(diff = replace_na(c_across()[max(which(!is.na(c_across())))] - c_across()[min(which(!is.na(c_across())))], 0))
票数 1
EN

Stack Overflow用户

发布于 2020-08-31 22:34:59

base R中的一个向量化选项是根据行/列索引提取值,然后减去

代码语言:javascript
复制
df1$NewVar <- df1[cbind(seq_len(nrow(df1)), max.col(!is.na(df1), 'last'))] - 
            df1[cbind(seq_len(nrow(df1)), max.col(!is.na(df1), 'first'))]
df1$NewVar[is.na(df1$NewVar)] <- 0

df1
#  S1 S2 S3 S4 S5 NewVar
#1 NA NA NA NA NA      0
#2 NA  3 NA  5 NA      2
#3  1 NA NA NA  5      4
#4  1 NA  2 NA  7      6
#5  2 NA NA NA NA      0
#6 NA NA  3  4 NA      1
#7 NA NA  3 NA NA      0

数据

代码语言:javascript
复制
df1 <- structure(list(S1 = c(NA, NA, 1L, 1L, 2L, NA, NA), S2 = c(NA, 
3L, NA, NA, NA, NA, NA), S3 = c(NA, NA, NA, 2L, NA, 3L, 3L), 
    S4 = c(NA, 5L, NA, NA, NA, 4L, NA), S5 = c(NA, NA, 5L, 7L, 
    NA, NA, NA)), class = "data.frame", row.names = c("1", "2", 
"3", "4", "5", "6", "7"))
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/63673961

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档