如何使用包含两列的一个条件执行 loc

Avi*_*Sar 13 python dataframe pandas

我有 df 有两列 A 和 B ,它们都是带有字符串值的列。

例子:

df_1 = pd.DataFrame(data={
    "A":['a','b','c'],
    "B":['a x d','z y w','q m c'] #string values not a list
})
print(df_1)

#output
   A      B
0  a  a x d
1  b  z y w
2  c  q m c
Run Code Online (Sandbox Code Playgroud)

现在我想做的是在 df_1 中执行 loc 以获得 col B 与 col A 中的字符串值共存的所有行。

在此示例中,我想要的输出是第一行和第三行:

   A      B
0  a  a x d # 'a x d' contain value 'a'
2  c  q m c # 'q m c' contain value 'c'
Run Code Online (Sandbox Code Playgroud)

我尝试了不同的 loc 条件,但出现了 unhashable type: 'Series' 错误:

df_1.loc[df_1["B"].str.contains(df_1["A"])] #TypeError: unhashable type: 'Series'
df_1.loc[df_1["A"] in df_1["B"]] #TypeError: unhashable type: 'Series'
Run Code Online (Sandbox Code Playgroud)

由于 df 的大小,我真的不想使用 for/while 循环。

知道如何执行此操作吗?

moz*_*way 21

没有矢量方法可以in使用两列进行映射。你需要在这里循环:

\n
mask = [a in b for a,b in zip(df_1[\'A\'], df_1[\'B\'])]\n\ndf_1.loc[mask]\n
Run Code Online (Sandbox Code Playgroud)\n

输出:

\n
   A      B\n0  a  a x d\n2  c  q m c\n
Run Code Online (Sandbox Code Playgroud)\n
速度比较(3000行)
\n
# operator.contains\n518 \xc2\xb5s \xc2\xb1 4.61 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 1000 loops each)\n\n# list comprehension\n554 \xc2\xb5s \xc2\xb1 3.84 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 1000 loops each)\n\n# numpy.apply_along_axis\n7.32 ms \xc2\xb1 58.8 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 100 loops each)\n\n# apply\n20.7 ms \xc2\xb1 379 \xc2\xb5s per loop (mean \xc2\xb1 std. dev. of 7 runs, 10 loops each)\n
Run Code Online (Sandbox Code Playgroud)\n

  • @Aviv 一个快速的解决方法是在列表理解中使用 `df['B'].fillna('')` (或 `df['A'].fillna('')` ,具体取决于哪一列具有 NA ) (2认同)

piR*_*red 10

可爱的!

from operator import contains

df_1.loc[map(contains, *map(df_1.get, ['B', 'A']))]

   A      B
0  a  a x d
2  c  q m c
Run Code Online (Sandbox Code Playgroud)

没有导入,但有一个丑陋的dunder ... /-:

df_1.loc[map(str.__contains__, *map(df_1.get, ['B', 'A']))]
Run Code Online (Sandbox Code Playgroud)

另外,对于OP...不要接受这个答案。我只是在打高尔夫球。您永远不应该在生产代码中使用它,因为由于使用了 2 个贴图和一个 splat,它不太透明。

只是为了超级清楚......

mozway 的更好


Cor*_*ien 6

你可以试试:

out = df_1.loc[df_1.apply(lambda x: x['A'] in x['B'], axis=1)]
print(out)

# Output
   A      B
0  a  a x d
2  c  q m c
Run Code Online (Sandbox Code Playgroud)

替代方案numpy

df_1.loc[np.apply_along_axis(lambda x: x[0] in x[1], axis=1, arr=df_1)]
Run Code Online (Sandbox Code Playgroud)