【问题标题】:R / dyplr: Transforming two rows into two columnsR / dplyr:将两行转换为两列
【发布时间】:2018-04-27 08:18:49
【问题描述】:

我在 R 中有一个如下所示的数据框:

Word    Base    Number  Type
-       -       -       -
shoe    shoe    4834    singular
shoes   shoe    49955   plural
toy     toy     75465   singular
toys    toy     23556   plural
key     key     39485   singular
keys    key     6546    plural
jazz    jazz    58765   plural

我想改造它,使它看起来像这样:

Word_Sg Word_Pl Base    Num_Singular    Num_Plural
--      --      --      --              --
shoe    shoes   shoe    4834            49955
toy     toys    toy     75465           23556
key     keys    key     39485           6546
NA      jazz    jazz    NA              58765

因此,我不想为单数和复数的值设置两行,而是希望有两个列,一个带有单数的数字,一个带有复数的数字。

我使用dplyr::summarize 尝试了一些事情,但到目前为止,没有任何成功。这是我到目前为止提出的代码:

dataframe1 <- dataframe %>% 
      mutate(Num_Singular = case_when(Type == "singular" ~ Number)) %>%
      mutate(Num_Plural = case_when(Type == "plural" ~ Number)) %>%
      dplyr::select(Word, Base, Num_Singular, Num_Plural) %>%
      group_by(Base) %>%
      dplyr::summarize(Num_Singular = paste(na.omit(Num_Singular)),
                       Num_Plural = paste(na.omit(Num_Plural))

但是,它给了我这个错误:

Error in summarise_impl(.data, dots) : 
  Column `Num_Singular` must be length 1 (a summary value), not 2)

我认为问题可能在于有些行不一定有单数和复数,但只有一个(例如“jazz”)。大多数行都有。

那么我如何在 R 或 dplyr 中做到这一点?

【问题讨论】:

  • @akraf 也许,尽管该解决方案(gatherunitespread)依赖于具有相似类的列;在本例中,这样做会在收集时将数字转换为 character

标签: r dataframe dplyr tidyr tidyverse


【解决方案1】:

如果你先看前几列::

select(dat, Base, Word, Type)[1:2,]
#   Base  Word     Type
# 1 shoe  shoe singular
# 2 shoe shoes   plural

从这里开始,考虑它只是将其分散到单数/复数列中,有效地从“高”到“宽”。 (如果Type 中有两个以上的类别会更明显。)

select(dat, Base, Word, Type) %>%
    spread(Type, Word) %>%
    rename(Word_Pl=plural, Word_Sg=singular)
#   Base Word_Pl Word_Sg
# 1 jazz    jazz    <NA>
# 2  key    keys     key
# 3 shoe   shoes    shoe
# 4  toy    toys     toy

您也可以轻松地对Number 重复此操作。从那里开始,只需根据键列合并/加入它们,Base

full_join(
  select(dat, Base, Word, Type) %>%
    spread(Type, Word) %>%
    rename(Word_Pl=plural, Word_Sg=singular),
  select(dat, Base, Number, Type) %>%
    spread(Type, Number) %>%
    rename(Num_Pl=plural, Num_Sg=singular),
  by = "Base"
)
#   Base Word_Pl Word_Sg Num_Pl Num_Sg
# 1 jazz    jazz    <NA>  58765     NA
# 2  key    keys     key   6546  39485
# 3 shoe   shoes    shoe  49955   4834
# 4  toy    toys     toy  23556  75465

消耗性数据:

library(dplyr)
library(tidyr)
dat <- read.table(text='Word    Base    Number  Type
shoe    shoe    4834    singular
shoes   shoe    49955   plural
toy     toy     75465   singular
toys    toy     23556   plural
key     key     39485   singular
keys    key     6546    plural
jazz    jazz    58765   plural', header=TRUE, stringsAsFactors=FALSE)

【讨论】:

    【解决方案2】:

    tidyr 的新 pivot_wider() 函数让这一切变得简单......

    library(dplyr)
    library(tidyr)
    
    dat <- read.table(header = T, stringsAsFactors = F, text='
    Word    Base    Number  Type
    shoe    shoe    4834    singular
    shoes   shoe    49955   plural
    toy     toy     75465   singular
    toys    toy     23556   plural
    key     key     39485   singular
    keys    key     6546    plural
    jazz    jazz    58765   plural')
    
    dat %>% 
      pivot_wider(id_cols = Base, names_from = Type, values_from = c(Word, Number))
    
    # # A tibble: 4 x 5
    #   Base  Word_singular Word_plural Number_singular Number_plural
    #   <chr> <chr>         <chr>                 <int>         <int>
    # 1 shoe  shoe          shoes                  4834         49955
    # 2 toy   toy           toys                  75465         23556
    # 3 key   key           keys                  39485          6546
    # 4 jazz  NA            jazz                     NA         58765
    

    【讨论】:

      【解决方案3】:

      核心思想是通过它的类型以及是单词还是数字来识别每个数据点......然后很容易传播到您想要的格式。 (我不会费心重命名变量或专门对它们进行排序以匹配您的预期输出,因为这很容易做到,而且不是问题的一部分)

      library(dplyr)
      library(tidyr)
      
      dat <- read.table(header = T, stringsAsFactors = F, text='
      Word    Base    Number  Type
      shoe    shoe    4834    singular
      shoes   shoe    49955   plural
      toy     toy     75465   singular
      toys    toy     23556   plural
      key     key     39485   singular
      keys    key     6546    plural
      jazz    jazz    58765   plural')
      
      dat %>% 
        gather(variable, value, Word, Number) %>%
        unite(Type, variable, Type) %>%
        spread(Type, value, convert = T) %>% 
        as_tibble()
      
      # # A tibble: 4 x 5
      #   Base  Number_plural Number_singular Word_plural Word_singular
      #   <chr>         <int>           <int> <chr>       <chr>        
      # 1 jazz          58765              NA jazz        NA           
      # 2 key            6546           39485 keys        key          
      # 3 shoe          49955            4834 shoes       shoe         
      # 4 toy           23556           75465 toys        toy  
      

      【讨论】:

      • 如果在末尾添加%&gt;% str(),您会注意到在将numeric 列与character 列中的数据组合后,数字将转换为character。这可能是一个可接受的步骤(重新转换回integer),但对于numeric(浮点数),我建议数字有所不同。因此,这种方法(如@akraf 的第一条评论中所建议的)仅适用于所有“数据”列(相对于“类别”列)的类型相同或足够相同的情况。
      【解决方案4】:

      您可以通过Base 加入数据的pluralsingular 子集,然后删除Type 列并对其他列重新排序...

      full_join(filter(dat, Type == "plural"), 
                filter(dat, Type == "singular"),
                by = "Base", 
                suffix = c("_Pl", "_Sg")) %>% 
        select(Word_Sg, Word_Pl, Base, Number_Sg, Number_Pl)
      
      #   Word_Sg Word_Pl Base Number_Sg Number_Pl
      # 1    shoe   shoes shoe      4834     49955
      # 2     toy    toys  toy     75465     23556
      # 3     key    keys  key     39485      6546
      # 4    <NA>    jazz jazz        NA     58765
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-01-28
        • 2021-07-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-04-25
        相关资源
        最近更新 更多