【问题标题】:R - calculating mode and percentages by mode and targetR - 按模式和目标计算模式和百分比
【发布时间】:2015-11-16 08:08:03
【问题描述】:

我正在尝试计算数字列的模式。不是数字的列应该有一个“NA”作为向量中的占位符。我还需要根据目标的百分比。一些示例数据:

c1= c("A", "B", "C", "C", "B", "C", "C") 
c2= factor(c(1, 1, 2, 2,1,2,1), labels = c("Y","N"))
d= as.Date(c("2015-02-01", "2015-02-03","2015-02-01","2015-02-05", "2015-02-03","2015-02-01", "2015-02-03"), format="%Y-%m-%d")
x= c(1,1,2,3,1,2,4) 
y= c(1,2,2,6,2,3,1) 
t= c(1,0,1,1,0,0,1)
df=data.frame(c1, c2, d, x, y,t) 
df

  c1 c2          d x y t
1  A  Y 2015-02-01 1 1 1
2  B  Y 2015-02-03 1 2 0
3  C  N 2015-02-01 2 2 1
4  C  N 2015-02-05 3 6 1
5  B  Y 2015-02-03 1 2 0
6  C  N 2015-02-01 2 3 0
7  C  Y 2015-02-03 4 1 1

我需要每个数字列的模式:

mode=as.numeric(c("NA","NA", "NA", 1,2,1))
mode
[1] NA NA NA  1  2  1

当列中的值 == 模式时,t==1 的行百分比向量

[1] NA NA NA  0.33  0.33  

当列 != 模式中的值时,t==1 的行百分比向量

[1] NA NA NA  0.75  0.75

我如何计算这样的向量?

我发现的最佳模式是:

library(plyr)

mode_fun <- function(x) {
  mode0 <- names(which.max(table(x)))
  if(is.numeric(x)) return(as.numeric(mode0))
  mode0
}
kdf_mode=apply(kdf,2, numcolwise(mode_fun))

但如果有任何非数字列,则会出错。

【问题讨论】:

  • 非常感谢阿克伦!
  • 这太复杂了,我不得不仔细考虑...请在您的答案下查看评论。非常感谢您的帮助!

标签: r apply mode


【解决方案1】:

我们可以使用sapply 循环'df' 的列,应用mode_fun 得到输出vector ('v1')。我们使用if/else 条件为非数字列返回NA

 v1 <- unname(sapply(df, function(x) if(!is.numeric(x)) NA else mode_fun(x)))
 v1
 #[1] NA NA NA  1  2  1

对于第二种情况(我想我们不需要第 6 列,即“t”)。我们使用sapply 遍历'df' 的列,使用if/else 条件。在else 条件中,我们比较mode 值是否等于列值(mode_fun(x)==x))。我们使用&amp; 来获取等于mode 的值的逻辑索引,该索引对应于t==1。获取sum 并除以sum(v1)

unname(sapply(df[-6], function(x) if(!is.numeric(x)) {
            NA
            } else {
                v1 <- mode_fun(x)==x
                sum(v1 & t==1)/sum(v1) 
  } ))
 #[1]        NA        NA        NA 0.3333333 0.3333333

对于第三个,我们更改条件以获取列不等于mode 的逻辑索引。与前一种情况相同。

unname(sapply(df[-6], function(x) if(!is.numeric(x)){
         NA 
         } else {
              v1 <- mode_fun(x)!=x
              sum(v1 & t==1)/sum(v1)
   } ))
 #[1]   NA   NA   NA 0.75 0.75

在我们计算 'v1' 之后,这也可以在不使用 sapply 循环的情况下完成。我们创建一个逻辑索引,其中 class 列是“数字”,而列名不是“t”(“indx”)。

indx <- sapply(df, is.numeric) &  names(df)!='t'

我们根据“indx”(df[indx]v1[indx])对“df”和“v1”进行子集化,通过使用col 复制vector 来确定长度。 col 给出了df[indx] 中列的数字索引。然后我们检查子集数据集是否等于vector,以给出一个逻辑矩阵。

indx1 <- df[indx]==v1[indx][col(df[indx])] 

和前面的代码一样,我们使用&amp;来检查'indx1'中的TRUE值是否也对应于't==1. DocolSums, divide by thecolSumsof 'indx1', and concatenate (c) with theNA `'v1' 的元素

unname(c(v1[is.na(v1)], colSums(indx1& t==1)/colSums(indx1)))
#[1]        NA        NA        NA 0.3333333 0.3333333

同样,我们可以通过改变条件来创建'indx2',然后像以前一样做colSums

indx2 <- df[indx]!=v1[indx][col(df[indx])] 
unname(c(v1[is.na(v1)], colSums(indx2& t==1)/colSums(indx2)))
#[1]   NA   NA   NA 0.75 0.75

【讨论】:

  • 对不起,我在示例中输入了错误的数字,0.66 ( v1[4]) 应该是 0.33。方法如下:按列计算模式(现在可以正常工作了!)。然后对于那些值等于众数的单元格,我们计算也有 t==1 的百分比。例如,在 x 列中,三个值(在第 1、2 和 5 行)等于模式(对于 col x 为 1),但只有在第 nr 1 行中,col t 中的值是 1(对于第 2 行和第 5 行,t 是0)。所以这就是为什么 v1 中的第四个值应该是 1/3=0.33。同样,对于 v2,我们正在查看 != 模式以及其中有多少具有 t==1 的值,因此我们得到 0.75。
  • 非常感谢!我沉默了这么久,因为使用我的真实数据,您的代码只给出了 NA:s,尽管使用示例数据它工作得很好。我花了一段时间才意识到数字列中有 NA:s 阻止了求和。我添加了 sum(mode_fun(x)==x, na.rm=TRUE) 现在没有问题了!非常感谢!
  • @ElinaJ 感谢您的反馈。 NA 值肯定会产生问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-12-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-08-17
  • 1970-01-01
  • 2022-01-14
相关资源
最近更新 更多