如何仅使用目标列的一个值来使用 Spread 函数?

How to use the Spread function using only one value of the target column?

我们有以下数据框 a,内容如下:


 > a
    google_prod      Value
1     categoria          ML
2        google         120
3       youtube          24
4     categoria          AO
5        google           2
6       youtube           0
7     categoria          ML
8        google          27
9       youtube           0
10    categoria          AO
11       google           5
12      youtube           0

我们想得到这个:

    categoria google_prod    Value
1          ML   google        120
2          ML   youtube        24
3          AO   google          2
4          AO   youtube         0      
5          ML   google         27
6          ML   youtube         0    
7          AO   google          5
8          AO    youtube        0    

换句话说,执行 Spread 或类似函数的一种应用,其中仅从 google_prod 列中获取一个值来应用它,在这种情况下它将是 'categoria'值。

library(tidyverse)

# getting the data
category <- rep(c("categoria",  "google",   "youtube"), 4)
value <- c("ML", "120", "24",   "AO",   "2",    "0",    "ML",   "27",   "0",    "AO",   "5",    "0")

df <- tibble(category, value)

df %>%
  mutate(helper = rep(1:(nrow(df)/3), each = 3)) %>%
  pivot_wider(names_from = category, values_from = value) %>%
  select(-helper) %>%
  pivot_longer(names_to = "google_prod",  values_to = "values", -1)

# # A tibble: 8 x 3
# categoria google_prod values
# <chr>     <chr>       <chr> 
# 1 ML        google      120   
# 2 ML        youtube     24    
# 3 AO        google      2     
# 4 AO        youtube     0     
# 5 ML        google      27    
# 6 ML        youtube     0     
# 7 AO        google      5 
# 8 AO        youtube     0 

一个想法如下。据我所见,您的目标值是 Value 中包含两个大写字母的值。我搜索了他们在哪里使用 grep() 并获得了索引。使用此信息,我使用 findIntervals() 创建了一个组变量。对于每个组,我汇总了数据;我提取大写字母值并将其放入 categoria。以类似的方式,我又创建了两列。它们是列表。所以我最后用了unnest()来得到输出。

library(tidyverse)

ind <- grep(x = mydf$Value, pattern = "[A-Z]+")

group_by(mydf, group = findInterval(x = 1:n(), vec = ind)) %>%
summarize(categoria = Value[google_prod == "categoria"],
          Google_prod = list(google_prod[google_prod != "categoria"]),
          Value = list(Value[google_prod != "categoria"])) %>% 
unnest(cols = Google_prod:Value)

  group categoria Google_prod Value
  <int> <chr>     <chr>       <chr>
1     1 ML        google      120  
2     1 ML        youtube     24   
3     2 AO        google      2    
4     2 AO        youtube     0    
5     3 ML        google      27   
6     3 ML        youtube     0    
7     4 AO        google      5    
8     4 AO        youtube     0    

数据

mydf <- structure(list(google_prod = c("categoria", "google", "youtube", 
"categoria", "google", "youtube", "categoria", "google", "youtube", 
"categoria", "google", "youtube"), Value = c("ML", "120", "24", 
"AO", "2", "0", "ML", "27", "0", "AO", "5", "0")), class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"))

这是另一个想法,使用 cumsum 创建一个组并提取 first 元素

library(dplyr)
mydf %>% 
   group_by(grp = cumsum(google_prod == 'categoria')) %>% 
   mutate(categoria = first(Value)) %>% 
   slice(-1) %>% 
   ungroup %>%
   select(-grp) %>%
   type.convert(as.is = TRUE)
# A tibble: 8 x 3
#  google_prod Value categoria
#  <chr>       <int> <chr>    
#1 google        120 ML       
#2 youtube        24 ML       
#3 google          2 AO       
#4 youtube         0 AO       
#5 google         27 ML       
#6 youtube         0 ML       
#7 google          5 AO       
#8 youtube         0 AO       

数据

mydf <- structure(list(google_prod = c("categoria", "google", "youtube", 
"categoria", "google", "youtube", "categoria", "google", "youtube", 
"categoria", "google", "youtube"), Value = c("ML", "120", "24", 
"AO", "2", "0", "ML", "27", "0", "AO", "5", "0")),
 class = "data.frame", row.names = c("1", 
"2", "3", "4", "5", "6", "7", "8", "9", "10", "11", "12"))