R 跨多个列应用函数

R 跨多个列应用函数,r,data.table,R,Data.table,请在这里找到我正在使用的长data.table的一个非常小的子集 dput(dt) structure(list(id = 1:15, pnum = c(4298390L, 4298390L, 4298390L, 4298558L, 4298558L, 4298559L, 4298559L, 4299026L, 4299026L, 4299026L, 4299026L, 4300436L, 4300436L, 4303566L, 4303566L), invid = c(15

请在这里找到我正在使用的长data.table的一个非常小的子集

dput(dt)
structure(list(id = 1:15, pnum = c(4298390L, 4298390L, 4298390L, 
    4298558L, 4298558L, 4298559L, 4298559L, 4299026L, 4299026L, 4299026L, 
    4299026L, 4300436L, 4300436L, 4303566L, 4303566L), invid = c(15L, 
    101L, 102L, 103L, 104L, 103L, 104L, 106L, 107L, 108L, 109L, 87L, 
    111L, 2L, 60L), fid = structure(c(1L, 1L, 1L, 2L, 2L, 2L, 2L, 
    4L, 4L, 4L, 4L, 3L, 3L, 2L, 2L), .Label = c("CORN", "DowCor", 
    "KIM", "Texas"), class = "factor"), dom_kn = c(1L, 0L, 0L, 0L, 
    1L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L), prim_kn = c(1L, 
    0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L), pat_kn = c(1L, 
    0L, 0L, 0L, 1L, 0L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L), net_kn = c(1L, 
    0L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 1L), age_kn = c(1L, 
    0L, 0L, 1L, 1L, 1L, 1L, 0L, 0L, 0L, 0L, 1L, 0L, 1L, 0L), legclaims = c(5L, 
    0L, 0L, 2L, 5L, 2L, 5L, 0L, 0L, 0L, 0L, 5L, 0L, 5L, 2L), n_inv = c(3L, 
    3L, 3L, 2L, 2L, 2L, 2L, 4L, 4L, 4L, 4L, 2L, 2L, 2L, 2L)), .Names = c("id", 
    "pnum", "invid", "fid", "dom_kn", "prim_kn", "pat_kn", "net_kn", 
    "age_kn", "legclaims", "n_inv"), class = "data.frame", row.names = c(NA, 
    -15L))
我希望在5个不同的列中应用调整后的大于比较

在每个
pnum
(专利)中,都有多个
invid
(发明人)。我想将每行
dom_kn
prim_kn
pat_kn
net_kn
age_kn
列的值与其他行中具有相同
pnum
的值进行比较。比较只是
,如果该值确实大于另一个值,则应归因于一个“点”

因此,对于第一行
pnum==4298390
invid==15
,您可以看到五列中的值都是
1
,而
invid==101 | 102
的值都是零。这意味着,如果我们单独比较(大于?)第一行中的每个值与第二行和第三行中的每个单元格,则总和将为10分。在每一次比较中,第一行中的值较大,有10次比较。 比较次数按设计
5*(n\u inv-1)
。 我要查找的第1行的结果应该是
10/10=1

对于
pnum==4298558
而言,列
net_kn
age_kn
在两行中都有值1(对于
invid
103和104),因此每个列都应该得到0.5分(如果有三个发明人的值为1,每个人都应该得到0.33分)。这同样适用于pnum==4298558

对于下一个
pnum==4299026
所有值均为零,因此每次比较应得到0分

因此请注意差异:有三种不同的二元比较

1 > 0 --> assign 1
1 = 1 --> assign 1 / number of positive values in column subset
0 = 0 --> assign 0
期望的结果 数据表中的一个额外列
result
,其值
1 0 0 0.2 0.8 0.2 0.8 0 0 0 0 0 1 0.8 0.2

关于如何有效地计算这个问题,有什么建议吗


谢谢

这里有一个使用
dplyr
的快速解决方案:

library(dplyr)
dt %>%
 group_by(pnum) %>% # group by pnum
 mutate_each(funs(. == max(.) & max(.) != 0), ends_with('kn')) %>%
 #give a 1 if the value is the max, and not 0. Only for the column with kn
 mutate_each(funs(. / sum(.)) , ends_with('kn')) %>%
 #correct for multiple maximums
 select(ends_with('kn')) %>%
 #remove all non kn columns
 do(data.frame(x = rowSums(.[-1]), y = sum(.[-1]))) %>%
 #make a new data frame with x = rowsums for each indvidual
 # and y the colusums
 mutate(out = x/y)
 #divide by y (we could just use /5 if we always have five columns)
在列
out
中给出所需的输出:

Source: local data frame [15 x 4]
Groups: pnum [6]

      pnum     x     y   out
     (int) (dbl) (dbl) (dbl)
1  4298390     5     5   1.0
2  4298390     0     5   0.0
3  4298390     0     5   0.0
4  4298558     1     5   0.2
5  4298558     4     5   0.8
6  4298559     1     5   0.2
7  4298559     4     5   0.8
8  4299026   NaN   NaN   NaN
9  4299026   NaN   NaN   NaN
10 4299026   NaN   NaN   NaN
11 4299026   NaN   NaN   NaN
12 4300436     5     5   1.0
13 4300436     0     5   0.0
14 4303566     4     5   0.8
15 4303566     1     5   0.2
NAN来自没有赢家的组,使用例如:

x[is.na(x)] <- 0

x[is.na(x)]这里有一个使用
dplyr的快速解决方案:

library(dplyr)
dt %>%
 group_by(pnum) %>% # group by pnum
 mutate_each(funs(. == max(.) & max(.) != 0), ends_with('kn')) %>%
 #give a 1 if the value is the max, and not 0. Only for the column with kn
 mutate_each(funs(. / sum(.)) , ends_with('kn')) %>%
 #correct for multiple maximums
 select(ends_with('kn')) %>%
 #remove all non kn columns
 do(data.frame(x = rowSums(.[-1]), y = sum(.[-1]))) %>%
 #make a new data frame with x = rowsums for each indvidual
 # and y the colusums
 mutate(out = x/y)
 #divide by y (we could just use /5 if we always have five columns)
在列
out
中给出所需的输出:

Source: local data frame [15 x 4]
Groups: pnum [6]

      pnum     x     y   out
     (int) (dbl) (dbl) (dbl)
1  4298390     5     5   1.0
2  4298390     0     5   0.0
3  4298390     0     5   0.0
4  4298558     1     5   0.2
5  4298558     4     5   0.8
6  4298559     1     5   0.2
7  4298559     4     5   0.8
8  4299026   NaN   NaN   NaN
9  4299026   NaN   NaN   NaN
10 4299026   NaN   NaN   NaN
11 4299026   NaN   NaN   NaN
12 4300436     5     5   1.0
13 4300436     0     5   0.0
14 4303566     4     5   0.8
15 4303566     1     5   0.2
NAN来自没有赢家的组,使用例如:

x[is.na(x)] <- 0
x[is.na(x)]
处理上述
NaN
案例(可以说是正确的答案)由读者决定


处理上述
NaN
案例(可以说是正确答案)留给读者。

我不太清楚,因为
pnum==4298558
,net_kn和age_kn都是1,所以没有一个大于另一个,根据您的描述,它们应该是0。为什么不是这样?描述可能不清楚。它们都有值1,需要与同样有值1的下一行进行比较。如果它们相等且为1,则应获得专利“比较简单>栏中正值数量的1/值,如果该值确实大于另一个值,则应归因于一个“点”。它们相等,所以它们得到0,为什么它们得到1?好的,我需要重新定义它。如果在同一列和同一专利中,多个值的值为1,则分配的值不为零。它必须是1除以非零值的数量。这些列只能取1或0?我不太清楚,因为
pnum==4298558
,net_kn和age_kn都有1,所以没有一个大于另一个,根据您的描述,它们应该得到0。为什么不是这样?描述可能不清楚。它们都有值1,需要与同样有值1的下一行进行比较。如果它们相等且为1,则应获得专利“比较简单>栏中正值数量的1/值,如果该值确实大于另一个值,则应归因于一个“点”。它们相等,所以它们得到0,为什么它们得到1?好的,我需要重新定义它。如果在同一列和同一专利中,多个值的值为1,则分配的值不为零。它必须是1除以非零值的数量,这些列只能取1或0?这真是一个很棒的解决方案。我甚至不知道可以通过
data.table
中的
参数向
添加列名。那太好了。同样非常出色的是,您成功地忽略了这个困难的解释,并意识到可以通过对列中的行进行求和来实现同样的效果。直到《蝙蝠侠与超人》的一半,我才意识到这一点!就我的理解而言,这里的
.N
是否等于特定变量的列和,而不是行数的计数?如果是,这是因为您在
by
语句中添加了
'var
?再次感谢!很乐意帮忙
.N
是“pnum”和给定“var”的每个唯一组合的行数。这真是一个很棒的解决方案。我甚至不知道可以通过
data.table
中的
参数向
添加列名。那太好了。同样非常出色的是,您成功地忽略了这个困难的解释,并意识到可以通过对列中的行进行求和来实现同样的效果。直到《蝙蝠侠与超人》的一半,我才意识到这一点!就我的理解而言,这里的
.N
是否等于特定变量的列和,而不是行数的计数?如果是,这是因为您在
by
语句中添加了
'var
?再次感谢!很乐意帮忙
.N
是“pnum”和给定“var”的每个唯一组合的行数。