用R中的data.table填充前一列的NA和特定条件

时间:2018-11-16 12:45:29

标签: r dplyr data.table na tidyr

我有一些桌子

        ID  V1  V2  V3  V4  V5  V6  V7  V8  V9 V10   limit
 1: 10167638  89  NA 116 102  96  NA 106 116  NA 144     3
 2: 10298462  74 114  NA  NA 114  NA 121 111  98 108     6
 3: 10316168  88  78  NA  77  72  96  NA  95  NA  NA     4
 4: 10423491 118  77  NA  86 139 127  NA 103  93  84     2
 5: 10497492  12 154  NA 121 121 114 111  NA  NA  NA     7
 6: 10619463  42  NA  NA  NA  NA  NA  NA  NA  NA 141     9
 7: 10631362 174  NA 125 118 117 116 139 116  NA 104    10
 8: 10725490  49  NA 175  NA 176  NA 139 123 140 141     5
 9: 10767348 140 106 174 162  NA 169 140 127 112  NA     6
10: 10832134  10 178  NA  NA 116  95  95 125 115 103     3

我尝试用先前的列值填充此NA (如果V2为NA,则用V1值填充)

具有限制条件(如果限制为3,则填充NA直到V3并保留NAs)

所以我想做的就是这样

         ID  V1  V2  V3  V4  V5  V6  V7  V8  V9 V10  limit
 1: 10167638  89  89 116 102  96  NA 106 116  NA 144     3
 2: 10298462  74 114 114 114 114 114 121 111  98 108     6
 3: 10316168  88  78  78  77  72  96  NA  95  NA  NA     4
 4: 10423491 118  77  NA  86 139 127  NA 103  93  84     2
 5: 10497492  12 154 154 121 121 114 111  NA  NA  NA     7
 6: 10619463  42  42  42  42  42  42  42  42  42 141     9
 7: 10631362 174 174 125 118 117 116 139 116 116 104    10
 8: 10725490  49  49 175 175 176  NA 139 123 140 141     5
 9: 10767348 140 106 174 162 162 169 140 127 112  NA     6
10: 10832134  10 178 178  NA 116  95  95 125 115 103     3

实际数据很大,因此可以使用data.table解决此问题 但是其他解决方案仍然可以,例如dplyr或tidyr或其他解决方案。

2 个答案:

答案 0 :(得分:2)

使用data.table的{​​{1}}函数:

代码

set()

结果

col <- paste0("V", 1:10)
for (i in 2:length(col)) {
  rows <- which(is.na(dt[[col[i]]]) & dt[["limit"]] >= i)
  set(
    x = dt,
    i = rows,
    j = col[i],
    value = dt[[col[i-1]]][rows]
  )
}

数据

dt
           ID  V1  V2  V3  V4  V5  V6  V7  V8  V9 V10 limit
 1:  10167638  89  89 116 102  96  NA 106 116  NA 144     3
 2:  10298462  74 114 114 114 114 114 121 111  98 108     6
 3:  10316168  88  78  78  77  72  96  NA  95  NA  NA     4
 4:  10423491 118  77  NA  86 139 127  NA 103  93  84     2
 5:  10497492  12 154 154 121 121 114 111  NA  NA  NA     7
 6:  10619463  42  42  42  42  42  42  42  42  42 141     9
 7:  10631362 174 174 125 118 117 116 139 139 139 104    10
 8:  10725490  49  49 175 175 176  NA 139 123 140 141     5
 9:  10767348 140 106 174 162 162 169 140 127 112  NA     6
10: 110832134  10 178 178  NA 116  95  95 125 115 103     3

答案 1 :(得分:0)

您可以尝试tidyverse

library(tidyverse)
dt %>% 
  gather(k, v, -ID, -limit) %>% # make df from wide to long
  mutate(k = factor(k, levels = unique(k))) %>% # for correct spreading in the last step
  group_by(ID) %>% 
  mutate(gr=ifelse(is.na(v), 1:n(), 0)) %>%  # check where the NA's are
  fill(v) %>% # update the values
  mutate(v = ifelse(limit >= gr, v, NA)) %>% # change to NA back again accrding limit
  select(-gr) %>% 
  spread(k, v) # backtransform to long
# A tibble: 10 x 12
# Groups:   ID [10]
          ID limit    V1    V2    V3    V4    V5    V6    V7    V8    V9   V10
       <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int> <int>
 1  10167638     3    89    89   116   102    96    NA   106   116    NA   144
 2  10298462     6    74   114   114   114   114   114   121   111    98   108
 3  10316168     4    88    78    78    77    72    96    NA    95    NA    NA
 4  10423491     2   118    77    NA    86   139   127    NA   103    93    84
 5  10497492     7    12   154   154   121   121   114   111    NA    NA    NA
 6  10619463     9    42    42    42    42    42    42    42    42    42   141
 7  10631362    10   174   174   125   118   117   116   139   116   116   104
 8  10725490     5    49    49   175   175   176    NA   139   123   140   141
 9  10767348     6   140   106   174   162   162   169   140   127   112    NA
10 110832134     3    10   178   178    NA   116    95    95   125   115   103