如何在R中将满足特定条件的案例中的缺失值替换为0?

3

背景:

我正在处理一个大型数据集,其中包含195,318名参与者赌博行为的纵向数据。该数据基于对一家赌博运营商内电子赌博行为的完全跟踪。赌博行为数据按月聚合,共计70个月。我有一个ID变量将参与者分开,一个时间变量(月份),以及许多赌博行为变量,如给定月份玩的活跃天数,下注量,总损失等。参与者在何时进行赌博活动方面存在差异。一个参与者可能在第2、3、4和7个月进行了赌博,另一个参与者可能在第3、5和7个月进行了赌博,第三个参与者可能在23、24、48、65等月进行了赌博。因此,存在大量“缺失值”。但是,由于记录了每次赌博,因此在此数据集中缺失意味着该人没有进行赌博。换句话说,缺失等于0。

问题/目标:

我想为缺失值(“NA”)插入0。但是我只想在特定情况下这样做。具体而言,我想在我定义的参与者的“活动期间”内为缺失值插入0,并将其他所有内容保留为原样。

参与者的活动期间是从他们开始赌博的第一个月到最后一个月的每个月。例如,对于在第2、3、4和7个月进行了赌博的参与者,我想在第5和6个月为其插入0。每个其他月份,即1和9至70,我希望保持为NA。我正在努力编写实现此目标的代码。我是R的新手。

示例数据框和代码

下面是一个示例代码,生成了一个数据框,展示了我问题中描述的关键特征。在这段代码中,只有2名参与者,1个赌博行为变量和10个时间点(“波”)。我包括了“长格式”和“宽格式”的数据框,因为我不确定哪一个会更有帮助/信息量。在“长格式”中包含时间变量。我的实际数据集是长格式,但我知道如何在两种格式之间切换。

# Example variables and data frame in long form
  # Includes id variable, time variable and example variable
id <- c(1, 1, 1, 1, 2, 2, 2)
time <- c(2, 3, 4, 7, 3, 5, 7)
daysPlayed <- c(2, 2, 3, 3, 2, 2, 2)
dfLong <- data.frame(id = id, time = time, daysPlayed = daysPlayed)

这段内容是在2020年3月28日由 reprex包 (v0.3.0) 创建的。

# Example variables and data frame in wide form
  # Includes id variable, days played in given month 
id <- c(1, 2)
daysPlayed.1 <- c(NA, NA)
daysPlayed.2 <- c(2, NA)
daysPlayed.3 <- c(2, 2)
daysPlayed.4 <- c(3, NA)
daysPlayed.5 <- c(NA, 2)
daysPlayed.6 <- c(NA, NA)
daysPlayed.7 <- c(3, 2)
daysPlayed.8 <- c(NA, NA)
daysPlayed.9 <- c(NA, NA)
daysPlayed.10 <- c(NA, NA)
dfWide <- data.frame(id=id, daysPlayed.1 = daysPlayed.1, daysPlayed.2 = daysPlayed.2,
                 daysPlayed.3 = daysPlayed.3, daysPlayed.4 = daysPlayed.4,
                 daysPlayed.5 = daysPlayed.5, daysPlayed.6 = daysPlayed.6,
                 daysPlayed.7 = daysPlayed.7, daysPlayed.8 = daysPlayed.8,
                 daysPlayed.9 = daysPlayed.9, daysPlayed.10 = daysPlayed.10)

本示例由reprex package (v0.3.0)创建于2020年03月28日。

1个回答

2

在这个例子中,假设每个玩家都有9个月的数据(您可以稍后更改为实际月份值),我们可以使用complete来填充缺失的月份序列,并用0填充其中间的值。

library(dplyr)

dfLong %>%
  tidyr::complete(id, time = 1:9) %>%
  group_by(id) %>%
  mutate(daysPlayed = replace(daysPlayed, is.na(daysPlayed) & 
                      between(row_number(), min(which(!is.na(daysPlayed))),
                      max(which(!is.na(daysPlayed)))), 0))


#     id  time daysPlayed
#   <dbl> <dbl>      <dbl>
# 1     1     1         NA
# 2     1     2          2
# 3     1     3          2
# 4     1     4          3
# 5     1     5          0
# 6     1     6          0
# 7     1     7          3
# 8     1     8         NA
# 9     1     9         NA
#10     2     1         NA
#11     2     2         NA
#12     2     3          2
#13     2     4          0
#14     2     5          2
#15     2     6          0
#16     2     7          2
#17     2     8         NA
#18     2     9         NA

如果我们想要填补每个id的活动期间缺失的time,我们可以使用:

dfLong %>%
  group_by(id) %>%
  tidyr::complete(time = seq(min(time), max(time)), fill = list(daysPlayed = 0))

这段代码很好用,谢谢。不过,有可能仅为参与者的活动期完成时间吗?我有70个时间点,为每个参与者添加每个时间点的行会使我的数据框膨胀(从大约300万到1300万条观察)。例如,如果我的某个参与者在2、3、4和7进行了测量,那么我只需要在该参与者的1、5和6处添加行。另外,如果有一些代码可以让我删除只是NA值的行,那就更好了。 - André

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接