Pandas意味着与字符串一起使用的函数

问题描述 投票:0回答:2

我需要在Pandas数据帧上运行的聚合函数(mean,std,var,min,max等),可以从groupby()。apply()调用,但如果所有值都相同则不丢弃字符串。

所以:

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

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

Pandas行为(正如人们所预料的)是删除非数字值:

>>> 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

我究竟做错了什么?和/或者在熊猫中有更好/更简单的方法吗?

python arrays pandas apply pandas-groupby
2个回答
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

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的列重命名为您想要的任何内容。

© www.soinside.com 2019 - 2024. All rights reserved.