【问题标题】:How to fill one column with values taken randomly from the same row and different columns?如何用从同一行和不同列中随机获取的值填充一列?
【发布时间】:2019-06-12 20:46:49
【问题描述】:

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

我的数据如下:

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

【问题讨论】:

    标签: r dataframe


    【解决方案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)))
    

    【讨论】:

      【解决方案2】:

      另一种基本方法

      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
      

      此选项使用max.col 的ties.method 参数。 (默认是"random",所以你实际上不需要输入)

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

      数据

      感谢@JamesBonkowski

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

      【讨论】:

        【解决方案3】:

        还有另一种基本方法...我认为它与 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(.))
        

        可以,但是不行……

        【讨论】:

        • 谢谢!我刚刚发现在我的 df 中有一些行,其中所有列都是 NA,因此我收到错误“参数暗示不同的行数:0,1”。你知道我该怎么处理吗?
        • 我设法通过用 0 替换 NA 来解决这个问题(我知道,可能效率很低),然后我使用了你的代码,但它在我的 df 中创建了许多变量,称为“final.sic”。 code1”、“final.sic.code2”等,其中“final.sic.code1”在每一行中填充了 sic.code1 的第一个值,依此类推。我的 df 比我在这里写的不同而且大得多,所以我做了 cbind(df, final = apply(df[300:304], 1, fun)),其中 300.304 是我的列“sic.code1”-“sic .code4"
        • 我更新了我的代码以在所有值为 NA 时返回 NA;我不确定我是否理解您的第二条评论。
        • 谢谢。基本上我真正的 df 有 310 列,我只想将函数应用于其中的 4 个。我试图用你的代码做到这一点,但我想我做错了,我得到了一些非常奇怪的结果。无论如何,我最终使用以下代码进行了管理:df$final=apply(df[302:308], 1, fun)。我希望现在很清楚。再次感谢!
        猜你喜欢
        • 2016-06-14
        • 2019-03-14
        • 2015-02-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-03-08
        • 1970-01-01
        相关资源
        最近更新 更多