首页 > 解决方案 > 将因子变量分钟:秒转换为R中的数值变量分钟.秒

问题描述

我正在为我得到的数据框而苦苦挣扎:

 game.time.total game.time.first.half game.time.second.half
1           95:09                46:04                 49:05
2           95:09                46:04                 49:05
3           95:31                46:07                 49:23
4           95:31                46:07                 49:23
5           95:39                46:08                 49:31

目前,这些列当前是因子变量(参见 str 输出)

'data.frame':   5 obs. of  3 variables:
 $ game.time.total      : Factor w/ 29 levels "100:22","100:53",..: 7 7 10 10 12
 $ game.time.first.half : Factor w/ 27 levels "45:18","46:00",..: 3 3 5 5 6
 $ game.time.second.half: Factor w/ 29 levels "48:01","48:03",..: 12 12 15 15 17

但是我希望能够使用 colmeans() 对每一列进行平均。据我了解,我需要将列转换为数字并表示为 minutes.seconds ,如下所示:

game.time.total game.time.first.half game.time.second.half
1           95.09                46.04                 49.05
2           95.09                46.04                 49.05
3           95.31                46.07                 49.23
4           95.31                46.07                 49.23
5           95.39                46.08                 49.31

我知道我可以直接输入它们,但是还有更多类似格式的列和行......有没有一种简单的方法可以做到这一点?还是我需要重新调整原始文件(.csv)的格式?

编辑:谢谢你的回答。我在原始问题中的错误是我没有提供我的实际 DF。我现在已经添加了这个和 str() 结果。

@hello_friend 这是我应用您的第二个解决方案时返回的内容

 game.time.total game.time.first.half game.time.second.half
1               7                    3                    12
2               7                    3                    12
3              10                    5                    15
4              10                    5                    15
5              12                    6                    17

提前致谢。

标签: rnumber-formatting

解决方案


你必须在这里小心。想想"89:30"和的平均值"90:30"。它们加到 180 分钟,所以平均值应该是90:00。但是,如果您将它们转换为89.30and 90.30,那么它们相加,179.60并且均值变为89.80,这甚至没有意义。

有一些软件包可以让你更轻松地处理时间,例如lubridate,如果你经常处理时间,你应该学会使用它们。但是,下面的解决方案不需要任何额外的包并且非常简单。它定义了两个小函数来在"mm:ss"格式和秒数之间进行转换。您可以安全地在几秒钟内进行求和和平均,然后转换回原始格式:

as_seconds <- function(x) sapply(strsplit(x, ":"), function(y) sum(as.numeric(y) * c(60, 1)))

as_min_sec <- function(x) paste0(x %/% 60, sprintf(":%02d", 21))

apply(DF, 2, function(x) as_min_sec(mean(as_seconds(x))))
#>       game.time.total  game.time.first.half game.time.second.half 
#>               "95:21"               "46:21"               "49:21"

如果您只想在每列中用点替换冒号,您可以这样做:

as.data.frame(lapply(DF, function(x) gsub(":", ".", x)))
#>   game.time.total game.time.first.half game.time.second.half
#> 1           95.09                46.04                 49.05
#> 2           95.09                46.04                 49.05
#> 3           95.31                46.07                 49.23
#> 4           95.31                46.07                 49.23
#> 5           95.39                46.08                 49.31


推荐阅读