【问题标题】:Find minimum value greater than 0查找大于 0 的最小值
【发布时间】:2014-01-21 14:32:35
【问题描述】:

我有一个数据框,其中包含 1:4 的数值和一些 NA。对于每一行,我想计算出现次数最少的值大于 0 的频率(百分比)。

这是一个可以使用的示例数据框。

    df = as.data.frame(rbind(c(1,2,1,2,2,2,2,1,NA,2),c(2,3,3,2,3,3,NA,2,NA,NA),c(4,1,NA,NA,NA,1,1,1,4,4),c(3,3,3,4,4,4,NA,4,3,4)))

      V1 V2 V3 V4 V5 V6 V7 V8 V9 V10
    1  1  2  1  2  2  2  2  1 NA   2
    2  2  3  3  2  3  3 NA  2 NA  NA
    3  4  1 NA NA NA  1  1  1  4   4
    4  3  3  3  4  4  4 NA  4  3   4

我有 2 点正在努力解决。 1)找到大于 0 的值的最低频率和 2)将函数应用于我的数据帧的每一行。当我开始处理这个函数时,我使用下面的代码实现了它,但它似乎并没有应用于每一行。我对 value.1、value.2 等的结果对于每一行都是相同的。

    Low_Freq = function(x){
      value.1 = sum(x==1, na.rm=TRUE) #count the number of 1's per row
      value.2 = sum(x==2, na.rm=TRUE) #count the number of 2's per row
      value.3 = sum(x==3, na.rm=TRUE) #count the number of 3's per row
      value.4 = sum(x==4, na.rm=TRUE) #count the number of 4's per row
      num.values = rowSums(!is.na(x), na.rm=TRUE) #count total number of non-NA values in each row

      #what is the minimum frequency value greater than 0 among value.1, value.2, value.3, and value.4 for EACH row?
      min.value.freq = min(cbind(value.1,value.2,value.3,value.4)) 

      out = min.value.freq/num.values #calculate the percentage of the minimum value for each row
    }

    df$Low_Freq = apply(df, 1, function(x))

然后我开始使用 rowSums() 来计算 value.1、value.2、value.3 和 value.4。这解决了我为每一行计算 value.1、value.2 等的问题,但是,我必须在不使用 apply() 的情况下应用该函数才能运行:

    Low_Freq = function(x){
      value.1 = rowSums(x==1, na.rm=TRUE) #count the number of 1's per row
      value.2 = rowSums(x==2, na.rm=TRUE) #count the number of 2's per row
      value.3 = rowSums(x==3, na.rm=TRUE) #count the number of 3's per row
      value.4 = rowSums(x==4, na.rm=TRUE) #count the number of 4's per row
      num.values = rowSums(!is.na(x), na.rm=TRUE) #count total number of non-NA values in each row

      #what is the minimum frequency value greater than 0 among value.1, value.2, value.3, and value.4 for EACH row?
      min.value.freq = min(cbind(value.1,value.2,value.3,value.4)) 

      out = min.value.freq/num.values #calculate the percentage of the minimum value for each row
    }

    df$Low_Freq = Low_Freq(df)

因此,应用于每一行的行为似乎发生在函数本身内。这一切都很好而且很花哨,但是当我进行最终计算时,我无法弄清楚如何确定值 1、2、3 或 4 中的哪一个具有每行的最低频率。该值必须除以每行的非 NA 值的数量。

我想要的结果应该是这样的:

      V1 V2 V3 V4 V5 V6 V7 V8 V9 V10  Low_Freq
    1  1  2  1  2  2  2  2  1 NA   2 0.3333333
    2  2  3  3  2  3  3 NA  2 NA  NA 0.4285714
    3  4  1 NA NA NA  1  1  1  4   4 0.4285714
    4  3  3  3  4  4  4 NA  4  3   4 0.4444444

我觉得我在用这个看似简单的功能兜圈子。任何帮助将不胜感激。

谢谢。

【问题讨论】:

    标签: r apply min


    【解决方案1】:

    table 函数将返回每个值出现的频率,忽略 NA 值。因此,table 结果中的min 是某个值在您的行中出现的最小频率,总和是您的行中非NA 值的数量。

    Low_Freq = function(x){
      tab = table(x)
      return(min(tab) / sum(tab))
    }
    df$Low_Freq = apply(df, 1, Low_Freq)
    df
    #   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10  Low_Freq
    # 1  1  2  1  2  2  2  2  1 NA   2 0.3333333
    # 2  2  3  3  2  3  3 NA  2 NA  NA 0.4285714
    # 3  4  1 NA NA NA  1  1  1  4   4 0.4285714
    # 4  3  3  3  4  4  4 NA  4  3   4 0.4444444
    

    如果您不想将 5s 用作分子,而是将它们用作分母,您可以这样做:

    df = as.data.frame(rbind(c(1,2,1,2,2,2,2,1,NA,2),c(2,3,3,2,3,3,NA,2,NA,NA),c(4,1,NA,NA,NA,1,1,1,4,4),c(3,3,3,4,4,4,5,4,3,4)))
    Low_Freq = function(x){
      tab = table(x[x != 5])
      return(min(tab) / sum(!is.na(x)))
    }
    df$Low_Freq = apply(df, 1, Low_Freq)
    df
    #   V1 V2 V3 V4 V5 V6 V7 V8 V9 V10  Low_Freq
    # 1  1  2  1  2  2  2  2  1 NA   2 0.3333333
    # 2  2  3  3  2  3  3 NA  2 NA  NA 0.4285714
    # 3  4  1 NA NA NA  1  1  1  4   4 0.4285714
    # 4  3  3  3  4  4  4  5  4  3   4 0.4000000
    

    【讨论】:

    • 感谢您的回复。如果我在两行中出现一个数字“5”并且我只想使用数字 1、2、3 和 4 的最小频率,我该如何修改它?但是这个数字除以的总数应该仍然是非NA值的数量(包括5个)?
    猜你喜欢
    • 1970-01-01
    • 2012-09-16
    • 2010-10-20
    • 1970-01-01
    • 2017-04-20
    • 1970-01-01
    • 2021-10-27
    • 2021-09-15
    相关资源
    最近更新 更多