【问题标题】:Pivoting 4x4 into 16x1将 4x4 旋转为 16x1
【发布时间】:2023-01-29 22:13:57
【问题描述】:

我一直在尝试找到一种方法将具有 4 列的数据集转换为一行。我将举例说明我的意思。

我希望将此数据集转换为...

当我尝试在 Excel 中使用 pivot 函数时,我的问题来了,它不允许我将数据转换为一行。我还在 Excel 中尝试了许多其他功能,但运气不佳。

目前,数据在 Excel 中,在那里操作可能更容易。但是,如果 Excel 根本没有该功能,那么 R 也可以正常工作。感谢您的帮助。

【问题讨论】:

    标签: r excel pivot


    【解决方案1】:

    一个技巧是先将数据重塑为长格式,然后在使用 tidyverse 系列的 tidyr 进行几次操作后将数据重塑为宽格式: 我首先将您的示例数据存储在名为“df”的 R 中:

      df
      ID sit1 sit2 sit3 sit4
      1   -1    2    0    0
      2   -3   -2   -3   -2
      3   -1    2    0    4
      4   -1    2    0    0
    

    将 df 转换为长格式,将所有坐柱合并为一个 名为“坐”的单列:

    dflong<-pivot_longer(df[,-c(1)],cols = everything(),names_to = 
                         'sit',values_to = 'values')
    

    使 sit 的值独一无二:

    dflong$sit<-paste(dflong$sit,rep(c(1:4),each=4),sep = '_')
    

    然后将数据重塑为宽格式,将每个坐值分配到一列中

    dfwide<-pivot_wider(dflong,names_from = 'sit',values_from = 'values')
    

    希望这会有所帮助。

    【讨论】:

      【解决方案2】:
      df <- tibble::tribble(
        ~ID, ~sit1, ~sit2, ~sit3, ~sit4,
        1,   -1,    2,    0,    0,
        2,   -3,   -2,   -3,   -2,
        3,   -1,    2,    0,    4,
        4,   -1,    2,    0,    0 
      )
      
      library(tidyr)
      
      col_order <- expand.grid(names(df)[-1], df$ID) |> 
        unite("Var", c(Var1, Var2))
      
      df |> 
        pivot_wider(names_from = ID, values_from = starts_with("sit")) |> 
        dplyr::relocate(col_order$Var)
      
      # A tibble: 1 × 16
        sit1_1 sit2_1 sit3_1 sit4_1 sit1_2 sit2_2 sit3_2 sit4_2 sit1_3 sit2_3 sit3_3
         <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
      1     -1      2      0      0     -3     -2     -3     -2     -1      2      0
      # … with 5 more variables: sit4_3 <dbl>, sit1_4 <dbl>, sit2_4 <dbl>, sit3_4 <dbl>,
      #   sit4_4 <dbl>
      

      【讨论】:

      • OP 要求按行扩展。 (列扩展对于 unlist 来说是微不足道的。)
      【解决方案3】:

      使用最新版本的 Excel 365 中的 Excel 函数应该可以解决这个问题。

      但它也可以使用 Windows Excel 2010+ 和 Excel 365(Windows 或 Mac)中提供的 Power Query 来完成

      使用 Power Query

      • 选择数据表中的一些单元格
      • Data =&gt; Get&amp;Transform =&gt; from Table/Rangefrom within sheet
      • 当 PQ 编辑器打开时:Home =&gt; Advanced Editor
      • 记下表格名称在 2 号线
      • 粘贴下面的 M 代码代替您看到的内容
      • 将第 2 行中的表名称更改回最初生成的名称。
      • 阅读cmets并探索Applied Steps以了解算法

      我提供了两种不同的方法来做到这一点。你应该测试看看哪个对你的实际数据更有效

      M 代码版本 1

      let
          Source = Excel.CurrentWorkbook(){[Name="myTable"]}[Content],
          colNames = Table.ColumnNames(Source),
      
      //set data types
          #"Changed Type" = Table.TransformColumnTypes(Source,
              List.Transform(colNames, each {_, Int64.Type})),
      
      x = List.Transform(List.RemoveFirstN(colNames,1),(cn)=>{cn, cn & Text.From(1)}),
      
      //put each row in wide format
          tableData = Table.RemoveColumns(#"Changed Type", colNames{0}),
          wideList = List.Generate(
              ()=>[r= tableData{0}, idx=0],
              each [idx] < Table.RowCount(tableData),
              each [r=tableData{[idx]+1}, idx = [idx]+1],
              each   Record.RenameFields([r], List.Transform(List.RemoveFirstN(colNames,1), (cn)=>{cn, cn & "_" & Text.From([idx]+1)}))),
          wideTable = Table.FromRecords({Record.Combine(wideList)}),
          #"Wide Table Typed Columns" = Table.TransformColumnTypes(wideTable, List.Transform(Table.ColumnNames(wideTable), each {_, Int64.Type}))
      in
          #"Wide Table Typed Columns"
      

      M 代码版本 2

      let
          Source = Excel.CurrentWorkbook(){[Name="myTable"]}[Content],
          
      //set data types
          colNames = Table.ColumnNames(Source),
          #"Changed Type" = Table.TransformColumnTypes(Source,
              List.Transform(colNames, each {_, Int64.Type})),
      
      //Unpivot to => three columns
          #"Unpivoted Other Columns" = Table.UnpivotOtherColumns(#"Changed Type", {"ID"}, "Attribute", "Value"),
      
      //Group by ID
      //then Pivot and rename the columns
          #"Grouped Rows" = Table.Group(#"Unpivoted Other Columns", {"ID"}, {
              {"pivot", each Table.ToRecords(Table.RemoveColumns( 
                  Table.RenameColumns(
                      Table.Pivot(_, List.Distinct([Attribute]), "Attribute","Value"),
                      List.Transform(List.Distinct([Attribute]), (cn)=>{cn, cn & Number.ToText([ID]{0},"_0")})),
                          "ID"))}
              }),
      
          wide = Table.FromRecords({Record.Combine(List.Combine(#"Grouped Rows"[pivot]))}),
      
      //set data types
          typedWide = Table.TransformColumnTypes(wide, List.Transform(Table.ColumnNames(wide), each {_, Int64.Type}))
      in
          typedWide
      

      源数据

      结果

      【讨论】:

        猜你喜欢
        • 2012-05-24
        • 1970-01-01
        • 1970-01-01
        • 2011-06-17
        • 2011-04-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-01
        相关资源
        最近更新 更多