向量化多个熊猫列的添加

时间:2020-01-03 15:31:24

标签: python pandas

我有一个示例数据框:

   val1  val2  val3  val4  total
0     1     2     3     4     50
1     5     6     4     8     65
2     2     3     6     5     74

我想基于简单的列添加和划分来创建一些新列。每次都会得到一个比例/比率,因此我设置了一个快速功能来做到这一点:

def vectorize(df,value_cols,total_col):

    return df[value_cols] / df[total_col]

现在我想获得val1total的比例:

total = 'total'
values = 'val1'

df['result'] = vectorize(df,values,total)

   val1  val2  val3  val4  total    result
0     1     2     3     4     50  0.020000
1     5     6     4     8     65  0.076923
2     2     3     6     5     74  0.027027

这看起来很棒。

现在,当我想在除以total之前添加多列时,我遇到了问题。

例如,我尝试找出val1 + val2total的比例:

total = 'total'
values = ['val1','val2']

df['result2'] = vectorize(df,values,total)

ValueError: Wrong number of items passed 5, placement implies 1

这不起作用,因为我的列名现在在列表中。它返回的数据帧为Nans

有没有解决这个问题的简单方法?

我尝试将sum()添加到函数中,但没有得到正确的结果:

return df[value_cols].sum() / df[total_col]

我尝试使用enumerate将列加在一起,然后除以total

for i,col in enumerate(value_cols):

    sums = df[col] += df[col]

    return sums / df[total_col]

但是这些都不起作用。

我基本上是想在函数中自动化它:

df['val1'] + df['val2'] / df['total'] 

但是也允许只包含一列,即仅val1个。

我的现实世界数据框有数百列,我想像这样将一个或多个列加在一起。我可以手动输入所有内容,但我想尝试通过创建矢量化功能来加快速度。

我的df再现性:

import pandas as pd

pd.DataFrame({'val1': pd.Series([1, 5, 2],dtype='int64',index=pd.RangeIndex(start=0, stop=3, step=1)), 'val2': pd.Series([2, 6, 3],dtype='int64',index=pd.RangeIndex(start=0, stop=3, step=1)), 'val3': pd.Series([3, 4, 6],dtype='int64',index=pd.RangeIndex(start=0, stop=3, step=1)), 'val4': pd.Series([4, 8, 5],dtype='int64',index=pd.RangeIndex(start=0, stop=3, step=1)), 'total': pd.Series([50, 65, 74],dtype='int64',index=pd.RangeIndex(start=0, stop=3, step=1))}, index=pd.RangeIndex(start=0, stop=3, step=1))

4 个答案:

答案 0 :(得分:1)

这是一种方法:

def vectorize(df,value_cols,total_col):
    # for multiple columns
    if isinstance(value_cols, list):
        return df[value_cols].sum(axis=1) / df[total_col]
    # for single column
    return df[value_cols] / df[total_col]

答案 1 :(得分:1)

只需调整功能:

def vectorize(df,value_cols,total_col):
    if(isinstance(value_cols, list)):
        return df[value_cols].apply(sum, axis=1).div(df[total_col])
    else:
        return df[value_cols].div(df[total_col])

输出:

   val1  val2  val3  val4  total    result   result2
0     1     2     3     4     50  0.020000  0.060000
1     5     6     4     8     65  0.076923  0.169231
2     2     3     6     5     74  0.027027  0.067568

答案 2 :(得分:0)

使用remove_configuration()是正确的选择。但是您需要指定要添加的轴。默认情况下,它添加行,而不是列。这就是您需要的:

LayoutManager

答案 3 :(得分:0)

由于您需要执行许多除法,因此可以对列进行求和,因此我将对函数进行一些修改。向其传递DataFrame,分母列,然后传递一个列表列表,这些列表指定基于每个子列表添加的列。

def sum_then_divide(df, total_col, numer_col_list):
    """
    df : pd.DataFrame
    total_col : str, denominator
    numer_col_list: list of lists
        Sum all columns in each sublist before dividing
    """
    u = pd.concat([df[cols].sum(1).rename('+'.join(cols)) for cols in numer_col_list], axis=1)
    return u.divide(df[total_col], axis=0)

sum_then_divide(df, 'total', [['val1'], ['val1', 'val2'], ['val1', 'val3', 'val4']])
#       val1  val1+val2  val1+val3+val4
#0  0.020000   0.060000        0.160000
#1  0.076923   0.169231        0.261538
#2  0.027027   0.067568        0.175676