在R中:如果缺少另一行的值,则替换一行的值

Posted

技术标签:

【中文标题】在R中:如果缺少另一行的值,则替换一行的值【英文标题】:In R: Replace values of a row if missing with values of another row 【发布时间】:2014-10-02 13:25:27 【问题描述】:

我对 R 比较陌生,可能这个问题的解决方案相当简单。

我有一个如下所示的数据框:

id1    id2    v1    v2    v3    ...    v100
  A      X     1    NA    NA    ...       1
  B      Y     1     3     4    ...       1
  C      X     1     3     4    ...       1
  D      X     1     3     4    ...       1
  E      Y     1     3     4    ...       1
  A      X    NA     3     4    ...      NA 

我想做的是将具有相同 id(id1 和 id2)的两个观察结果“合并”到一个观察结果。一个观测值的缺失值应替换为另一个观测值。

例如,在上面的数据框中,这些是“观察 1”和“观察 6”,结果应如下所示:

id1    id2    v1    v2    v3    ...    v100
  A      X     1     3     4    ...       1
  B      Y     1     3     4    ...       1
  C      X     1     3     4    ...       1
  D      X     1     3     4    ...       1
  E      Y     1     3     4    ...       1

目前我正在为此使用循环,我知道它非常慢并且可能不是最佳解决方案。我有 1000 多个观测值,其中大约有 100 个重复观测值和几千个变量。如果有人能提供如何加快速度的想法,我会非常高兴。

提前非常感谢!

编辑:2014 年 3 月 10 日

非常感谢所有有用的 cmets! 大卫·阿姆斯特朗的答案正是我想要的!非常感谢!

很抱歉我的第一篇文章不够精确,所以这里有一些规范。

具有相同 ID 的观察可以在数据集中出现多次,而不仅仅是两次。

此外,在所有这些相同的观察中,只有 一个 观察将具有每个变量的非缺失值(如果全部)。也可能是某个变量的所有观测值都缺失的情况,但绝不可能是两个观测值都具有非缺失值的情况。下面的例子可能会让事情更清楚。

id1    id2    v1    v2    v3    v4    v5    v6    v7
  A      X     6     9     3     1     2     1     1
  B      X     2     2     1     4     2     3     3
  C      X     1     6     7     1     3     4     5
  D      X     4     2     9     2     3     6     2
  E      X    NA     3    NA    NA    NA    NA    NA
  E      X    NA    NA     4    NA    NA    NA    NA
  E      X    NA    NA    NA     3    NA    NA    NA
  E      X    NA    NA    NA    NA     6    NA    NA
  E      X    NA    NA    NA    NA    NA     4    NA
  E      X    NA    NA    NA    NA    NA    NA     1

我想要的结果是:

id1    id2    v1    v2    v3    v4    v5    v6    v7
  A      X     6     9     3     1     2     1     1
  B      X     2     2     1     4     2     3     3
  C      X     1     6     7     1     3     4     5
  D      X     4     2     9     2     3     6     2
  E      X    NA     3     4     3     6     4     1

我希望这会有所帮助。

非常感谢!

【问题讨论】:

我们是否可以假设总是有一对具有缺失值的观测值,使得一个观测值的缺失值总是另一个观测值中的值,反之亦然?例如,我们可以做类似x[is.na(x)] <- na.omit(y)的事情吗? @vandm 目前尚不清楚您希望如何summarise 具有相同组且具有非缺失值的行。在您提供的示例中,这些值完全相同,而您的原始数据集中可能并非如此。如果有三重等怎么办? @vandm,你不需要在这里创建一个全新的帐户。只需向您现有的 CrossValidated 帐户添加另一个帐户 【参考方案1】:

也许

library(data.table)
setDT(df)[, lapply(.SD, na.omit), by = list(id1, id2)]
#    id1 id2 v1 v2 v3 v100
# 1:   A   X  1  3  4    1
# 2:   B   Y  1  3  4    1
# 3:   C   X  1  3  4    1
# 4:   D   X  1  3  4    1
# 5:   E   Y  1  3  4    1

如果我们不能总是假设存在缺失值(如 @Rolands 评论中提到的),您可以添加 unique(如果您总是只想要一对)。类似的东西

unique(setDT(df)[, lapply(.SD, na.omit), by = list(id1, id2)])

【讨论】:

感谢@akrun,实际上很难说出他们到底想要什么,所以也添加了unique【参考方案2】:

试试:

library(dplyr) 
df %>%
    group_by(id1, id2) %>%
    summarise_each(funs(mean=mean(., na.rm=TRUE)))

#    id1 id2 v1 v2 v3
# 1   A   X  1  3  4
# 2   B   Y  1  3  4
# 3   C   X  1  3  4
# 4   D   X  1  3  4
# 5   E   Y  1  3  4

或许

df %>% 
    group_by(id1, id2) %>%
    mutate_each(funs(replace(., is.na(.), stats::na.omit(.)))) %>%
    unique()

数据

df <- structure(list(id1 = c("A", "B", "C", "D", "E", "A"), id2 = c("X", 
"Y", "X", "X", "Y", "X"), v1 = c(1L, 1L, 1L, 1L, 1L, NA), v2 = c(NA, 
3L, 3L, 3L, 3L, 3L), v3 = c(NA, 4L, 4L, 4L, 4L, 4L)), .Names = c("id1", 
"id2", "v1", "v2", "v3"), class = "data.frame", row.names = c(NA, 
-6L))

【讨论】:

【参考方案3】:

如果 ddf 是您的数据框:

> t(sapply(split(ddf, paste(ddf$id1, ddf$id2)), 
           function(x) sapply(x[3:ncol(ddf)], sum, na.rm=T)))
    v1 v2 v3 v4
A X  1  3  4  1
B Y  1  3  4  1
C X  1  3  4  1
D X  1  3  4  1
E Y  1  3  4  1

【讨论】:

以上是关于在R中:如果缺少另一行的值,则替换一行的值的主要内容,如果未能解决你的问题,请参考以下文章

如何使用javascript替换innerhtml中的值

R将数据帧中的字符串匹配替换为来自另一个数据帧/数组的值

如果不是 NAN,则用以前的值替换 Pandas 中的缺失值

更新一行,如果缺少则插入新行

C语言 如何将一个二维数组的值全部替换成另一个二维数组

SQL:如果 *condition* 在另一行上,则更新一行