我有一个由问卷数据组成的数据框,每列代表调查问卷中的一个项目。
数据类似于以下内容:
df <- data.frame(Q1a = c(3, 2, 5, 6, 9), Q1b = c(2, 0, -2, 0, 9), Q2a = c(1, 4, 7, 2, 4),
Q2b = c(0, 0, -1, 0, 0), Q3a = c(5, 7, 2, 0, 9), Q3b = c(-2, -2, 3, 6, 9),
Q4a = c(5, 2, 4, 9, 0), Q4b = c(0, 0, -2, -2, -2))
每个问卷项目有两个版本(a,b)。我想选择所有带有“b”后缀的项目。对于那些带有“b”后缀的列,我想将值为-2的单元格数除以该特定列中非空白和非NA的总数。我想对所有列重复上述过程。我设法用以下代码完成它:
test <- df %>%
select(ends_with("b")) %>%
mutate_all(funs(round(sum(. == -2)/sum(. != "" | . != NA)*100,
digits = 2)))
由于没有“group_by”等效,我知道它适用于列而不是行,所以在上面输出的每一行中重复相同的结果。我已设法使用以下代码删除包含slice
重复信息的行:
test <- df %>%
select(ends_with("b")) %>%
mutate_all(funs(round(sum(. == -2)/sum(. != "" | . != NA)*100,
digits = 2))) %>%
slice(1)
通过上面的输出,我希望通过将值中的最大值替换为值1来继续我的dplyr管道,并将所有其他值替换为最大值的百分比。
我所拥有的是以下内容:
我想要的输出是:
我的两个问题是:
1)。是否有一个group_by等效的列适用于列?如果是这样,我就不必以这种笨拙的方式使用slice
。
2)。有人可以帮我完成我的dplyr管道到我想要的输出吗?我不知道如何从那里开始。
谢谢!
答案 0 :(得分:3)
首先,以长格式收集数据,然后过滤NA和0值。 你可以分组和总结。
library(tidyverse)
df %>%
select(ends_with("b")) %>%
gather() %>%
filter( !value == 0 | is.na( value ) ) %>%
group_by( key ) %>%
summarise( output = round( 100 * length( value[value == -2] ) / n(), digits = 1 ) )
# # A tibble: 4 x 2
# key output
# <chr> <dbl>
# 1 Q1b 33.3
# 2 Q2b 0
# 3 Q3b 40
# 4 Q4b 100
请注意,Q3b的结果与您想要的输出不同。您确定所需的输出是否正确?
答案 1 :(得分:1)
总是更喜欢以长格式处理数据。但是,如果data.frame中有3000+
列,并且OP希望以宽格式本身处理数据,那么一个解决方案可以是使用dplyr::summarise_all
而不是mutate_all
来使用OP:
library(dplyr)
df %>%
select(ends_with("b")) %>%
summarise_all(funs(round(sum(. == -2)/sum(!is.na(.))*100,
digits = 2))) %>%
mutate(maxV = max(.)) %>%
mutate_all(funs(100*./maxV)) %>%
select(-maxV)
# Q1b Q2b Q3b Q4b
# 1 33.33 0 66.67 100