按组计算大于0的非NA值的数量

时间:2017-01-20 16:13:45

标签: r function dataframe

以下是数据集df

的示例
Name    L1     L2     L3    L4
Carl    1       NA     0     2
Carl    0       1     4     1 
Joe     3       0     3     1
Joe     2       2     1     0

我想创建一个函数,该函数能够计算列L2,L3和L4中大于0的值的数量,作为某个名称的函数。例如:

someFunction(Joe)
# 4

但是,我的专栏中有一些NA个。

我尝试使用complete.cases删除NA但我不想删除整行。我想使用aggregate,但是,我不确定如何。谢谢你的帮助。

4 个答案:

答案 0 :(得分:4)

我们可以使用

colSums(df[c("L2", "L3", "L4")] > 0, na.rm = TRUE)

或者你可能想要每人一笔钱:

m <- rowsum((df[c("L2", "L3", "L4")] > 0) + 0, df[["Name"]], na.rm = TRUE)

#     L2 L3 L4
#Carl  1  1  2
#Joe   1  2  1

这里有一些有趣的事情。 df[c("L2", "L3", "L4")] > 0是一个逻辑矩阵(NA):

  • 虽然colSums可以毫无困难地使用rowsum,但0不能。因此,修复是将0添加到此矩阵以将其转换为0-1数值矩阵;
  • 添加此(df[c("L2", "L3", "L4")] > 0) + 0时,我们必须df[c("L2", "L3", "L4")] > 0 + 0而不是+。 R中的操作优先级表示>优先于5 > 4 + 0 ## FALSE (5 > 4) + 0 ## 1 。试试这个玩具示例:

    >

    因此,我们希望括号首先评估+,然后data.frame(m)

如果您希望结果是数据框,只需将生成的矩阵转换为数据框:

extract <- function (person) {
  m <- rowsum((df[c("L2", "L3", "L4")] > 0) + 0, df[["Name"]], na.rm = TRUE)
  rowSums(m)[[person]]
  }

<强>后续

人们停止响应,因为关于获取函数的特定问题没有获取摘要数据集那么有趣。

好吧,如果你仍然采取我的方法,我会定义这样的功能:

extract("Joe")
# 4
extract("Carl")
# 4

然后你可以打电话

extract2 <- function (person) {
  ## subset data
  sub <- subset(df, df$Name == person, select = c("L2", "L3", "L4"))
  ## get sum
  sum(sub > 0, na.rm = TRUE)
  }

注意,这显然不是编写此类函数的最有效方法。因为如果您只想提取一个人的总和,则无需继续处理所有数据。我们可以这样做:

extract2("Joe")
# 4
extract2("Carl")
# 4

然后你可以打电话

$(document).ready(function() {

var info = ["Hello", "Bye", "Hey Gary"];
for (i = 0; i < 3; i++){
	document.getElementById('main').innerHTML += "<a id='" + info[i] + "' class='list-group-item'>"+info[i]+"</a>";
	document.getElementById(info[i]).innerHTML += "<input class='myBtn btn btn-danger pull-right'  	class='test77' value='send'>";
	document.getElementById('main').innerHTML += "<br><hr></hr>";
}

createbutton();
           
function createbutton() {
	$(".myBtn").click(function () {
		var value = $(this).closest("a").text();
		alert(value);
	});
}
	




});

答案 1 :(得分:3)

使用aggregate,您需要设置na.rm的{​​{1}}参数,以及sum本身的na.action参数。之后,可以轻松添加三列:

aggregate

或在dplyr中,

df_sums <- aggregate(. ~ Name, df, FUN = function(x) {
    sum(x > 0, na.rm = TRUE)
}, na.action = na.pass)

df_sums$sum_L2_L3_L4 <- with(df_sums, L1 + L2 + L3)

df_sums
##   Name L1 L2 L3 L4 sum_L2_L3_L4
## 1 Carl  1  1  1  2            4
## 2  Joe  2  1  2  1            4

或直接

library(dplyr)

df %>% group_by(Name) %>% 
    summarise_all(funs(sum(. > 0, na.rm = TRUE))) %>% 
    mutate(sum_L2_L3_L4 = L2 + L3 + L4)

## # A tibble: 2 × 6
##     Name    L1    L2    L3    L4 sum_L2_L3_L4
##   <fctr> <int> <int> <int> <int>        <int>
## 1   Carl     1     1     1     2            4
## 2    Joe     2     1     2     1            4

或data.table

df %>% group_by(Name) %>% summarise(sum = sum(cbind(L2, L3, L4) > 0, na.rm = TRUE))
## # A tibble: 2 × 2
##     Name   sum
##   <fctr> <int>
## 1   Carl     4
## 2    Joe     4

或直接

library(data.table)

setDT(df)[, lapply(.SD, function(x){sum(x > 0, na.rm = TRUE)}), by = Name
    ][, sum_L2_L3_L4 := L2 + L3 + L4, by = Name][]

##    Name L1 L2 L3 L4 sum_L2_L3_L4
## 1: Carl  1  1  1  2            4
## 2:  Joe  2  1  2  1            4

答案 2 :(得分:2)

我们可以使用aggregaterowSums来获取输出

aggregate(cbind(Total=rowSums(df[3:5]>0, 
              na.rm=TRUE))~cbind(Name=df$Name), FUN = sum)
#  Name Total
#1 Carl     4
#2  Joe     4

或使用data.table,将'data.frame'转换为'data.table'(setDT(df)),按'名称'分组并指定.SDcols中的选择列,{ {1}} Data.table的子集(unlist),将其转换为逻辑向量(.SD)并获取TRUE值的>0以创建汇总的“总计”柱

sum

或另一个选项是library(data.table) setDT(df)[, .(Total = sum(unlist(.SD)>0, na.rm = TRUE)), Name, .SDcols = L2:L4] # Name Total #1: Carl 4 #2: Joe 4 。我们dplyr/tidyr感兴趣的列,select为'long'格式,gather只有大于0的元素,然后按'Name'分组才能获得总行数({ {1}})

filter

答案 3 :(得分:1)

使用plyr,您可以:

library(plyr)

nonZeroDF = ddply(DF[,-2],"Name",.fun = function(x) 
data.frame(nonZeroObs=sum((x[,-1]) >0,na.rm=TRUE) ))

#  Name nonZeroObs
#1 Carl          4
#2  Joe          4