在pd.DataFrame中获取所有str类型的元素

4
基于我对pandas的有限了解,pandas.Series.str.contains可以在pd.Series中搜索特定字符串。但是如果数据框很大,而我只想在做任何操作之前浏览其中所有种类的str元素怎么办?
例如像这样的示例:
pd.DataFrame({'x1':[1,2,3,'+'],'x2':[2,'a','c','this is']})
    x1  x2
0   1   2
1   2   a
2   3   c
3   +   this is

我需要一个函数来返回['+','a','c','this is']
4个回答

3

有两种可能的方法 - 检查保存为字符串的数字值或不检查。

检查差异:

df = pd.DataFrame({'x1':[1,'2.78','3','+'],'x2':[2.8,'a','c','this is'], 'x3':[1,4,5,4]}) 
print (df)
     x1       x2  x3
0     1      2.8   1
1  2.78        a   4 <-2.78 is float saved as string
2     3        c   5 <-3 is int saved as string
3     +  this is   4

#flatten all values
ar = df.values.ravel()
#errors='coerce' parameter in pd.to_numeric return NaNs for non numeric
L = np.unique(ar[np.isnan(pd.to_numeric(ar, errors='coerce'))]).tolist()
print (L)
['+', 'a', 'c', 'this is']

另一个解决方案是使用自定义函数来检查是否可以转换为浮点数:

def is_not_float_try(str):
    try:
        float(str)
        return False
    except ValueError:
        return True

s = df.stack()
L = s[s.apply(is_not_float_try)].unique().tolist()
print (L)
['a', 'c', '+', 'this is']

如果需要将所有值保存为字符串,请使用isinstance

s = df.stack()
L = s[s.apply(lambda x: isinstance(x, str))].unique().tolist()
print (L)
['2.78', 'a', '3', 'c', '+', 'this is']

这是我认为最好的方式。 - Ami Tavory
@AmiTavory - 谢谢。 - jezrael
这很优雅。我使用了 df.apply(lambda x:pd.to_numeric(x,errors='ignore')) 将类似于 '1.23' 的字符串数字转换为 1.23,所以我可以告诉你的函数在这个例子上会起作用。但是如果数据框中有列表元素,np.unique() 可能会失败。我会投票支持你。 - Garvey
@Garvey - 谢谢。np.unique应该被省略,它不是必要的。 - jezrael
@Garvey - 我在思考如果使用errors='ignore',如何检查数字?因为如果使用errors='coerce',它会创建NaN并且可以检查它。 - jezrael
1
@jezrael 嗯,我故意设置了errors=ignore来先将像'1.23'这样的内容转换为1.23,这与问题无关。之后,我意识到有必要查看数据框中仍包含哪些字符串类型。 - Garvey

3

如果您只考虑字符串值而不关心性能,那么这是一个非常简单的答案。

df.where(df.applymap(type).eq(str)).stack().tolist()

['a', 'c', '+', 'this is']

2
您可以使用 str.isdigitunstack
df[df.apply(lambda x : x.str.isdigit()).eq(0)].unstack().dropna().tolist()
Out[242]: ['+', 'a', 'c', 'this is']

2
使用正则表达式和集合并运算,可以尝试类似以下的方式:
>>> set.union(*[set(df[c][~df[c].str.findall('[^\d]+').isnull()].unique()) for c in df.columns])
{'+', 'a', 'c', 'this is'}

如果您使用一般数字的正则表达式, 您也可以省略浮点数。

1
很高兴看到你回答问题 (-: - piRSquared
@piRSquared 你也是!你的声望已经大大地增长了! - Ami Tavory

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接