R语言 在列中用0或以上的值n重复n次填充NAs

yfwxisqw  于 2023-01-18  发布在  其他
关注(0)|答案(3)|浏览(119)

我有一个数据框,如下所示:

df <- data.frame(x = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
                 y = c(NA, 2, NA, NA, NA, 3, NA, NA, NA, 1, NA, NA))

我希望它看起来像这样:

data.frame(x = c(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12),
           y = c(0, 2, 2, 0, 0, 3, 3, 3, 0, 1, 0, 0))

#>     x y
#> 1   1 0
#> 2   2 2
#> 3   3 2
#> 4   4 0
#> 5   5 0
#> 6   6 3
#> 7   7 3
#> 8   8 3
#> 9   9 0
#> 10 10 1
#> 11 11 0
#> 12 12 0

我用while循环解决了这个问题,但是我在寻找一个更像R的解决方案。
这是循环解决方案:

df[is.na(df)] <- 0 # replace all NA with 0

i = 1
while (i < nrow(df)){
  
  if (df$y[i] < 2){ # do nothing if y = 1
    i = i+1
  } else {
    df$y[(i+1):(i+df$y[i]-1)] <- df$y[i]
    i = i+df$y[i]
  }
}

附加问题:是否可以在管道内对多个色谱柱(例如色谱柱z = c(1, NA, NA, NA, 4, NA, NA, NA, NA, 2, NA, NA))进行分析?

nwlls2ji

nwlls2ji1#

您可以使用numeric创建一个空向量,使用complete.casesrep获取value,并使用complete.casessequence获取索引:

fill_n_repeat <- function(x){
  value = x[complete.cases(x)]
  idx = which(complete.cases(x))
  v = numeric(length(x)) 
  v[sequence(value, idx)] <- rep(value, value)
  v
}
library(dplyr)
df %>% 
  mutate(across(y:z, fill_n_repeat))
    x y z
1   1 0 1
2   2 2 0
3   3 2 0
4   4 0 0
5   5 0 4
6   6 3 4
7   7 3 4
8   8 3 4
9   9 0 0
10 10 1 2
11 11 0 2
12 12 0 0
0md85ypi

0md85ypi2#

对行进行分组,以便每个非NA开始一个新组,然后对于每个这样的组,如果第一个元素是NA,则输出0,否则输出第一个元素,多次后跟0。这仅使用基数R,但如果您喜欢dplyr,则用mutate替换transform,其他所有内容保持不变。

f <- function(x) if (is.na(x[1])) 0 else ifelse(seq_along(x) > x[1], 0, x[1])
transform(df, y = ave(y, cumsum(!is.na(y)), FUN = f))

给予(续)

x y
1   1 0
2   2 2
3   3 2
4   4 0
5   5 0
6   6 3
7   7 3
8   8 3
9   9 0
10 10 1
11 11 0
12 12 0

如果有几列,那么如果ix包含要处理的列号或列名,那么使用与上面相同的f,然后在要转换的每一列上运行它。

ix <- "y"
f <- function(x) if (is.na(x[1])) 0 else ifelse(seq_along(x) > x[1], 0, x[1])
f2 <- function(i) ave(df[[i]], cumsum(!is.na(df[[i]])), FUN = f)
replace(df, ix, lapply(ix, f2))
mlmc2os5

mlmc2os53#

或者,请尝试下面的代码没有任何自定义函数

df2 <- df %>% mutate(z=y) %>% fill(z) %>% group_by(y,z) %>%
 mutate(row=row_number()+1, y=ifelse(z>=row,z,y)) %>% ungroup() %>% 
select(-z,-row)

相关问题