【问题标题】:Replace NaNs in dataframe with values from another dataframe based on two criteria根据两个标准将数据框中的 NaN 替换为另一个数据框中的值
【发布时间】:2015-06-20 19:17:57
【问题描述】:

您好,这是我在 stackoverflow 上的第一篇文章。我一直在尝试解决这个问题,但无法单独找出答案,也无法找到其他回答这个问题的帖子。

我需要用另一个数据帧中的值替换我的数据集中的缺失值;然而,棘手的地方在于我需要匹配的值有另一个与它们相关的因素,但匹配日期。

这是第一个数据帧的简化版本:

> df1
 date       site       Value  
 1991-07-08 A          22.5
 1991-07-09 A          NaN
 1992-07-13 B          23.1
 1992-07-14 A          NaN
 1993-07-07 B          27.3

这是第二个数据框的简化版本:

> df2
date       site         value
1991-07-08 A          22.5
1991-07-09 A           NaN
1992-07-14 A           NaN
1991-07-08 B          10.6
1992-07-09 B            23
1992-07-14 B           NaN
1992-07-09 C          11.3
1992-07-14 C          12.4

我想要做的是,当 A 缺少值时,将其替换为 B 中的值(具有相同的日期),如果 B 没有值,则使用 C 的值(具有相同的日期)。因此,生成的数据框将如下所示:

> dfFIN
date       site       Value  
1991-07-08 A          22.5
1991-07-09 A            23
1992-07-13 B          23.1
1992-07-14 A          12.4
1993-07-07 B          27.3

这是我目前想出的:

dfFIN<-replace(df1[which(df1$site=="A"),],
           df1$value[which(df$value=="NaN")],
           df2$value[which(df2$site=="B" &        
           df2$date==df1$date[which(df1$value=="NaN" & df1$site=="A")])])

但是,我收到以下错误消息:

Error in [<-.data.frame(*tmp*, list, value = numeric(0)) : 
    missing values are not allowed in subscripted assignments of data frames

而且我还没有合并站点 C。我不太确定该怎么做,如果有任何帮助,我将不胜感激。

【问题讨论】:

  • 您需要使用?is.nan 而不是尝试=="NaN" - NaN 是一个代表无限值的特殊值。

标签: r replace dataframe nan


【解决方案1】:

欢迎来到 SO!首先,您的问题似乎有点不明确,所以我继续进行了一些更改。我从两个数据框开始:

df1 <- read.table(text = "
date       site       Value  
1991-07-08 A          22.5
1991-07-09 A          NaN
1992-07-13 B          23.1
1992-07-14 A          NaN
1993-07-07 B          27.3
", head = T)
df2 <- read.table(text = "
date       site         Value
1991-07-08 A          22.5
1991-07-09 A           NaN
1992-07-14 A           NaN
1991-07-08 B          10.6
1991-07-09 B            23
1992-07-14 B           NaN
1992-07-09 C          11.3
1992-07-14 C          12.4
", head = T)

NaN 替换为更传统的NA

df1$Value[is.nan(df1$Value)] <- NA
df2$Value[is.nan(df2$Value)] <- NA

合并(左连接)从长格式转换为宽格式 (reshape2) 的数据帧,以便日期作为键:

library(reshape2)
dd1 <- dcast(df1, date ~ site)
dd2 <- dcast(df2, date ~ site)

dm <- merge(dd1, dd2, by = "date", all.x = TRUE, suffixes = c("", ".y"))

dm 看起来像这样:

        date    A    B  A.y  B.y    C
1 1991-07-08 22.5   NA 22.5 10.6   NA
2 1991-07-09   NA   NA   NA 23.0   NA
3 1992-07-13   NA 23.1   NA   NA   NA
4 1992-07-14   NA   NA   NA   NA 12.4
5 1993-07-07   NA 27.3   NA   NA   NA

现在,您可以非常轻松地将NA 替换为您想要的任何内容,而无需担心日期。我正在使用以下规则:如果缺少A,则使用B.y,如果还缺少B.y,则使用C

dm$A <- ifelse(is.na(dm$A), 
               ifelse(is.na(dm$B.y),
                      dm$C, dm$B.y), 
               dm$A)

现在恢复原来的格式:

dfFin <- na.omit(melt(dm[, c("date", "A", "B")], id = "date", variable.name = "site"))

         date site value
1  1991-07-08    A  22.5
2  1991-07-09    A  23.0
4  1992-07-14    A  12.4
8  1992-07-13    B  23.1
10 1993-07-07    B  27.3

【讨论】:

  • 谢谢@tonytonov 跟进,假设我的站点比 ABC 多,每个站点会有不同的替换站点,例如,站点 A 将替换为 B 而不是 C;站点 B 将由 C 而不是 D 替换;站点 E 将替换为 F 而不是 G。如何将 if else 语句更改为更通用?
  • 这需要不同于ifelse 的东西。我建议您问另一个与此相关的问题。完成后您可以给我发送通知。
猜你喜欢
  • 1970-01-01
  • 2021-11-01
  • 2022-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-03-23
  • 1970-01-01
  • 2020-04-14
  • 1970-01-01
相关资源
最近更新 更多