基于来自其他列

时间:2017-02-14 12:04:13

标签: python string pandas conditional-statements startswith

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

我想创建一个新列,其中值以文本列中文本字符串的开头为条件。

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

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

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

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

如果以上都不返回0

2 个答案:

答案 0 :(得分:5)

有可能使用多个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

EDIT1:

感谢您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

答案 1 :(得分:0)

一种不同且较慢的解决方案: 但是,优点是模式的映射是一个函数参数(隐式默认值为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

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

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