并提前感谢您的回顾。
我有一个事件数据框(EV):
Event_ID | Person_ID | Start_Period | End_Period | Event_Type
------------------------------------------------------------
A | Person1 | 1 | 9 | Assessment
B | Person1 | 2 | 9 | Activity
C | Person1 | 3 | 6 | Assessment
D | Person2 | 3 | 6 | Activity
E | Person3 | 7 | 13 | Assessment
我有一个Person-Periods(PP)数据框
Person_ID | Period
----------------------
Person1 | 1
Person1 | 2
Person1 | 3
Person2 | 1
Person2 | 2
Person2 | 3
Person3 | 1
Person3 | 2
Person3 | 3
我想了解每个时期内有多少活动或评估在此期间进行。例如,如果EV中Person1的事件的开始周期为5且结束周期为10,则此事件应显示在PP中的5,6,7,8,9,10中。结果如下:
Person_ID | Period | ActivitiesFreq | AssessmentsFreq
----------------------------------------------
Person1 | 1 | 0 | 1
Person1 | 2 | 1 | 1
Person1 | 3 | 1 | 2
Person2 | 1 | 0 | 0
Person2 | 2 | 0 | 0
Person2 | 3 | 1 | 0
Person3 | 1 | 0 | 0
Person3 | 2 | 0 | 0
Person3 | 3 | 0 | 0
目前我正在使用for循环 - 这很慢。我拒绝加入,因为完整数据集有数百和数千个数据。我尝试过使用dplyr包中的mutate:
mutate(PP,SUM(EV$Person_ID==Person_ID,EV$Start_Period<=Period,EV$End_Period>=Period)
但是我收到以下错误:
Warning messages:
1: In mutate_impl(.data, dots) :
is.na() applied to non-(list or vector) of type 'NULL'
2: In mutate_impl(.data, dots) :
longer object length is not a multiple of shorter object length
3: In mutate_impl(.data, dots) :
longer object length is not a multiple of shorter object length
我愿意使用其他软件包 - 我想我不太了解mutate的工作方式
答案 0 :(得分:4)
这是使用data.table v1.9.5
(当前devel版本)的解决方案。我将它用于新的on=
功能,允许连接而无需设置密钥:
require(data.table) # v1.9.5+
ans = setDT(df2)[df1, .(Period, Event_Type,
isBetween = Period %between% c(Start_Period, End_Period)),
by = .EACHI, on = "Person_ID", nomatch = 0L]
dcast(ans, Person_ID + Period ~ Event_Type, fun.aggregate = sum)
# Using 'isBetween' as value column. Use 'value.var' to override
# Person_ID Period Activity Assessment
# 1: Person1 1 0 1
# 2: Person1 2 1 1
# 3: Person1 3 1 2
# 4: Person2 1 0 0
# 5: Person2 2 0 0
# 6: Person2 3 1 0
# 7: Person3 1 0 0
# 8: Person3 2 0 0
# 9: Person3 3 0 0
工作原理:
setDT()
将 data.frame 转换为 data.table 就地(通过引用)。
setDT(df2)[df1, on = "Person_ID"]
对列Person_ID
执行加入操作。对于df1
中的每一行,计算df2
中相应的匹配行,并提取与这些匹配行对应的所有列。
setDT(df2)[df1, on = "Person_ID", nomatch = 0L]
,因为您可能已经猜到只返回匹配的行,并在Person_ID
中遗漏了df1
中的df2
行by = .EACHI
j
部分非常有用且功能强大。它有助于计算我们在[]
中提供的表达式,df1
中的第二个参数,df1
中的每一行。
例如,考虑Person_ID
的第2行。加入df2
,它与by = .EACHI
的第1,2,3行匹配。 .()
将执行Period = 1,2,3
中提供的表达式,该表达式将返回Event_Type = "Activity"
,isBetween = FALSE,TRUE,TRUE
和Event_Type
。 j
被回收以适应最长矢量的长度(= 3)。
基本上,我们同时加入和计算。这是 data.table 中的一项功能(仅限?),其中 join 被视为 subset 操作的扩展。由于我们可以在进行子集化和分组时进行计算,因此我们也可以在加入时完全相同。这是 fast 和 *内存效率,因为整个连接不必实现。
为了更好地理解它,请尝试计算最后一行将导致ans
表达式。
然后,看看Activity
,结果应该是显而易见的。
然后我们要采取最后一步,即为每个Assessment
计算Person_ID, Period
和dcast
的数量,并将它们作为单独的列。这可以使用Person_ID, Period
函数一步完成。
该公式暗示,对于每个sum()
,我们希望inBetween
Event_Type
的值setTimeout(
function () {
$('#ddlSessionList option:contains('+sessionName()+')')
.prop('selected', true);
}, 200);
,作为单独的列,用于{{1}的每个唯一值}。
答案 1 :(得分:0)
如果没有加入数据集,我还没有想出办法。这是一个基于 dplyr 的解决方案,首先使用left_join
连接数据集(我只从该任务所需的EV
中获取了三列)。
加入数据集后,您只需按Person_ID
对数据集进行分组,并计算两种类型事件的累计总和。我投了arrange
,以防Period
Person_ID
内的Event_Type
内的真实数据集不正常,并删除了mutate
中的library(dplyr)
PP %>%
left_join(., select(EV, -Event_ID, -End_Period), by = c("Person_ID", "Period" = "Start_Period")) %>%
group_by(Person_ID) %>%
arrange(Period) %>%
mutate(ActivitiesFreq = cumsum(Event_Type == "Activity" & !is.na(Event_Type)),
AssessmentFreq = cumsum(Event_Type == "Assessment" & !is.na(Event_Type)),
Event_Type = NULL)
Source: local data frame [9 x 4]
Groups: Person_ID
Person_ID Period ActivitiesFreq AssessmentFreq
1 Person1 1 0 1
2 Person1 2 1 1
3 Person1 3 1 2
4 Person2 1 0 0
5 Person2 2 0 0
6 Person2 3 1 0
7 Person3 1 0 0
8 Person3 2 0 0
9 Person3 3 0 0
列。
AVERAGE(cell1,cell2...)
答案 2 :(得分:-1)
这是一个潜在的解决方案: