R语言 如何创建一个新列,并根据两列中各行的条件为其赋值?

myzjeezk  于 2023-04-18  发布在  其他
关注(0)|答案(2)|浏览(189)

我是R的初学者,正在尝试创建一个新列,该列的值由两列中的行的值确定。
我的 Dataframe 看起来像这样:
df <- data.frame(subjectid = c(1,1,1,1,1,2,2,2,2,2,3,3,3,3,3), subj_day = c("1_1","1_1","1_1","1_2","1_2","2_1","2_1","2_1","2_2","2_2","3_1","3_1","3_1","3_2","3_2"), done_meditation = c(0,0,1,1,1,0,1,1,0,0,1,1,1,1,1))

> df
   subjectid subj_day done_meditation
1          1      1_1               0
2          1      1_1               0
3          1      1_1               1
4          1      1_2               1
5          1      1_2               1
6          2      2_1               0
7          2      2_1               1
8          2      2_1               1
9          2      2_2               0
10         2      2_2               0
11         3      3_1               1
12         3      3_1               1
13         3      3_1               1
14         3      3_2               1
15         3      3_2               1

这些数据来自一个多天的研究,参与者每天提供多个回答,每行反映一个回答。
subj_day列显示该行中反映的响应时该参与者的参与者编号和研究日期。
'done_meditation'中的值指的是参与者在做出响应时是否在当天完成了冥想。如果在完成冥想后提供了响应,则done_meditation = 1。因此,如果参与者在当天的任何响应之前完成了冥想,则当天所有的done_meditation行都将= 1。
然而,如果他们在完成冥想之前提供一些响应,而在完成冥想之后提供一些响应,则只有一些done_meditation行将= 1。
我需要创建一个列,提供参与者在整个研究中完成的冥想次数。
因此,新的 Dataframe 可能看起来像这样:

> df
   subjectid subj_day done_meditation total_meditations
1          1      1_1               0     2
2          1      1_1               0     2
3          1      1_1               1     2
4          1      1_2               1     2
5          1      1_2               1     2
6          2      2_1               0     1
7          2      2_1               1     1
8          2      2_1               1     1
9          2      2_2               0     1
10         2      2_2               0     1
11         3      3_1               1     2
12         3      3_1               1     2
13         3      3_1               1     2
14         3      3_2               1     2
15         3      3_2               1     2

因为参与者2仅在2个研究日中的1天完成了冥想,所以他们在每一行中获得1分。
因为参与者1和3在研究的两天内完成了冥想,所以他们在每一行中获得2分。
知道实际的研究是7天的可能是有用的,所以参与者的total_meditations得分最高可达7。
我试着写了几个循环,但没有成功,也试着在dplyr中使用group_by和mutate函数,但没有成功。
非常感谢提前任何帮助!

**更新:**我想我已经找到了一个有效的解决方案。下面的内容似乎可以完成这项工作。如果有人有更优雅的解决方案,仍然欢迎任何新的建议:)

df2 <- df %>% group_by(subjectid, subj_day) %>%
  summarise(meditationCount = sum(done_meditation)) %>%
  mutate(meditationCount = ifelse(meditationCount >= 1, 1, 0)) %>%
  group_by(subjectid) %>%
  summarise(total_meditations = sum(meditationCount))
 
merged.df <- merge(df,df2, by = "subjectid")
gdx19jrr

gdx19jrr1#

好代码在构造你自己的答案!一些小建议压缩代码:

  • 您可以使用max来获得1或0的依赖日,而不是sum/ifelse
  • 您可以使用.groups = "drop_last"summarise为您删除subj_day组,因此无需第二次调用group_by
  • 连接可以在管道中完成,因此不需要新创建的 Dataframe (下面的示例使用基本R管道,但magrittr%>%管道也可以工作)
df |> 
  group_by(subjectid, subj_day) |> 
  summarise(mediated = max(done_meditation), .groups = "drop_last") |> 
  summarise(total_meditations = sum(mediated)) |> 
  left_join(df, y = _, by = "subjectid")
    # Or use `%>% left_join(df, y = ., ...)` with magrittr pipe

#>    subjectid subj_day done_meditation total_meditations
#> 1          1      1_1               0                 2
#> 2          1      1_1               0                 2
#> 3          1      1_1               1                 2
#> 4          1      1_2               1                 2
#> 5          1      1_2               1                 2
#> 6          2      2_1               0                 1
#> 7          2      2_1               1                 1
#> 8          2      2_1               1                 1
#> 9          2      2_2               0                 1
#> 10         2      2_2               0                 1
#> 11         3      3_1               1                 2
#> 12         3      3_1               1                 2
#> 13         3      3_1               1                 2
#> 14         3      3_2               1                 2
#> 15         3      3_2               1                 2

P.S.在SO you are allowed to answer your own question上,所以如果你对自己的解决方案感到满意,请将其作为答案发布,你可以接受它,给予自己应得的荣誉!

h22fl7wq

h22fl7wq2#

根据你自己和安迪的回答,我想补充另一个建议:
如果max()的结果用每组(subj_day)的响应数n()进行了归一化,则可以使用mutate()而不是summarise()。然后不再需要left_join()

df %>% mutate(total_meditations = max(done_meditation)/n(), .by = subj_day) %>%  
  mutate(total_meditations = sum(total_meditations), .by = subjectid)

相关问题