【问题标题】:How to build a pandas dataframe in a recursive function?如何在递归函数中构建熊猫数据框?
【发布时间】:2021-06-11 19:20:09
【问题描述】:

我正在尝试在数据挖掘中实现“自下而上计算”算法 (https://www.aaai.org/Papers/FLAIRS/2003/Flairs03-050.pdf)。

我需要使用“pandas”库来创建一个数据框并将其提供给一个递归函数,该函数还应该返回一个数据框作为输出。我只能将最后一列作为输出返回,因为我无法弄清楚如何动态构建数据框。

这是python程序:

import pandas as pd

def project_data(df, d):
    return df.iloc[:, d]

def select_data(df, d, val):
    col_name = df.columns[d]
    return df[df[col_name] == val]

def remove_first_dim(df):
    return df.iloc[:, 1:]

def slice_data_dim0(df, v):
    df_temp = select_data(df, 0, v)
    return remove_first_dim(df_temp)

def buc(df):
    dims = df.shape[1]
    if dims == 1:
        input_sum = sum(project_data(df, 0) )
        print(input_sum)
    else:
        dim_vals = set(project_data(df, 0).values)

        for dim_val in dim_vals:
            sub_data = slice_data_dim0(df, dim_val)
            buc(sub_data)
        sub_data = remove_first_dim(df)
        buc(sub_data)


data = {'A':[1,1,1,1,2],
        'B':[1,1,2,3,1],
        'M':[10,20,30,40,50]
        }
    
df = pd.DataFrame(data, columns = ['A','B','M'])
buc(df)

我得到以下输出:

30
30
40
100
50
50
80
30
40

但我需要的是一个数据框,像这样(不一定是格式化的,而是一个数据框):

    A   B   M
0   1   1   30
1   1   2   30
2   1   3   40
3   1   ALL 100
4   2   1   50
5   2   ALL 50
6   ALL 1   80
7   ALL 2   30
8   ALL 3   40
9   ALL ALL 150

我如何做到这一点?

【问题讨论】:

    标签: python pandas data-mining


    【解决方案1】:

    不幸的是,pandas 没有进行小计的功能 - 所以诀窍是只计算它们并与原始数据框连接在一起。

    from itertools import combinations
    import numpy as np
    
    dim = ['A', 'B']
    vals = ['M']
    
    df = pd.concat(
        [df]
    # subtotals:
        + [df.groupby(list(gr), as_index=False)[vals].sum() for r in range(len(dim)-1) for gr in combinations(dim, r+1)]
    # total:
        + [df.groupby(np.zeros(len(df)))[vals].sum()]
        )\
        .sort_values(dim)\
        .reset_index(drop=True)\
        .fillna("ALL")
    

    输出:

          A    B    M
    0     1    1   10
    1     1    1   20
    2     1    2   30
    3     1    3   40
    4     1  ALL  100
    5     2    1   50
    6     2  ALL   50
    7   ALL    1   80
    8   ALL    2   30
    9   ALL    3   40
    10  ALL  ALL  150
    

    【讨论】:

    • 感谢一百万!有没有办法在不使用 itertools 的情况下做到这一点?除了 pandas 和 numpy 之外,我不允许导入任何东西(是的,这是一项学校任务。)
    • 是的,但是您必须编写自己的组合而不使用重复功能。可以从原文开始:docs.python.org/3/library/itertools.html#itertools.combinations
    • 太好了,谢谢!会检查出来的。最后一件事。输出中 A 和 B 列下的值显示为 .0,例如 1 显示为 1.0,2 显示为 2.0 等。这仅适用于 A 和 B,输出适用于 M。我该如何解决这个问题?
    • 我尝试使用 df.astype(int),但没有任何作用。
    • 嗯,所以这个问题是,python 中的int 没有None - 因此当你连接时,因为这些是数字,所以它默认为float 类型。可能最简单的选择是将所有dim 列映射到strfor col in dim: df[col] = df[col].map(are),然后再连接。
    猜你喜欢
    • 2021-02-12
    • 2021-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-02
    • 2018-12-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多