【问题标题】:Splitting a dataframe based on condition根据条件拆分数据框
【发布时间】:2018-10-24 19:44:07
【问题描述】:

我正在尝试根据medical_plan_id 将我的数据框拆分为两个。如果为空,则进入df1。如果不是空到df2.

df1 = df_with_medicalplanid[df_with_medicalplanid['medical_plan_id'] == ""]
df2 = df_with_medicalplanid[df_with_medicalplanid['medical_plan_id'] is not ""]

下面的代码有效,但如果没有空字段,我的代码会引发TypeError("invalid type comparison")

df1 = df_with_medicalplanid[df_with_medicalplanid['medical_plan_id'] == ""]

如何处理这种情况?

我的 df_with_medicalplanid 如下所示:

wellthie_issuer_identifier       ...       medical_plan_id
0                   UHC99806       ...                  None
1                   UHC99806       ...                  None

【问题讨论】:

  • is not改成!=?
  • 'medical_plan_id' 列中的 dtype 是什么?如果是整数或浮点数,那么与“”比较会导致类型错误。您可以尝试改用.isnull()

标签: python pandas


【解决方案1】:

使用==,而不是is,来测试相等性

同样,使用!= 代替is not 表示不等式。

is 在 Python 中有特殊的含义。如果两个变量指向同一个对象,则返回True,而== 检查变量引用的对象是否相等。另见Is there a difference between == and is in Python?

不要重复掩码计算

您正在创建的布尔掩码是您的逻辑中最昂贵的部分。这也是您希望避免手动重复的逻辑,因为您的第一个和第二个掩码彼此相反。因此,您可以使用bitwise inverse ~(“波浪号”)(也可通过operator.invert 访问)来否定现有掩码。

空字符串不同于空值

可以通过== '' 测试相等与空字符串,但相等与空值需要一个专门的方法:pd.Series.isnull。这是因为空值在 NumPy 数组中表示,这些数组由 Pandas、np.nannp.nan != np.nan by design 使用。

如果你想用空值替换空字符串,你可以这样做:

df['medical_plan_id'] = df['medical_plan_id'].replace('', np.nan)

从概念上讲,缺失值为 null (np.nan) 而不是空字符串是有意义的。但与上述过程相反,即将空值转换为空字符串也是可以的:

df['medical_plan_id'] = df['medical_plan_id'].fillna('')

如果差异很重要,您需要了解您的数据并应用适当的逻辑。

半决赛解决方案

假设你确实有空值,计算一个布尔掩码及其逆:

mask = df['medical_plan_id'].isnull()

df1 = df[mask]
df2 = df[~mask]

最终解决方案:避免额外的变量

创建额外的变量是程序员应该避免的事情。在这种情况下,不需要创建两个新变量,您可以使用GroupBydict 来给出一个数据帧字典,其中包含False (== 0) 和True (== 1) 键对应于你的面具:

dfs = dict(tuple(df.groupby(df['medical_plan_id'].isnull())))

那么dfs[0] 代表df2dfs[1] 代表df1(另见this related answer)。上面的一个变种,你可以放弃字典构建,使用 Pandas GroupBy 方法:

dfs = df.groupby(df['medical_plan_id'].isnull())

dfs.get_group(0)  # equivalent to dfs[0] from dict solution
dfs.get_group(1)  # equivalent to dfs[1] from dict solution

示例

将以上所有内容付诸实践:

df = pd.DataFrame({'medical_plan_id': [np.nan, '', 2134, 4325, 6543, '', np.nan],
                   'values': [1, 2, 3, 4, 5, 6, 7]})

df['medical_plan_id'] = df['medical_plan_id'].replace('', np.nan)
dfs = dict(tuple(df.groupby(df['medical_plan_id'].isnull())))

print(dfs[0], dfs[1], sep='\n'*2)

   medical_plan_id  values
2           2134.0       3
3           4325.0       4
4           6543.0       5

   medical_plan_id  values
0              NaN       1
1              NaN       2
5              NaN       6
6              NaN       7

【讨论】:

  • 我在fillna("") 上使用了类似的东西。我想我不应该使用它。没有这个,任何地方都空无一物,半最终解决方案正在发挥作用
  • @user1896796,在我看来,空值是np.nan,而不是空字符串是有道理的,所以我更喜欢df['medical_plan_id'] = df['medical_plan_id'].replace('', np.nan)。所以我不会使用fillna('')
  • 我试过用这种方式打印print ("In df1", dfs[0])。我收到print ("In df1", dfs[0]) KeyError: 0
  • 抱歉。用数据框更新了问题。这是在我根据您的 cmets 删除 fillna("") 之后。
  • @user1896796,那么我概述的解决方案仍然失败吗?如果是这样,我们仍然需要一个minimal reproducible example,它证明了问题。如果您需要这方面的帮助,请参阅 How to make good reproducible pandas examples
【解决方案2】:

另一个变体是解压df.groupby,它返回一个带有元组的迭代器(第一项是groupby的元素,第二项是数据框)。

例如:

cond = df_with_medicalplanid['medical_plan_id'] == ''
(_, df1) , (_, df2) = df_with_medicalplanid.groupby(cond)

_ 在 Python 中用于标记不想保留的变量。为了便于阅读,我将代码分成两行。


完整示例

import pandas as pd 

df_with_medicalplanid = pd.DataFrame({
    'medical_plan_id': ['214212','','12251','12421',''],
    'value': 1
})

cond = df_with_medicalplanid['medical_plan_id'] == ''
(_, df1) , (_, df2) = df_with_medicalplanid.groupby()

print(df1)

返回:

  medical_plan_id  value
0          214212      1
2           12251      1
3           12421      1

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-17
    • 2010-10-31
    相关资源
    最近更新 更多