问题 Pandas:如果A列中的行包含“x”,则将“y”写入B列中的行


对于 pandas,我正在寻找一种方法,根据A列中相应行的子串,将条件值写入B列中的每一行。

所以,如果细胞在 A 包含 "BULL""Long" 至 B。或者,如果细胞在 A 包含 "BEAR""Short" 至 B

期望的输出:

A                  B
"BULL APPLE X5"    "Long"
"BEAR APPLE X5"    "Short"
"BULL APPLE X5"    "Long"

B最初是空的: df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']],columns=['A','B'])


3580
2018-06-20 11:11


起源

这个问题问得好。如果你必须根据字符串搜索分配B,那么所需的列B是二进制的。 - user3341078


答案:


在您错误地创建Dataframe时,您的代码会出错,只需创建一个列 A 然后加 B 基于 A

import pandas as pd
df = pd.DataFrame(["BULL","BEAR","BULL"], columns=['A'])
df["B"] = ["Long" if ele  == "BULL" else "Short" for ele in df["A"]]

print(df)

    A      B
0  BULL   Long
1  BEAR  Short
2  BULL   Long

或者在创建数据帧之前对数据进行逻辑处理:

import pandas as pd
data = ["BULL","BEAR","BULL"]
data2 = ["Long" if ele  == "BULL" else "Short" for ele in data]
df = pd.DataFrame(list(zip(data, data2)), columns=['A','B'])

print(df)
      A      B
 0  BULL   Long
 1  BEAR  Short
 2  BULL   Long

为了您的编辑:

df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']], columns=['A','B'])

df["B"] = df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "")

print(df)

            A      B
0  BULL APPLE X5   Long
1  BEAR APPLE X5  Short
2  BULL APPLE X5   Long

或者只需在以下后面添加列:

df = pd.DataFrame(['BULL APPLE X5','BEAR APPLE X5','BLL APPLE X5'], columns=['A'])

df["B"] = df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "")

print(df)

或使用包含:

df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']], columns=['A','B'])


df["B"][df['A'].str.contains("BULL")] = "Long"
df["B"][df['A'].str.contains("BEAR")] = "Short"

print(df)
0  BULL APPLE X5   Long
1  BEAR APPLE X5  Short
2  BULL APPLE X5   Long

9
2018-06-20 11:21



这只适用于不在公牛的情况下你必须是熊。但这并不是OP的条件 - joaquin
@joaquin,OP并没有说有任何其他可能性,但如果有的话,为它添加逻辑并不会太难。 - Padraic Cunningham
@PadraicCunningham谢谢,我已经使用正确的DataFrame更正了OP,以免混淆未来的读者。如果您愿意,可以编辑您的答案。将尝试您的解决方案 - Winterflags
绝对,很容易纠正。只是我想要注意“如果A中的单元格包含”BEAR“”与“如果A中的单元格不包含”Bull“”则不一样。 - joaquin
@Winterflags所以你匹配子串? - Padraic Cunningham


你可以用 str.extract 搜索正则表达式模式 BULL|BEAR,然后使用 Series.map 替换这些字符串 Long 要么 Short

In [50]: df = pd.DataFrame([['BULL APPLE X5',''],['BEAR APPLE X5',''],['BULL APPLE X5','']],columns=['A','B'])

In [51]: df['B'] = df['A'].str.extract(r'(BULL|BEAR)').map({'BULL':'Long', 'BEAR':'Short'})

In [55]: df
Out[55]: 
               A      B
0  BULL APPLE X5   Long
1  BEAR APPLE X5  Short
2  BULL APPLE X5   Long

但是,形成中间系列 str.extract 与...相比相当慢 df['A'].map(lambda x:...)。使用IPython的 %timeit 为基准计时,

In [5]: df = pd.concat([df]*10000)

In [6]: %timeit df['A'].str.extract(r'(BULL|BEAR)').map({'BULL':'Long', 'BEAR':'Short'})
10 loops, best of 3: 39.7 ms per loop

In [7]: %timeit df["A"].map(lambda x: "Long" if "BULL" in x else "Short" if "BEAR" in x else "")
100 loops, best of 3: 4.98 ms per loop

大部分时间都花在了 str.extract

In [8]: %timeit df['A'].str.extract(r'(BULL|BEAR)')
10 loops, best of 3: 37.1 ms per loop

而呼唤 Series.map 比较快:

In [9]: x = df['A'].str.extract(r'(BULL|BEAR)')

In [10]: %timeit x.map({'BULL':'Long', 'BEAR':'Short'})
1000 loops, best of 3: 1.82 ms per loop

4
2018-06-20 12:04



非常感谢,正则表达式非常有用。肯定能用到这个。 - Winterflags
感谢您添加timeit测试,非常有趣。 - Winterflags


另外,填充 df['B'] 你可以尝试以下方法 -

def applyFunc(s):
    if s == 'BULL':
        return 'Long'
    elif s == 'BEAR':
        return 'Short'
    return ''

df['B'] = df['A'].apply(applyFunc)
df
>>
       A      B
0  BULL   Long
1  BEAR  Short
2  BULL   Long

什么的 apply 函数确实是,每行的值是 df['A'] ,它叫 applyFunc 函数使用参数作为该行的值,并将返回的值放入同一行 df['B'] ,场景背后真正发生的事情有点不同,但价值并未直接投入 df['B'] 而是一个新的 Series 已创建,最后,将分配新系列 df['B'] 。


3
2018-06-20 11:20



谢谢,我已经使用正确的DataFrame更正了OP,以免混淆未来的读者。如果您愿意,可以编辑您的答案。 - Winterflags
完成后,更新了答案。 - Anand S Kumar