R 指示特定值首次出现的新变量
我想创建一个新的变量,它指示变量值的第一个特定观察值 在下面的示例数据集中,我希望有一个新变量“firstna”,它是“1”,用于该播放器的第一个“NA”观察值R 指示特定值首次出现的新变量,r,dplyr,panel,transformation,hierarchical-data,R,Dplyr,Panel,Transformation,Hierarchical Data,我想创建一个新的变量,它指示变量值的第一个特定观察值 在下面的示例数据集中,我希望有一个新变量“firstna”,它是“1”,用于该播放器的第一个“NA”观察值 game_data <- data.frame(player = c(1,1,1,1,2,2,2,2), level = c(1,2,3,4,1,2,3,4), points = c(20,NA,NA,NA,20,40,NA,NA)) game_data player level points 1 1 1
game_data <- data.frame(player = c(1,1,1,1,2,2,2,2), level = c(1,2,3,4,1,2,3,4), points = c(20,NA,NA,NA,20,40,NA,NA))
game_data
player level points
1 1 1 20
2 1 2 NA
3 1 3 NA
4 1 4 NA
5 2 1 20
6 2 2 40
7 2 3 NA
8 2 4 NA
game\u data这是一个包含数据的解决方案。表
:
library("data.table")
game_data <- data.table(player = c(1,1,1,1,2,2,2,2), level = c(1,2,3,4,1,2,3,4), points = c(20,NA,NA,NA,20,40,NA,NA))
game_data[, firstna:=is.na(points) & !is.na(shift(points)), player][]
# > game_data[, firstna:=is.na(points) & !is.na(shift(points)), player][]
# player level points firstna
# 1: 1 1 20 FALSE
# 2: 1 2 NA TRUE
# 3: 1 3 NA FALSE
# 4: 1 4 NA FALSE
# 5: 2 1 20 FALSE
# 6: 2 2 40 FALSE
# 7: 2 3 NA TRUE
# 8: 2 4 NA FALSE
库(“data.table”)
游戏数据游戏数据[,firstna:=is.na(点数)和!is.na(移位(点数)),玩家][]
#玩家等级分数firstna
#1:120假
#2:12不适用
#3:13 NA假
#4:14 NA错误
#5:2120假
#6:240假
#7:23不适用
#8:24NA假
您可以通过按玩家分组,然后进行变异来检查一行是否有NA值,而前一行没有
game_data %>%
group_by(player) %>%
mutate(firstna = ifelse(is.na(points) & lag(!is.na(points)),1,0)) %>%
ungroup()
结果:
# A tibble: 8 x 4
# Groups: player [2]
player level points firstna
<dbl> <dbl> <dbl> <dbl>
1 1 1 20 0
2 1 2 NA 1
3 1 3 NA 0
4 1 4 NA 0
5 2 1 20 0
6 2 2 40 0
7 2 3 NA 1
8 2 4 NA 0
#一个tible:8 x 4
#分组:玩家[2]
玩家等级分数firstna
1 1 1 20 0
2 1 2 NA 1
3 1 3 NA 0
414Na0
5 2 1 20 0
6 2 2 40 0
7 2 3 NA 1
8 2 4 NA 0
按玩家分组,然后创建一个布尔向量,用于前一行中既为NA又不重复的案例
# A tibble: 8 x 4
# Groups: player [2]
player level points firstna
<dbl> <dbl> <dbl> <dbl>
1 1 1 20 0
2 1 2 NA 1
3 1 3 NA 0
4 1 4 NA 0
5 2 1 20 0
6 2 2 40 0
7 2 3 NA 1
8 2 4 NA 0
一直运行到玩家组末尾的NAs块的第一行:
game_data %>%
group_by(player) %>%
mutate(firstna=as.numeric(is.na(points) & !duplicated(cbind(points,cumsum(!is.na(points))))))
库(tidyverse)
库(数据表)
数据帧(
player=c(1,1,1,1,2,2,2),
级别=c(1,2,3,4,1,2,3,4),
点=c(20,NA,NA,NA,20,40,NA,NA)
)->游戏数据
游戏数据基础1A基础R
解决方案:
ave(game_data$points, game_data$player,
FUN = function(x) seq_along(x) == match(NA, x, nomatch = 0))
另一个ave
选项,按组(player
)查找第一个NA
game_data$firstna另一种使用base的方法:
game_data$firstna <-
unlist(
tapply(game_data$points, game_data$player, function(x) {i<-which(is.na(x))[1];x[]<-0;x[i]<-1;x})
)
使用diff
transform(game_data, firstna = ave(is.na(points), player, FUN = function(x) c(0,diff(x))))
# player level points firstna
# 1 1 1 20 0
# 2 1 2 NA 1
# 3 1 3 NA 0
# 4 1 4 NA 0
# 5 2 1 20 0
# 6 2 2 40 0
# 7 2 3 NA 1
# 8 2 4 NA 0
及其dplyr
等价物:
library(dplyr)
game_data %>% group_by(player) %>% mutate(firstna = c(0,diff(is.na(points))))
# # A tibble: 8 x 4
# # Groups: player [2]
# player level points firstna
# <dbl> <dbl> <dbl> <dbl>
# 1 1 1 20 0
# 2 1 2 NA 1
# 3 1 3 NA 0
# 4 1 4 NA 0
# 5 2 1 20 0
# 6 2 2 40 0
# 7 2 3 NA 1
# 8 2 4 NA 0
库(dplyr)
游戏数据%>%由(玩家)分组%>%变异(firstna=c(0,diff(is.na(点数)))
##A tibble:8 x 4
##组别:玩家[2]
#玩家等级分数firstna
#
# 1 1 1 20 0
#2 1 2 NA 1
#3 1 3 NA 0
#414Na0
# 5 2 1 20 0
# 6 2 2 40 0
#7 2 3 NA 1
#8 2 4 NA 0
这假设NAs总是集中在一起。伙计,ave
再次攻击。该功能需要更好的公关。做得好!(而且速度也非常快)是啊,见鬼,这和平均数无关。。。为什么文档中会这样描述呢?一个问题:为什么返回的是数字而不是逻辑(正如我从=
中所期望的那样)?ave
将返回类型强制为其第一个参数的类型。因此,作为game\u data$points
numeric
,返回一个数值向量。这是使用ave
时要记住的一件事。这一次,该功能运行良好,但在其他情况下,它可能是一个障碍。这解释了为什么在game_data$的情况下,分数也非常好。可能比原版稍快:)酷!但是…我认为它与前面的NA
…:cumsum(is.NA(c(NA,1,NA))
相违背。也许OP从未出现过这种情况,但我只是想提一提。谢谢你的帮助,代码运行得很好,我喜欢使用dplyr。如果我想在第一个“NA”出现之前的一行中有firstna的“1”(在第1行和第6行的示例代码中),我可以添加什么?我在上面的答案中添加了必要的代码。很高兴听到这有帮助。别忘了投票并接受!非常感谢,这对我帮助很大!那么,把它当作一个新问题来考虑吧。你会得到更多的关注的,不管怎样。还添加了该解决方案。
ave(game_data$points, game_data$player,
FUN = function(x) seq_along(x) == match(NA, x, nomatch = 0))
game_data$firstna <- ave(game_data$points, game_data$player,
FUN = function(x) cumsum(is.na(x)) == 1)
game_data
# player level points firstna
#1 1 1 20 0
#2 1 2 NA 1
#3 1 3 NA 0
#4 1 4 NA 0
#5 2 1 20 0
#6 2 2 40 0
#7 2 3 NA 1
#8 2 4 NA 0
game_data$firstna <-
unlist(
tapply(game_data$points, game_data$player, function(x) {i<-which(is.na(x))[1];x[]<-0;x[i]<-1;x})
)
ave(game_data$points, game_data$player, FUN = function(x) {
i<-which(is.na(x))[1];x[]<-0;x[i]<-1;x
})
transform(game_data, firstna = ave(is.na(points), player, FUN = function(x) c(0,diff(x))))
# player level points firstna
# 1 1 1 20 0
# 2 1 2 NA 1
# 3 1 3 NA 0
# 4 1 4 NA 0
# 5 2 1 20 0
# 6 2 2 40 0
# 7 2 3 NA 1
# 8 2 4 NA 0
library(dplyr)
game_data %>% group_by(player) %>% mutate(firstna = c(0,diff(is.na(points))))
# # A tibble: 8 x 4
# # Groups: player [2]
# player level points firstna
# <dbl> <dbl> <dbl> <dbl>
# 1 1 1 20 0
# 2 1 2 NA 1
# 3 1 3 NA 0
# 4 1 4 NA 0
# 5 2 1 20 0
# 6 2 2 40 0
# 7 2 3 NA 1
# 8 2 4 NA 0