【问题标题】:Convenient way to convert dataframe to vector of tuple?将数据帧转换为元组向量的便捷方法?
【发布时间】:2022-01-22 12:29:21
【问题描述】:

我正在尝试在 Julia 中创建一个将数据帧转换为元组向量的函数。

例如,

using DataFrames
df = DataFrame(A=1:4, B=4:7, C=10:13)

4×3 DataFrame
 Row │ A      B      C     
     │ Int64  Int64  Int64 
─────┼─────────────────────
   1 │     1      4     10
   2 │     2      5     11
   3 │     3      6     12
   4 │     4      7     13

T = [t for t in zip(df.A, df.B, df.C)]

T = 4-element Vector{Tuple{Int64, Int64, Int64}}:
 (1, 4, 10)
 (2, 5, 11)
 (3, 6, 12)
 (4, 7, 13)

那么 T 就变成了我想要的结果。

但是,问题是我需要对上述过程进行功能化。

所以,我需要的是自动将数据框的列放入 zip 函数中。

我想做的函数形式如下

using DataFrames

function DataframeToTuple(df)
    T = [t for t in zip(df.first column name, df.second column name, ... df.last column name)]
    return T
end

有什么方便的方法吗?非常感谢

【问题讨论】:

    标签: dataframe tuples julia


    【解决方案1】:

    这可能是最短的方法:

    julia> Tuple.(eachrow(df))
    4-element Vector{Tuple{Int64, Int64, Int64}}:
     (1, 4, 10)
     (2, 5, 11)
     (3, 6, 12)
     (4, 7, 13)
    

    知道您可以以相同的方式将DataFrame 转换为NamedTuples 的Vector 也很有趣:

    julia> NamedTuple.(eachrow(df))
    4-element Vector{NamedTuple{(:A, :B, :C), Tuple{Int64, Int64, Int64}}}:
     (A = 1, B = 4, C = 10)
     (A = 2, B = 5, C = 11)
     (A = 3, B = 6, C = 12)
     (A = 4, B = 7, C = 13)
    

    【讨论】:

      【解决方案2】:

      如果数据框不是很宽(大约小于 1000 列),将数据框转换为 NamedTuple 向量的更有效方法是:

      julia> Tables.rowtable(df)
      4-element Vector{NamedTuple{(:A, :B, :C), Tuple{Int64, Int64, Int64}}}:
       (A = 1, B = 4, C = 10)
       (A = 2, B = 5, C = 11)
       (A = 3, B = 6, C = 12)
       (A = 4, B = 7, C = 13)
      

      如果您坚持使用元组,那么请执行Tuple.(Tables.rowtable(df))

      【讨论】:

        【解决方案3】:

        有很多方法可以做到这一点-不可避免地会涉及到TupleNamedTuple.

        using DataFrames
        df = DataFrame(A=1:4, B=4:7, C=10:13)
        
        4×3 DataFrame
        Row │ A      B      C     
            │ Int64  Int64  Int64 
        ────┼─────────────────────
          1 │     1      4     10
          2 │     2      5     11
          3 │     3      6     12
          4 │     4      7     13
        
        [Tuple(df[n,:]) for n in 1:size(df,1)]
        
        4-element Vector{Tuple{Int64, Int64, Int64}}:
        (1, 4, 10)
        (2, 5, 11)
        (3, 6, 12)
        (4, 7, 13)
        

        原因很有趣。作为一个基本思想,有两种类型,简单值和集合。前者的例子是String,后者的例子是TupleArray。类型名称以大写字母开头。

        对于每一种类型,都有一个对应的函数,与类型同名,但名称全小写。类型String 具有函数stringTuple 具有函数tuple。该函数获取数据并将其放入新类型。如果新类型是简单类型,则进行转换,如果是集合,则将数据放入新集合中而不进行转换。

         # String
         string(1.0)       # -> "1.0"
         string(1:3)       # -> "1:3"
        
         # Tuple
         tuple(1.0)        # -> (1.0,)
         tuple(1:3)        # -> (1:3,) 
         tuple([1,2,3,4])  # -> ([1, 2, 3, 4],)
        

        仅对于集合,提供了另一个与类型同名的函数,并以大写字母开头。这样就完成了转换。

         # Tuple
         Tuple(1.0)       # -> (1.0,)
         Tuple(1:3)       # -> (1,2,3)
         Tuple([1,2,3,4]) # -> (1,2,3,4)
        

        因此,在这里,当转换为元组时,我们必须使用函数Tuple(或函数NamedTuple)。

        【讨论】:

        • 本段“对于每一种类型,都有对应的函数,与类型同名,但名称全小写。...如果新类型是简单类型,那么转换完成,如果是一个集合,那么数据将被放入一个新的集合中而不进行转换。”这是完全正确的。 stringString 基本上不相关tuple(x,y,z)(x,y, z) 是同一个东西,tuple 的名称主要是为了提供一种函数形式,即在地图等使用的事物周围放置括号
        • 太棒了!非常感谢
        猜你喜欢
        • 2017-12-30
        • 1970-01-01
        • 2012-04-03
        • 1970-01-01
        • 2017-03-09
        • 1970-01-01
        • 1970-01-01
        • 2013-03-30
        • 2015-01-25
        相关资源
        最近更新 更多