在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中:如果缺少另一行的值,则替换一行的值的主要内容,如果未能解决你的问题,请参考以下文章