数据争用-数据分布在三行中-DPLyr

时间:2018-09-19 17:07:16

标签: r dplyr dataset

我有一个非常不整洁的数据集

A tibble: 200000 x 2
ChatData  
 <chr>                  
 1 Sep 30, 2018 7:12pm       
 2 Person A
 3 Hello                        
 4 Sep 30, 2018 7:11pm        
 5 Person B           
 6 Hello there                 
 7 Sep 30, 2018 7:10pm        
 8 Person A
...

您会看到日期,人员姓名,评论和重复内容。

我正在研究这个问题,并且有一个非常复杂的方法,可以根据名称等添加一个分数列。...

我想把它变成这样的东西

Person A , Person B
Hello      NA
NA         Hello there
how's you, NA
...

(将日期作为行名或第三列的日期会很好,但对于问题而言并非必不可少)

理想情况下,我正在寻找dplyr / tidyverse解决方案 我正在处理大量数据,因此循环等方面的工作不会太慢。

要使用的原始数据:

structure(list(ChatData = c("Sep 30, 2018 7:12pm", "Person A", "Hello", "Sep 30, 2018 7:11pm", "Person B", "Hello there")), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))

如果有人想知道我正在分析Facebook Messenger数据,这就是您下载它时使用的表格。

谢谢。

3 个答案:

答案 0 :(得分:2)

在这种情况下,您的起始数据集只有一列(又称功能)。但是在这种情况下,每种消息在此处编码的数据类型有三种:时间戳记,人员标签和消息。将它们转换成表格,其中每个消息都在其自己的行中,并且每一列代表每个观察值的不同方面,即长或整洁的格式:https://cran.r-project.org/web/packages/tidyr/vignettes/tidy-data.html

在下面的方法中,用户首先定义在数据集中重复哪些功能。我在这里称它们为“标题”,因为我正在朝着这些列标题的表工作。然后,脚本将该信息添加到数据中,并将单列数据转换为整齐的格式,每条消息一行,每列每一条消息的一个方面。

您请求的输出是此输出的一个很小的变化,在下面的最后一行:%>% spread(person, msg)中进行了处理,该输出将Person A和Person b的数据分成了单独的列。

library(tidyverse)

header_names <- c("timestamp", "person", "msg")

rows_per <- length(header_names)
data_length <- length(data$ChatData) / rows_per
data2 <- data %>%
  mutate(msg_number = rep(1:(nrow(data)/rows_per), each=rows_per),
         # This line repeats the header_names sequence for each msg
         header = rep(header_names, data_length)) %>%
  spread(header, ChatData) %>%
  mutate(timestamp = lubridate::mdy_hm(timestamp)) %>%
  spread(person, msg)


head(data2)
# A tibble: 2 x 4
  msg_number timestamp           `Person A` `Person B` 
       <int> <dttm>              <chr>      <chr>      
1          1 2018-09-30 19:12:00 Hello      NA         
2          2 2018-09-30 19:11:00 NA         Hello there

答案 1 :(得分:1)

基本上,您只有一个要转换为3列数据的字符向量。frame

另一种选择是只使用matrix并指定ncol=3byrow=TRUE

# your sample data
d <- structure(list(ChatData = c("Sep 30, 2018 7:12pm", "Person A", "Hello", "Sep 30, 2018 7:11pm", "Person B", "Hello there")), row.names = c(NA, -6L), class = c("tbl_df", "tbl", "data.frame"))

matrix( d$ChatData, ncol=3, byrow=TRUE,
        dimnames=list( NULL, c("date_time", "person", "message")) )

结果是一个字符矩阵:

     date_time             person     message      
[1,] "Sep 30, 2018 7:12pm" "Person A" "Hello"      
[2,] "Sep 30, 2018 7:11pm" "Person B" "Hello there"

但是您可以将其包装在as.data.frame()中以转换为data.frame,然后根据需要继续使用dplyr从那里进行工作。

将其放在一起以得到一个完整的解决方案:

它变成了一个很好的,简短易读的代码IMO:

library(dplyr)
library(lubridate)

result_df <- 
  matrix( d$ChatData, ncol=3, byrow=TRUE, 
          dimnames=list(NULL, c("date_time", "person", "message")) ) %>% 
  as.data.frame() %>% 
  mutate(date_time=lubridate::mdy_hm(date_time))

答案 2 :(得分:0)

这是一种方法:

data %>% group_by(msg_number = rep(1:(nrow(data)/3), each=3)) %>% 
  summarize(msg_data = list(ChatData)) %>% as.data.frame

  msg_number                                   msg_data
1          1       Sep 30, 2018 7:12pm, Person A, Hello
2          2 Sep 30, 2018 7:11pm, Person B, Hello there

这将为每条消息编号,并将数据放入列列表中。