如何检查数据框是否包含任何字符串,如果它确实存在于 python 中,如何找到它的位置?

How to check if a dataframe contains any string and find the location of it if it does exist in python?

当我尝试将数据帧转换为 dtype=float 时,它 return 错误提示无法将字符串转换为浮点数。因此,我试图在数据框中找到字符串的位置。

这是我创建的示例数据框:

df = pd.DataFrame(np.arange(1,25).reshape(6,4))
Attribute = ['Eric', 'Sarah', 'Steve', 'David', 'Sam', 'Joe']
df.insert(0, 'Name', Attribute)
df[2][4] = 'strin'

看起来像:

    Name   0   1      2   3
0   Eric   1   2      3   4
1  Sarah   5   6      7   8
2  Steve   9  10     11  12
3  David  13  14     15  16
4    Sam  17  18  strin  20
5    Joe  21  22     23  24

顺便说一句,它会发出警告:

SettingWithCopyWarning: A value is trying to be set on a copy of a slice from 
a DataFrame

如果有人知道如何避免警告请 lmk。我创建一个迭代器到 return str 在我想要的列中的位置:

for x in range(2,df.shape[1]):
    for y in range(df.shape[0]):
        if type(df.iloc[:,x][y]) == str:
            print('str:',(y,x))

有效。 returns str: (4, 3)。请问有没有更简单的方法呢

如果您知道只有 1 个有问题的字符串,最快的方法就是尝试使用 pd.to_numeric 进行转换,回溯包含索引:

>>> pd.to_numeric(df[2])
Traceback (most recent call last):
  File "pandas/_libs/src\inference.pyx", line 1021, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "strin"

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "...\lib\site-packages\pandas\core\tools\numeric.py", line 126, in to_numeric
    coerce_numeric=coerce_numeric)
  File "pandas/_libs/src\inference.pyx", line 1052, in pandas._libs.lib.maybe_convert_numeric
ValueError: Unable to parse string "strin" at position 4

不过,我相信这只会return第一次出现。所以我们可以强制错误,并找到结果 NaN:

>>> pd.to_numeric(df[2], errors='coerce').isnull()
0    False
1    False
2    False
3    False
4     True
5    False
Name: 2, dtype: bool

在索引 4 处找到有问题的字符串!这将允许您对 DataFrame 进行子集化以显示转换失败的所有字符串,只需将 bool 数组传递给 df[] 调用即可。

编辑:我意识到我没有涵盖可以在多个列中找到一个字符串的情况。为避免遍历列,您可以使用以下代码片段获取另一个 bool 数组:

import functools

df.loc[0, 1] = 'another_string'

df[[0,1,2,3]].apply(functools.partial(pd.to_numeric, errors='coerce')).isnull().any(axis=1)

0     True
1    False
2    False
3    False
4     True
5    False
dtype: bool

bool 数组传递给 df[] 调用打印:

   Name   0               1      2   3
0  Eric   1  another_string      3   4
4   Sam  17              18  strin  20

如果需要行、列坐标,使用np.where:

results = df[[0,1,2,3]].apply(functools.partial(pd.to_numeric, errors='coerce')).isnull()
np.where(results)

# returns both positions: (array([0, 4], dtype=int64), array([1, 2], dtype=int64))

或者,您可以迭代这些值,尝试转换为数字类型,从异常中获取有问题的字符串并查找它:

import re

r = re.compile("(?<=\')\w+(?=\')")

for row in df[2]:
    try:
        float(row)
    except ValueError as exc:
        matches = r.findall(str(exc))
        for m in matches:
            i = (df[2] == m).index
            print(f"Found string '{m}' at index {i}")

# prints:
# Found string 'strin' at index Int64Index([4], dtype='int64')

这似乎过于复杂了,但我想尝试一下:)。

最后,谈谈您收到的警告。以下代码不产生警告:

import pandas as pd

df = pd.DataFrame(np.arange(1,25).reshape(6,4))
Attribute = ['Eric', 'Sarah', 'Steve', 'David', 'Sam', 'Joe']
df.insert(0, 'Name', Attribute)
df.loc[4, 2] = 'strin' # no warning

当您调用 df[2][4] 时,您进行了两次调用:__getitem__(2) 和随后的 __getitem__(4),即所谓的 chained indexing,其中 df.loc[4, 2]只是一个电话。根据情况,这可能 return 是您的 DataFrame 的视图或副本,这会导致意外错误。此外,使用单个 .loc 调用可能会更快。请务必阅读文档以获得更详细的解释。