【问题标题】:Replace largest value in a row with a specific number and replace all other values in that same row based on that largest value using dplyr用特定数字替换一行中的最大值,并使用 dplyr 根据该最大值替换同一行中的所有其他值
【发布时间】:2018-11-23 22:45:06
【问题描述】:

我有一个由问卷数据组成的数据框,每一列代表问卷中的一个项目。

数据如下所示:

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) 

使用上面的输出,我想继续我的 dplyr 管道,用值 1 替换该行中的最大值,并将所有其他值替换为最大值的百分比。

我有以下内容:

我想要的输出是:

我的两个问题是:

1)。是否有适用于列的 group_by 等效项?如果是这样,我就不用这么笨拙地使用slice了。

2)。有人可以帮我完成我想要的输出的 dplyr 管道吗?我不知道如何从那里开始。

谢谢!

【问题讨论】:

  • 如果你把它存储在其他对象比如df1,你基本上需要df1/apply(df1, 1, max)
  • 为什么 Q3b 66.67 是您想要的输出?如果那个 nog 是 40(即 5 个值中有 2 个是 -2)

标签: r dplyr


【解决方案1】:

处理长格式数据总是比较可取的。但是,如果 3000+ 列在 data.frame 中并且 OP 想要处理宽格式本身的数据,那么一种解决方案可以是使用 dplyr::summarise_all 而不是 OP 使用的 mutate_all

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

【讨论】:

  • 谢谢,已对您的回复表示赞同。但是,正确的 Q3b 响应应该是 66.66 而不是 40。
  • @DTYK 谢谢。我已经编辑了答案。使用0 检查的列名应该被删除。我认为您需要的只是!is.na(.) 检查。
  • 感谢您的编辑。我早些时候意识到您和@Wimpel 的响应都检查了 NA 和 0。我需要的是检查空白 ("") 和 NA。在我的工作中,我将改为检查空白和 NA。干杯!
  • @DTYK 在数字列上,您不需要检查"""" 自动强制转换为 NA
【解决方案2】:

首先,以长格式收集数据,然后过滤 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 的结果与您想要的输出不同。您确定所需的输出正确吗?

【讨论】:

  • 谢谢,我想要的输出是错误的。给我一点时间来改变它。
  • 这里的教训是 dplyr 只有在数据整齐时才真正发挥作用,即您不能跨列传播问题分数。
  • @Wimpel 我已经做出了改变。请更新您的答案。谢谢,非常感谢!
  • 没关系!立即阅读gather 并从那里开始。
  • 是的,gather 并制作一个包含时间、项目和分数列的 data.frame。
猜你喜欢
  • 2018-02-16
  • 1970-01-01
  • 2018-06-06
  • 2021-07-18
  • 1970-01-01
  • 2021-07-28
  • 1970-01-01
  • 1970-01-01
  • 2023-04-09
相关资源
最近更新 更多