0

我有一个包含两列的数据框:公司名称和长格式标签。每家公司都有不同数量的标签,大约有 80k 行:

Company   Tags

Company A Tag A
Company A Tag B
Company A Tag C
Company B Tag A
Company B Tag B
Company B Tag C
Company B Tag D
Company B Tag E
Company B Tag F
Company C Tag A
Company C Tag B
Company C Tag C
Company C Tag D

我想把它变成一个宽格式:

Company   Tag 1   Tag 2   Tag 3   Tag 4    Tag 5   Tag 6 

Company A Tag A   Tag B   Tag C
Company B Tag A   Tag B   Tag C   Tag D    Tag E   Tag F
Company C Tag A   Tag B   Tag C   Tag D

Spread 不起作用,因为它希望我将一列传递给它,该列将成为宽格式的列名,但我没有。所以我不能按原样传播它。看来我有两个选择:

  1. 使用附加到每个公司的数字创建另一个列,以用作宽格式的列名。但我不知道如何在每家公司的代码中做到这一点。

  2. 找到一个包,它的功能可以比 Spread 更灵活地转换数据帧。Splitstackshape 在将数据帧转换为格式方面做得很好,但反之则不行。

任何意见,将不胜感激!另外,我很想学习如何更好地格式化这些表格,而不必做一堆手动制表符/间距。

4

4 回答 4

4

您的选择1是要走的路;但是仅考虑您提供的信息,无法判断值应该转到哪一列(是Tag <num>根据顺序创建的列还是原始列的Tags?)。但是,如果我们假设新列是根据排序创建的,那么您可以只group_by使用Companyvalue 和 use来创建一个变量,以在ing 为宽格式row_number()后用作所需的列名。spread

library(tidyverse)

df <- read.table(
  header = T,
  sep = ",",
  text = '
Company,Tags
Company A,Tag A
Company A,Tag B
Company A,Tag C
Company B,Tag A
Company B,Tag B
Company B,Tag C
Company B,Tag D
Company B,Tag E
Company B,Tag F
Company C,Tag A
Company C,Tag B
Company C,Tag C
Company C,Tag D')

df %>% 
  group_by(Company) %>% 
  mutate(tag_column = str_c("Tag", row_number())) %>% 
  spread(tag_column, Tags)
#> # A tibble: 3 x 7
#> # Groups:   Company [3]
#>   Company   Tag1  Tag2  Tag3  Tag4  Tag5  Tag6 
#>   <fct>     <fct> <fct> <fct> <fct> <fct> <fct>
#> 1 Company A Tag A Tag B Tag C <NA>  <NA>  <NA> 
#> 2 Company B Tag A Tag B Tag C Tag D Tag E Tag F
#> 3 Company C Tag A Tag B Tag C Tag D <NA>  <NA>

reprex 包(v0.2.0)于 2018 年 2 月 18 日创建。

于 2018-02-18T19:53:11.423 回答
2

对于您的示例,您可以考虑仅使用table,这会产生类似的结果

table(df)
#            Tags
# Company     Tag A Tag B Tag C Tag D Tag E Tag F
# Company A     1     1     1     0     0     0
# Company B     1     1     1     1     1     1
# Company C     1     1     1     1     0     0

如果您现在希望每个值代表列名,您可以运行

tb <- table(df)
z <- which(tb==1, arr.ind=T)
tb[z]<-colnames(tb)[z[,2]]
tb
 #         Tags
 # Company    Tag A Tag B Tag C Tag D Tag E Tag F
 #  Company A Tag A Tag B Tag C 0     0     0    
 #  Company B Tag A Tag B Tag C Tag D Tag E Tag F
 #  Company C Tag A Tag B Tag C Tag D 0     0    
于 2018-02-18T20:01:30.037 回答
2

另一个更简单的选择可能是使用dcastfrom reshape2。如果 OP 有兴趣在转换后重命名列,那么它也会更容易。一个人只需要创建一个向量来为列具有不同的名称Tag A即可Tag F

library(reshape2)
> dcast(df, Company ~ Tags)
#    Company Tag A Tag B Tag C Tag D Tag E Tag F
#1 Company A Tag A Tag B Tag C  <NA>  <NA>  <NA>
#2 Company B Tag A Tag B Tag C Tag D Tag E Tag F
#3 Company C Tag A Tag B Tag C Tag D  <NA>  <NA>


# Data
df <- read.table( text = "Company   Tags
'Company A' 'Tag A'
'Company A' 'Tag B'
'Company A' 'Tag C'
'Company B' 'Tag A'
'Company B' 'Tag B'
'Company B' 'Tag C'
'Company B' 'Tag D'
'Company B' 'Tag E'
'Company B' 'Tag F'
'Company C' 'Tag A'
'Company C' 'Tag B'
'Company C' 'Tag C'
'Company C' 'Tag D'", header = T, stringsAsFactor = F)
于 2018-02-18T20:01:53.617 回答
0

这个怎么样?

data <- read.table(text="Company Tag
                   CompanyA TagA
                   CompanyA TagB
                   CompanyA TagC
                   CompanyB TagA
                   CompanyB TagB
                   CompanyB TagC
                   CompanyB TagD
                   CompanyB TagE
                   CompanyB TagF
                   CompanyC TagA
                   CompanyC TagB
                   CompanyC TagC
                   CompanyC TagD
                   ",header=TRUE)

library(reshape2)
d = dcast(data,Company~Tag,value.var = "Tag")
names(d)[grep("^Tag", names(d))] = paste("Tag", 1:(ncol(d)-1), sep = "" )

输出 :

   Company Tag1 Tag2 Tag3 Tag4 Tag5 Tag6
1 CompanyA TagA TagB TagC <NA> <NA> <NA>
2 CompanyB TagA TagB TagC TagD TagE TagF
3 CompanyC TagA TagB TagC TagD <NA> <NA>
于 2018-02-18T20:04:38.313 回答