我有一个长数据框,其中包含多个主题(id),试验编号和回复。我想知道每个主题的回复变化了多少次。可能的响应是1和0。 因此,对于同一主题的每一行,新的“更改”列应具有相同的编号。
现在,我能够获得整个数据帧在响应中的更改数量,而不是特定于每个主题(id)。
我如何获得此号码,以便特定于ID?我以为group_by()
会这样做,但是不会。
HNPS_df2的标头:id Trial_Num响应 每个试用版的每个ID都有一行
HNPS_df2 <- HNPS_df2 %>%
group_by(id) %>%
mutate(change = cumsum(ifelse(Response != lag(Response) | is.na(lag(Response)), 1, 0)))
有什么想法吗? 对于这个问题,我是陌生的,如果再重复一遍,详细的解释将非常棒,对不起!
编辑 我没有得到一个错误,我只是没有得到我想要的哈。 这是我的数据框的简化版本
df <- data_frame(
id = c(500, 500, 500, 501, 501, 501, 502, 502, 502),
trial_num = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
Response = c(0, 0, 0, 1, 0, 0, 1, 1, 0))
我希望它看起来像是添加一列具有更改次数的列
change <- data_frame(change = c(0, 0, 0, 1, 1, 1, 1, 1, 1))
但是当我使用此代码时:
df <- df %>%
group_by(id) %>%
mutate(changeD = cumsum(ifelse(Response!= lag(Response) | is.na(lag(Response)), 1, 0)))
计数器不会在每个新的ID号上“重新启动”
答案 0 :(得分:1)
首先,我创建一个临时变量R2
,用一个我知道NA
不需要的值替换Response
中的Response
。然后,由于R2
没有NA
的值,所以我只看diff(R2)
。如果diff
不是0
,说明存在更改,因此sum(diff(R2) != 0)
等于更改次数。
library(dplyr)
df <- data_frame(
id = c(500, 500, 500, 501, 501, 501, 502, 502, 502),
trial_num = c(1, 2, 3, 1, 2, 3, 1, 2, 3),
Response = c(0, 0, 0, 1, 0, 0, 1, 1, 0))
df %>%
mutate(R2 = replace(Response, is.na(Response), max(Response, na.rm = T) + 1)) %>%
group_by(id) %>%
mutate(change = sum(diff(R2) != 0)) %>%
select(-R2)
# # A tibble: 9 x 4
# # Groups: id [3]
# id trial_num Response change
# <dbl> <dbl> <dbl> <int>
# 1 500 1 0 0
# 2 500 2 0 0
# 3 500 3 0 0
# 4 501 1 1 1
# 5 501 2 0 1
# 6 501 3 0 1
# 7 502 1 1 1
# 8 502 2 1 1
# 9 502 3 0 1
diff
函数计算每个元素与下一个元素之间的差。例如
diff(c(1, 2, 4, 5, 10))
# [1] 1 2 1 5
基本R版本
df$change <-
with(df, rep(tapply({r <- Response
replace(r, is.na(r), max(r, na.rm = T) + 1)}
, id
, function(x) sum(diff(x) != 0))
, lengths(split(id, id))))
答案 1 :(得分:1)
如果您有兴趣,可以直接使用data.table
:
library(data.table)
setDT(df)[, Change := max(rleid(Response) - 1), by = id][, .(Change)]
Change
1: 0
2: 0
3: 0
4: 1
5: 1
6: 1
7: 1
8: 1
9: 1
您也可以将其合并到dplyr
中:
library(data.table)
library(dplyr)
df %>% group_by(id) %>%
mutate(Change = max(rleid(Response) - 1)) %>%
ungroup() %>% select(Change)
Change
<dbl>
1 0
2 0
3 0
4 1
5 1
6 1
7 1
8 1
9 1
如果没有data.table
,类似的事情也将起作用:
library(dplyr)
df %>% group_by(id) %>% mutate(Change = Response != lag(Response),
Change = ifelse(is.na(Change), FALSE, Change),
Change = max(cumsum(Change))) %>% ungroup() %>% select(Change)
Change
<int>
1 0
2 0
3 0
4 1
5 1
6 1
7 1
8 1
9 1