【问题标题】:Group DataFrame by sequential occurrence of values in a column in Julia通过在 Julia 的列中按顺序出现的值对 DataFrame 进行分组
【发布时间】:2021-12-28 04:01:02
【问题描述】:

假设我有以下 DataFrame:

julia> Random.seed!(1)
TaskLocalRNG()

julia> df = DataFrame(data = rand(1:10, 10), gr = rand([0, 1], 10))
10×2 DataFrame
 Row │ data   gr    
     │ Int64  Int64 
─────┼──────────────
   1 │     1      1
   2 │     4      0
   3 │     7      0
   4 │     7      0
   5 │    10      1
   6 │     2      1
   7 │     8      0
   8 │     8      0
   9 │     7      0
  10 │     2      0

我想要的不仅仅是:gr 的值,还有这些值的出现。在这种情况下,组数应为 4:

Group 1 (1 row)
 Row │ data   gr    
     │ Int64  Int64 
─────┼──────────────
   1 │     1      1


Group 2 (3 rows)
 Row │ data   gr    
     │ Int64  Int64 
─────┼──────────────
   2 │     4      0
   3 │     7      0
   4 │     7      0

Group 3 (2 rows)
 Row │ data   gr    
     │ Int64  Int64 
─────┼──────────────
   5 │    10      1
   6 │     2      1

Group 4 (4 rows)
 Row │ data   gr    
     │ Int64  Int64 
─────┼──────────────
   7 │     8      0
   8 │     8      0
   9 │     7      0
  10 │     2      0

如果我按列 :gr 分组,但是,我只能得到两个组:

julia> groupby(df, :gr)
GroupedDataFrame with 2 groups based on key: gr
First Group (7 rows): gr = 0
 Row │ data   gr    
     │ Int64  Int64 
─────┼──────────────
   1 │     4      0
   2 │     7      0
   3 │     7      0
   4 │     8      0
   5 │     8      0
   6 │     7      0
   7 │     2      0
⋮
Last Group (3 rows): gr = 1
 Row │ data   gr    
     │ Int64  Int64 
─────┼──────────────
   1 │     1      1
   2 │    10      1
   3 │     2      1

如何在 Julia DataFrames.jl 中实现这一点?谢谢

versioninfo()
Julia Version 1.7.1
Commit ac5cc99908 (2021-12-22 19:35 UTC)
Platform Info:
  OS: macOS (x86_64-apple-darwin19.5.0)
  CPU: Apple M1 Max
  WORD_SIZE: 64
  LIBM: libopenlibm
  LLVM: libLLVM-12.0.1 (ORCJIT, westmere)
Environment:
  JULIA_NUM_THREADS = 1
  JULIA_EDITOR = code

【问题讨论】:

    标签: julia dataframes.jl


    【解决方案1】:

    您可以按每次 :gr 更改值时递增的新变量进行分组。

    例如:

    nrow = size(df,1)
    gr1 = zeros(Int64, nrow)
    for i=2:nrow
    gr1[i] = gr1[i-1] + (df.gr[i] != df.gr[i-1])
    end
    df.gr1 = gr1
    

    【讨论】:

      【解决方案2】:

      与@GEK 的回答基本思路相同,实现更加矢量化:

      julia> edgedetect(col) = [0; abs.(diff(col))] |> cumsum
      edgedetect (generic function with 1 method)
      
      julia> edgedetect([0, 1, 1, 1, 0, 0, 1]) |> print 
      [0, 1, 1, 1, 2, 2, 3]
      
      

      abs.(diff(col))col 列的值发生变化的地方放置一个 1,在其他地方放置一个 0。 (diff 在给定 n 个元素的情况下返回 n-1 个差异,因此我们在结果前加上 0 以保持列长度。)对此进行累积求和,我们得到一个新列,每次原始列中的值更改时都会增加.

      然后我们可以在转换后的数据帧上使用此函数groupby,如下所示:

      julia> groupby(transform(df, :gr => edgedetect => :gr_edges, copycols = false), :gr_edges) |> print
      GroupedDataFrame with 4 groups based on key: gr_edges
      Group 1 (1 row): gr_edges = 0
       Row │ data   gr     gr_edges 
           │ Int64  Int64  Int64    
      ─────┼────────────────────────
         1 │     1      1         0
      Group 2 (3 rows): gr_edges = 1
       Row │ data   gr     gr_edges 
           │ Int64  Int64  Int64    
      ─────┼────────────────────────
         1 │     4      0         1
         2 │     7      0         1
         3 │     7      0         1
      Group 3 (2 rows): gr_edges = 2
       Row │ data   gr     gr_edges 
           │ Int64  Int64  Int64    
      ─────┼────────────────────────
         1 │    10      1         2
         2 │     2      1         2
      Group 4 (4 rows): gr_edges = 3
       Row │ data   gr     gr_edges 
           │ Int64  Int64  Int64    
      ─────┼────────────────────────
         1 │     8      0         3
         2 │     8      0         3
         3 │     7      0         3
         4 │     2      0         3
      
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-03-20
        • 1970-01-01
        • 1970-01-01
        • 2018-05-28
        • 2020-11-16
        • 2014-11-29
        • 1970-01-01
        • 2017-02-01
        相关资源
        最近更新 更多