如何在Pandas系列中识别空字符串

4
我有一个数据框,如果'gender'列为空,我想用'name'列的值填充'column3'列,否则用'gender'列的值填充'column3'列。
vals = {
    'name' : ['n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7'],
    'gender' : ['', '', '', 'f',  'f', 'c', 'c'],
    'age' : [39, 12, 27, 13, 36, 29, 10]
}
df4 = pd.DataFrame(vals)
df4['column3'] = df4['name'] if len(df4['gender']) == 0 else df4['gender']

结果是column3只包含来自“gender”的值。 我尝试了以下语句:
df4['column3'] = np.where(df4['gender'].empty, df4['name'],df4['gender'])
df4['column3'] = df4['name'] if df4['gender'].empty else df4['gender']

结果相同...所以我认为我的代码无法识别Python数据框中的空字符串。我错过了什么?


2
使用 df4['column3'] = np.where(df4.gender.eq(''), df4.name, df4.gender) - Zero
@Zero,好的,它可以工作:) 请创建答案并解释为什么我的代码不正确。 - Nik
请检查我的答案,你会发现你所执行的操作实际上并没有应用于每一行,你应该使用apply函数来使用axis = 1进行类似的逻辑处理。 - Menglong Li
不要使用lambda。你的逻辑很容易向量化。 - jpp
3个回答

6
您的numpy.where结构是可以使用的。
您遇到的问题是如何测试列与空字符串。答案就是检查相等性 versus ''
这很容易实现:
```python if column == '': # do something else: # do something else ```
请注意,您需要将上面的代码应用于您正在使用的DataFrame的特定列。
df4['column3'] = np.where(df4['gender'] == '', df4['name'], df4['gender'])

pd.Series.empty 用于测试序列是否没有任何数据项,即没有行,而不是测试其元素是否为空字符串。

示例

import pandas as pd, numpy as np

vals = {
    'name' : ['n1', 'n2', 'n3', 'n4', 'n5', 'n6', 'n7'],
    'gender' : ['', '', '', 'f',  'f', 'c', 'c'],
    'age' : [39, 12, 27, 13, 36, 29, 10]
}
df4 = pd.DataFrame(vals)

df4['column3'] = np.where(df4['gender'] == '', df4['name'], df4['gender'])

#    age gender name column3
# 0   39          n1      n1
# 1   12          n2      n2
# 2   27          n3      n3
# 3   13      f   n4       f
# 4   36      f   n5       f
# 5   29      c   n6       c
# 6   10      c   n7       c

1
好的。你是正确的。它有效。答案被接受,因为你提供了解释。 - Nik

1
有许多种方法,但我认为以下是最简洁的:
idx = lambda x: x.gender==''
df4.loc[idx, 'column3'] = df4.loc[idx, 'name']
df4.column3= df.column3.fillna(df4.gender)

@jpp 我认为你不理解这里正在发生什么。它是矢量化的。Lambda函数正在对整个数据帧x执行布尔比较,以列“gender”作为索引。然后,loc使用此作为矢量化索引。这使我无需在loc中重复过滤。它还意味着我不会通过实际创建布尔索引来创建可能很大的idx对象。有关更多信息,请参见此处 - Little Bobby Tables
@jpp 你看了我的解释吗?我没有在apply函数中使用lambda。与其浪费时间侮辱别人,不如花点时间读一下我的解释。 - Little Bobby Tables
@jpp 是的。在 lambda: x: x.gender 中,x 是一个 DataFrame,因此 x.gender 是一个 Series。即它是矢量化的。它不是在 DataFrame 或 Series 的每个元素上使用 lambda 函数。 - Little Bobby Tables
@jpp,我在我的第一个解释中已经写过了:“这也意味着我不会通过实际创建布尔索引作为Series来创建一个可能很大的idx对象。” 如果原始DataFrame很大,那么这将是一个很大的idx对象。 - Little Bobby Tables
@jpp你的观点是你不喜欢使用逐元素lambda函数。这不是那样的情况。 - Little Bobby Tables
1
如果lambda函数没有任何作用,我不喜欢它们出现的任何地方:)。我对你所声明的目的提出质疑。 - jpp

1

我更喜欢仅使用pandas来完成这个任务,而不是引入numpy:

df4['column3'] = df4[['gender', 'name']].apply(lambda x: x[0] if x[0] else x[1], axis=1)

1
@MenglongLi,我没有。我给你点了赞。我想知道为什么有人在不留评论的情况下给你点了踩。这是一个好答案。 - Little Bobby Tables
@jpp 在点踩之前应该先解释一下你的理由。这样可以让用户纠正错误或改变他们的思维方式。 - Little Bobby Tables
为什么pandas中使用apply lambda比循环慢? - jpp

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接