熊猫是指可与琴弦配合使用的功能

时间:2018-09-03 00:39:26

标签: python arrays pandas apply pandas-groupby

我需要在Pandas数据帧上运行的聚合函数(均值,std,var,min,max等),可以从groupby()。apply()调用,但如果它们的所有值均不删除字符串一样

所以:

mean(['a','a'])应该产生'a'

mean(['a','b'])应该产生NaN

熊猫的行为(正如人们期望的那样)是丢弃非数字值:

>>> df = pd.DataFrame({'c1':  [1,2,3],
                       'c2':  [1,1,1],
                       'c3':  ['a','b','c'],
                       'c4':  ['a','a','a'],
                       'cat': ['x','x','y']})
>>> df.mean()
c1    2.0
c2    1.0

我需要的地方:

c1    2.0
c2    1.0
c3    NaN
c4    'a'
cat   NaN

我还需要针对每个组使用这些功能。因此,我创建了将如上所述输出字符串的函数,类似于mean(),然后可以从groupby.apply()进行调用:

def str_reduce(df):
    is_uniq = False
    try:
        is_uniq = df.unique().size == 1
    except:
        pass
    return df[0] if is_uniq else np.NaN

这与我直接应用它时的意思类似:

>>> df[['c3','c4']].apply(str_reduce)
c3    NaN
c4      a

但是当我按照groupby调用它时,它现在给出了意外的结果?

>>> df.groupby(['cat']).apply(str_reduce) 
cat
x   NaN
y   NaN

我在做什么错?和/或在熊猫中,有没有更好/更容易的方法?

2 个答案:

答案 0 :(得分:1)

在groupby上使用.apply时,它似乎将功能应用于整个分组对象。在这种情况下,您希望将功能应用于每个组中的每一列,因此使用.agg更合适,并且将为您提供期望的输出。

我认为您编写的功能并不完全是您想要的功能,因为您需要事先知道哪些列是数字列,否则对于数字列将无法正常工作。相反,您可以编写函数来检查dtype是否为数字并正常进行,否则它们将应用您的特殊规则。

import pandas as pd
import numpy as np
from pandas.api.types import is_numeric_dtype

def mean_str(col):
    if is_numeric_dtype(col):
        return col.mean()
    else:
        return col.unique() if col.nunique() == 1 else np.NaN

所以现在您将执行以下操作:

df.groupby('cat').agg(mean_str)

输出:

      c1  c2   c3 c4
cat                 
x    1.5   1  NaN  a
y    3.0   1    c  a

答案 1 :(得分:0)

这有任何帮助吗?

list_columns=df.columns.tolist()
dict_new={}
for i in range(len(list_columns)):
    if(df[list_columns[i]].dtype)=='O':
        list_of_items=list(set(df[list_columns[i]].tolist()))
        if(len(list_of_items)>1):
            dict_new[list_columns[i]]='NaN'
        else:
            dict_new[list_columns[i]]=list_of_items[0]
    elif(df[list_columns[i]].dtype)=='int64':
        dict_new[list_columns[i]]=df[list_columns[i]].mean()

s = pd.Series(dict_new, name='ValueColumn')
test=pd.DataFrame(s)
test.reset_index(inplace=True)


index   ValueColumn
0   c1  2
1   c2  1
2   c3  NaN
3   c4  a
4   cat NaN

您可以在此处将名为index的列重命名为所需的名称。