วิธีแทนที่ NA ด้วยชุดของค่า


18

ฉันมีกรอบข้อมูลต่อไปนี้:

library(dplyr)
library(tibble)


df <- tibble(
  source = c("a", "b", "c", "d", "e"),
  score = c(10, 5, NA, 3, NA ) ) 


df

ดูเหมือนว่านี้:

# A tibble: 5 x 2
  source score
  <chr>  <dbl>
1 a         10 . # current max value
2 b          5
3 c         NA
4 d          3
5 e         NA

สิ่งที่ฉันต้องการจะทำคือการแทนที่NAในคอลัมน์คะแนนด้วยค่าต่างๆสำหรับปัจจุบันmax + nเป็นต้นไป โดยnมีช่วงตั้งแต่ 1 ถึงจำนวนแถวทั้งหมดของdf

ส่งผลให้ในนี้ (เขียนด้วยมือ):

  source score
  a         10
  b          5
  c         11 # obtained from 10 + 1
  d          3
  e         12 #  obtained from 10 + 2

ฉันจะบรรลุสิ่งนั้นได้อย่างไร

คำตอบ:


8

ตัวเลือกอื่น:

transform(df, score = pmin(max(score, na.rm = TRUE) + 
                      cumsum(is.na(score)), score, na.rm = TRUE))

#  source score
#1      a    10
#2      b     5
#3      c    11
#4      d     3
#5      e    12

หากคุณต้องการทำสิ่งนี้ใน dplyr

library(dplyr)
df %>% mutate(score = pmin(max(score, na.rm = TRUE) + 
                      cumsum(is.na(score)), score, na.rm = TRUE))

6

สารละลาย R พื้นฐาน

df$score[is.na(df$score)] <- seq(which(is.na(df$score))) + max(df$score,na.rm = TRUE)

ดังนั้น

> df
# A tibble: 5 x 2
  source score
  <chr>  <dbl>
1 a         10
2 b          5
3 c         11
4 d          3
5 e         12

เป็นข้อสรุปที่สั้นที่สุด แต่สามารถย่อseq(which(is.na(df$score)))ให้สั้นลงได้1:sum(is.na(df$score))
sindri_baldur

@sindri_baldur ขอบคุณ ที่หนึ่งได้รับการเสนอโดยstackoverflow.com/a/60222864/12158757
ThomasIsCoding

6

นี่คือ dplyrวิธีการ

df %>% 
 mutate(score = replace(score, 
                       is.na(score), 
                       (max(score, na.rm = TRUE) + (cumsum(is.na(score))))[is.na(score)])
                       )

ซึ่งจะช่วยให้,

# A tibble: 5 x 2
  source score
  <chr>  <dbl>
1 a         10
2 b          5
3 c         11
4 d          3
5 e         12

4

ด้วยdplyr:

library(dplyr)

df %>%
  mutate_at("score", ~ ifelse(is.na(.), max(., na.rm = TRUE) + cumsum(is.na(.)), .))

ผลลัพธ์:

# A tibble: 5 x 2
  source score
  <chr>  <dbl>
1 a         10
2 b          5
3 c         11
4 d          3
5 e         12

3

dplyrวิธีการแก้ปัญหา

df %>%
  mutate(na_count = cumsum(is.na(score)),
         score = ifelse(is.na(score), max(score, na.rm = TRUE) + na_count, score)) %>%
  select(-na_count)
## A tibble: 5 x 2
#  source score
#  <chr>  <dbl>
#1 a         10
#2 b          5
#3 c         11
#4 d          3
#5 e         12

2

อีกอันหนึ่งค่อนข้างคล้ายกับโซลูชันของ ThomasIsCoding:

> df$score[is.na(df$score)]<-max(df$score, na.rm=T)+(1:sum(is.na(df$score)))
> df
# A tibble: 5 x 2
  source score
  <chr>  <dbl>
1 a         10
2 b          5
3 c         11
4 d          3
5 e         12

2

ไม่ได้ค่อนข้างหรูหราเมื่อเทียบกับโซลูชั่น R พื้นฐาน แต่ยังคงเป็นไปได้:

library(data.table)
setDT(df)

max.score = df[, max(score, na.rm = TRUE)]
df[is.na(score), score :=(1:.N) + max.score]

หรือเป็นหนึ่งบรรทัด แต่ช้าลงเล็กน้อย:

df[is.na(score), score := (1:.N) + df[, max(score, na.rm = TRUE)]]
df
   source score
1:      a    10
2:      b     5
3:      c    11
4:      d     3
5:      e    12
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.