如何用从同一行和不同列中随机抽取的值来填充一列?

时间:2019-06-12 20:46:49

标签: r dataframe

我正在寻找一种方法,该方法使用从同一行但从同一数据的不同列中获取的值来填充一列,我希望从中获取值的列是随机选择的。

我的数据如下:

sic.code.1 sic.code2 sic.code3 sic.code4
   7361       6211          NA       NA                                    
   6719        NA           NA       NA                                                     
   2329        NA           5065     5411                                                     
   2869       3674          6282     NA                             
   6282       6282          NA       NA
   6282        NA           NA       NA

我想创建一个新列“ sic.code.final”,其中每一行都用唯一的非na值填充(例如,第二行中的6719或第6行中的6282),或者在其他“ sic.code”列中的其他非na值中,应使用从其中之一获取的值(随机选择)填充该值。

我期望数据的可能实现之一可能是:

 sic.code.1 sic.code2 sic.code3 sic.code4   sic.code.final
    7361       6211          NA       NA          6211                               
    6719        NA           NA       NA          6719                                    
    2329       5065          5411     NA          2329                                           
    2869       3674          6282     NA          3674                    
    6282       6282          NA       NA          6282
    6282        NA           NA       NA          6282

任何帮助将不胜感激!

编辑

在我的数据中,有些行的所有列都具有NA:

sic.code.1 sic.code2 sic.code3 sic.code4
   7361       6211          NA       NA                                    
   6719        NA           NA       NA                                                     
   2329        NA           5065     5411                                                     
   2869       3674          6282     NA                             
   6282       6282          NA       NA
   NA          NA           NA       NA

3 个答案:

答案 0 :(得分:1)

这就是我在基地里要做的

df <- data.frame(sic.code.1 = 1:6,
                 sic.code2 = c(7, NA, NA, 8, 9, NA),
                 sic.code3 = c(NA, NA, 10, 1, NA, NA), 
                 sic.code4 = c(NA, NA, 12, NA, NA, NA))

cbind(df, sic.code.final = apply(df, 1, function(x) sample(rep(x[!is.na(x)], 2), 1)))

答案 1 :(得分:1)

另一种基本方法

set.seed(42)
df[, "final"] <- df[cbind(1:nrow(df),
                          max.col(!is.na(df), ties.method = "random"))]

结果

df
#  sic.code.1 sic.code2 sic.code3 sic.code4 final
#1          1         7        NA        NA     1
#2          2        NA        NA        NA     2
#3          3        12        10        NA    10
#4          4         8         1        NA     4
#5          5         9        NA        NA     5
#6          6        NA        NA        NA     6

此选项使用ties.method的{​​{1}}参数。 (默认值为max.col,因此您实际上不需要输入)

"random"为每一行返回非max.col(!is.na(df), ties.method = "random")值的列索引。然后NA从您的数据中提取这些值。

数据

感谢@JamesBonkowski

cbind(1:nrow(df), ...

答案 2 :(得分:0)

另一种基本方法...我认为它与James Bonkowski的区别在于对行的更健壮的处理,其中只有1个值不是NA。同样,以某种方式将fun的定义与其应用程序分开,对于理解代码和代码重用似乎很有用。

考虑从向量采样的问题(在我们的用例中为一行)。有两个挑战。首先,我们只想采样非NA值。第二个是sample()对待长度大于1的向量与长度为1的向量不同,如?sample所述。以下功能解决了这两个问题...

fun = function(x) {
    x = x[!is.na(x)]
    x[sample(length(x), 1)]
}

不幸的是,当向量包含所有NA时,它将返回长度为0的向量,而不是长度为1的向量,例如

> fun(NA)
logical(0)

可能不是一个特别优雅的变化

fun = function(x) {
    x = x[!is.na(x)]
    if (length(x)) {
        x[sample(length(x), 1)]
    } else NA 
}

那么眼前问题的应用就是apply()cbind()的简单应用

cbind(df, final = apply(df, 1, fun))

尝试使用“ tidyverse”方法来应用它令人沮丧,

df %>% rowwise() %>% mutate(final = fun(.))

可以,但是不会。