【问题标题】:Create new pandas column based on start of text string from other column根据来自其他列的文本字符串的开头创建新的 pandas 列
【发布时间】:2017-07-02 17:12:14
【问题描述】:

我有一个带有文本列的 pandas 数据框。

我想创建一个新列,其中的值取决于文本列中文本字符串的开头。

所以如果文本列的前 30 个字符:

== 'xxx...xxx'然后返回值1

== 'yyy...yyy' 然后返回值2

== 'zzz...zzz' 然后返回值3

if none of the above return 0

【问题讨论】:

  • 我忘了提到我们要在文本列中查看的字符数随每个条件而变化。因此对于值 1,我们查看前 30 个字符/值 2、25 个字符、值 3、35 个字符

标签: python string pandas conditional-statements startswith


【解决方案1】:

另一种较慢的解决方案: 但是,优点是模式的映射是一个函数参数(具有隐式默认值 0 值)

def map_starts_with(pat_map):
    def map_string(t):
        pats = [pat for pat in pat_map.keys() if t.startswith(pat)]
        return pat_map.get(pats[0]) if len(pats) > 0 else 0 
# get only value of "first" pattern if at least one pattern is found
    return map_string

df = pd.DataFrame({'col':[ 'xx', 'aaaaaa', 'c']})
      col
0      xx
1  aaaaaa
2       c

mapping = { 'aaa':4 ,'c':3}
df.col.apply(lambda x: map_starts_with(mapping)(x))

0    0
1    4
2    3

请注意,我们在这里也使用了柯里化。我想知道这种方法是否可以使用额外的 pandas 或 numpy 功能来实现。

请注意,“第一个”模式匹配可能取决于 dict 键的遍历顺序。如果键中没有重叠,这无关紧要。 (Jezrael 的解决方案,或其直接推广,也将选择一个元素进行匹配,但以更可预测的方式)

【讨论】:

  • 只是想分享我对code review的回答的一些改进
【解决方案2】:

可以使用多个numpy.where,但如果更多条件使用apply

对于从策略中选择的字符串,请使用indexing with str

df = pd.DataFrame({'A':['xxxss','yyyee','zzzswee','sss'],
                   'B':[4,5,6,8]})

print (df)
         A  B
0    xxxss  4
1    yyyee  5
2  zzzswee  6
3      sss  8
#check first 3 values
a = df.A.str[:3]
df['new'] = np.where(a == 'xxx', 1, 
            np.where(a == 'yyy', 2, 
            np.where(a == 'zzz', 3, 0)))

print (df)
         A  B  new
0    xxxss  4    1
1    yyyee  5    2
2  zzzswee  6    3
3      sss  8    0
def f(x):
    #print (x)
    if x == 'xxx':
        return 1
    elif x == 'yyy':
        return 2
    elif x == 'zzz':
        return 3
    else:
        return 0

df['new'] = df.A.str[:3].apply(f)
print (df)
         A  B  new
0    xxxss  4    1
1    yyyee  5    2
2  zzzswee  6    3
3      sss  8    0

编辑:

如果长度不同,只需要:

df['new'] = np.where(df.A.str[:3] == 'xxx', 1, 
            np.where(df.A.str[:2] == 'yy', 2, 
            np.where(df.A.str[:1] == 'z', 3, 0)))

print (df)
         A  B  new
0    xxxss  4    1
1    yyyee  5    2
2  zzzswee  6    3
3      sss  8    0

编辑1:

感谢Quickbeam2k1 使用str.startswith 检查每个字符串的开始:

df['new'] = np.where(df.A.str.startswith('xxx'), 1, 
            np.where(df.A.str.startswith('yy'), 2, 
            np.where(df.A.str.startswith('z'), 3, 0)))

print (df)
         A  B  new
0    xxxss  4    1
1    yyyee  5    2
2  zzzswee  6    3
3      sss  8    0

【讨论】:

  • 谢谢 - 它只适用于固定数量的字符(在您的示例 3 中),但是如果字符数随每个条件而变化,您会怎么做?
  • @jezrael,您甚至可能想使用(开始于)[pandas.pydata.org/pandas-docs/stable/generated/…
  • @Quickbeam2k1 - 谢谢,我添加它来回答。
  • @Pierre - 如果我或其他答案有帮助,请不要忘记accept。谢谢。
  • @jezrael 谢谢您-使用您的 np.where 方法,为什么当文本字符串为 NaN 时我得到值 1?不应该是0吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-03
  • 2020-04-25
  • 1970-01-01
  • 2020-09-24
  • 2021-10-12
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多