在数据帧上使用groupby和lambda函数时保留NaN值

2024-06-16 09:31:37 发布

您现在位置:Python中文网/ 问答频道 /正文

从这个question开始,我有一个这样的数据集:

    ChildID   MotherID   preDiabetes
0     20      455        No
1     20      455        Not documented
2     13      102        NaN
3     13      102        Yes
4     702     946        No
5     82      571        No
6     82      571        Yes
7     82      571        Not documented
8     60      530        NaN

我将其转换为以下内容,以便每位母亲对糖尿病前期有一个单一的值:

    ChildID   MotherID   preDiabetes
0   20        455        No
1   13        102        Yes
2   702       946        No
3   82        571        Yes
4   60        530        No

我通过应用以下逻辑实现了这一点:

  • 如果某个特定的MotherID的preDiabetes==“Yes”,则不管剩余的观察结果如何,都为preDiabetes指定一个值“Yes”
  • 否则,如果糖尿病前期!=“是”对于特定的MotherID,我将为preDiabetes指定一个值“否”

然而,在再次思考这一点之后,我意识到我应该保留NaN值,以便稍后对其进行插补,而不仅仅是将其指定为“否”。 因此,我应该将我的逻辑编辑为:

  • 如果某个特定的MotherID的preDiabetes==“Yes”,则不管剩余的观察结果如何,都为preDiabetes指定一个值“Yes”
  • 否则,如果特定MotherID的preDiabetes==NaN的all值,则为preDiabetes分配一个NaN值
  • else assign预设定值为“否”

因此,在上表中,MotherID=530的值应为NaN,如:

    ChildID   MotherID   preDiabetes
0   20        455        No
1   13        102        Yes
2   702       946        No
3   82        571        Yes
4   60        530        NaN

我尝试使用以下代码行执行此操作:

   df=df.groupby(['MotherID', 'ChildID'])['preDiabetes'].apply(
       lambda x: 'Yes' if 'Yes' in x.values else (np.NaN if np.NaN in x.values.all() else 'No'))

但是,运行这行代码会导致以下错误:

TypeError:'in'需要字符串作为左操作数,而不是浮点运算

如果你们能指出我做错了什么,我将不胜感激。谢谢


Tags: no代码indfnot逻辑nanall
3条回答

您可以尝试:

import pandas as pd
import numpy as np
import io

data_string = """ChildID,MotherID,preDiabetes
20,455,No
20,455,Not documented
13,102,NaN
13,102,Yes
702,946,No
82,571,No
82,571,Yes
82,571,Not documented
60,530,NaN
"""

data = io.StringIO(data_string)
df = pd.read_csv(data, sep=',', na_values=['NaN'])
df.fillna('no_value', inplace=True)
df = df.groupby(['MotherID', 'ChildID'])['preDiabetes'].apply(
         lambda x: 'Yes' if 'Yes' in x.values else (np.NaN if 'no_value' in x.values.all() else 'No'))
df

结果:

MotherID  ChildID
102       13         Yes
455       20          No
530       60         NaN
571       82         Yes
946       702         No
Name: preDiabetes, dtype: object

您可以使用自定义函数执行以下操作:

def func(s):

    if s.eq('Yes').any():
        return 'Yes'
    elif s.isna().all():
        return np.nan
    else:
        return 'No'

df  = (df
       .groupby(['ChildID', 'MotherID'])
       .agg({'preDiabetes': func}))

print(df)

   ChildID  MotherID preDiabetes
0       13       102         Yes
1       20       455          No
2       60       530         NaN
3       82       571         Yes
4      702       946          No

尝试:

df['preDiabetes']=df['preDiabetes'].map({'Yes': 1, 'No': 0}).fillna(-1)

df=df.groupby(['MotherID', 'ChildID'])['preDiabetes'].max().map({1: 'Yes', 0: 'No', -1: 'NaN'}).reset_index()

第一行preDiabetes格式化为数字,假设NaN是除YesNo(由-1表示)之外的所有内容

第二行假设至少有一个preDiabetesYes-我们为组输出Yes。假设我们有NoNaN,我们输出No。假设所有的都是NaN,我们输出NaN

产出:

>>> df

   MotherID  ChildID preDiabetes
0       102       13         Yes
1       455       20          No
2       530       60         NaN
3       571       82         Yes
4       946      702          No

相关问题 更多 >