如何重塑、分组和重命名 Julia 数据框?

How to reshape, group by and rename Julia dataframe?

我有以下数据框:

  Police Product  PV1  PV2  PV3   PM1   PM2  PM3
0       1      AA   10    8   14   150   145  140
1       2      AB   25    4    7   700   650  620
2       3      AA   13   22    5   120    80   60
3       4      AA   12    6   12   250   170  120
4       5      AB   10   13    5   500   430  350
5       6      BC    7   21   12  1200  1000  900

PV1 是第 1 年的项目 PV,PV2 是第 2 年的项目,.... 我想结合重塑和分组操作+一些重命名的东西来获得下面的 DF :

  Product Item  Year1  Year2  Year3
0      AA   PV     35     36     31
1      AA   PM    520    395    320
2      AB   PV     35     17     12
3      AB   PM   1200   1080    970
4      BC   PV      7     21     12
5      BC   PM   1200   1000    900 

它通过对产品名称的操作进行分组并重塑 DF 以将项目作为列传递,并将每个项目的总和放入新列年中。

我在 Python 中找到了一种方法,但我现在正在寻找一种在 Julia 中传递我的代码的解决方案。 groupby 操作没有问题,但我在重塑/重命名部分有更多问题。

如果您有任何想法,我将不胜感激。

感谢您的帮助

编辑:

按照您的建议,我已经安装了 Julia 1.5 并将 DataFrames pkg 更新为 0.22 版本。结果,代码运行良好。唯一剩下的问题与我的真实 DF 中列名的非恒定长度有关,这使得代码的转换部分不完全适用。我将寻找一种使用正则表达式拆分 char/num 的方法。

非常感谢您的宝贵时间,对于编辑中的错误,我们深表歉意。

可能有几种方法可以做到这一点。这是一个使用内置函数的示例(同时利用了几个高级功能,所以如果您对代码有任何疑问,请发表评论,我可以解释):

julia> using CSV, DataFrames, Chain

julia> str = """
       Police Product  PV1  PV2  PV3   PM1   PM2  PM3
            1      AA   10    8   14   150   145  140
            2      AB   25    4    7   700   650  620
            3      AA   13   22    5   120    80   60
            4      AA   12    6   12   250   170  120
            5      AB   10   13    5   500   430  350
            6      BC    7   21   12  1200  1000  900""";

julia> @chain str begin
           IOBuffer
           CSV.read(DataFrame, ignorerepeated=true, delim=" ")
           groupby(:Product)
           combine(names(df, r"\d") .=> sum, renamecols=false)
           stack(Not(:Product))
           transform!(:variable => ByRow(x -> (first(x, 2), last(x, 1))) => [:Item, :Year])
           unstack([:Product, :Item], :Year, :value, renamecols = x -> Symbol("Year", x))
           sort!(:Product)
       end
6×5 DataFrame
 Row │ Product  Item    Year1   Year2   Year3
     │ String   String  Int64?  Int64?  Int64?
─────┼─────────────────────────────────────────
   1 │ AA       PV          35      36      31
   2 │ AA       PM         520     395     320
   3 │ AB       PV          35      17      12
   4 │ AB       PM        1200    1080     970
   5 │ BC       PV           7      21      12
   6 │ BC       PM        1200    1000     900

我使用Chain.jl只是为了展示如何在实践中使用它(但当然不需要)。

您可以在任何处理阶段后添加 @aside show(_) 注释以查看处理步骤的结果。

编辑:

这是您需要的正则表达式(拆分非数字字符后跟数字字符)吗?

julia> match(r"([^\d]+)(\d+)", "fsdfds123").captures
2-element Array{Union{Nothing, SubString{String}},1}:
 "fsdfds"
 "123"

然后写:

ByRow(x -> match(r"([^\d]+)(\d+)", x).captures)

作为你的转变