在单独的列中每小时过去后获取字符列的模式? 数据

问题描述

我有一个非常大的数据集——大约有 2000 万个观测值,这是它的基本结构——

           date       time      string
  1     01/01/2020   20:00:00     A  
  2     01/01/2020   20:13:12     B
  3     01/01/2020   20:37:45     C
  4     01/01/2020   20:39:07     D 
  5     01/01/2020   20:41:29     A
  6     01/01/2020   20:46:48     E
  7     01/01/2020   21:00:00     J

我想要一个新列,也许是“mode”,它会计算“string”列中最常出现的文本字符串,但只能以每小时为间隔。所以表格最终会是这样的 -

           date       time      string      mode
  1     01/01/2020   20:00:00     A          
  2     01/01/2020   20:13:12     B
  3     01/01/2020   20:37:45     C
  4     01/01/2020   20:39:07     D 
  5     01/01/2020   20:41:29     A
  6     01/01/2020   20:46:48     E
  7     01/01/2020   21:00:00     J          A
  8     01/01/2020   21:20:12     I
  9     01/01/2020   21:38:32     I  
  10    01/01/2020   21:43:12     A
  11    01/01/2020   21:49:50     I
  12    01/01/2020   21:54:50     B
  13    01/01/2020   22:00:00     A          I
  14    01/01/2020   22:03:45     B

这样每当小时数字增加时,字符串列的模式就会被采用,然后模式测量值会在下一个小时的间隔内重置。

我对 R 很陌生,所以很遗憾我没有任何尝试或错误消息要显示。我查看了许多其他类似的主题/线程,但没有遇到任何可以帮助我找到可行解决方案的内容。当然不会要求任何人为我编写代码 - 非常感谢任何建议。

解决方法

一个选项是使用 here 中的 Mode 函数

 Mode <- function(x) {
       ux <- unique(x)
     ux[which.max(tabulate(match(x,ux)))]
}

通过 paste 对 'date'、'time' 列创建分组变量,使用 dmy_hms(来自 lubridate)将其转换为 Datetime 类,然后使用 {{1} } 将 '1 小时' 指定为 ceiling_date,通过在 'string' 列上应用 unit 创建 'mode' 列,并使用 Mode 仅在最后一行返回该值每组

case_when

-输出

library(dplyr)
library(lubridate
library(stringr)
df1 %>% 
     group_by(grp = ceiling_date(dmy_hms(str_c(date,time,sep=" ")),'1 hour')) %>% 
     mutate(mode = case_when(row_number() == n() ~ Mode(string),TRUE  ~ "")) %>%
     ungroup %>% 
     select(-grp)

数据

# A tibble: 14 x 4
#   date       time     string mode 
#   <chr>      <chr>    <chr>  <chr>
# 1 01/01/2020 20:04:01 A      ""   
# 2 01/01/2020 20:13:12 B      ""   
# 3 01/01/2020 20:37:45 C      ""   
# 4 01/01/2020 20:39:07 D      ""   
# 5 01/01/2020 20:41:29 A      ""   
# 6 01/01/2020 20:46:48 E      ""   
# 7 01/01/2020 21:00:00 J      "A"  
# 8 01/01/2020 21:20:12 I      ""   
# 9 01/01/2020 21:38:32 I      ""   
#10 01/01/2020 21:43:12 A      ""   
#11 01/01/2020 21:49:50 I      ""   
#12 01/01/2020 21:54:50 B      ""   
#13 01/01/2020 22:00:00 A      "I"  
#14 01/01/2020 22:03:45 B      "B"
,

使用 library(data.table) 我们可以做到

setDT(df1)[,hour := paste(date,sub(':.+','',time))]
df1[,n := seq(.N),by = .(hour,string)]
df1[,mode := string[which.max(n)],by=hour]