我需要在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
我在做什么错?和/或在熊猫中,有没有更好/更容易的方法?
答案 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的列重命名为所需的名称。