Pandas apply和map方法应用于每个列的每个元素

4

如何将自定义函数应用于每列的每个元素,如果该值不为null?

假设我有一个由10列组成的数据框,其中我想对其中4列的每个元素应用lower()函数,如果pd.notnull(x),否则只保留值为none。

我尝试像这样使用:

s.apply(lambda x: change_to_lowercase(x), axis = 1)

def change_to_lowercase(s):

    s['A'] =  s['A'].map(lambda x: x.lower() if pd.notnull(x) else x)
    s['B'] = s['B'].map(lambda x: x.lower() if pd.notnull(x) else x)
    s['C'] = s['C'].map(lambda x: x.lower() if pd.notnull(x) else x)
    s['D'] = s['D'].map(lambda x: x.lower() if pd.notnull(x) else x)
    return s

但是由于我的列是混合数据类型(NaN为浮点数,其余为Unicode),这导致了错误 -

float has no attribute map.

如何摆脱这个错误?
2个回答

5

我认为你需要使用DataFrame.applymap,因为它可以对数据框的每个元素进行操作:

L = [[1.5, 'Test', np.nan, 2], ['Test', np.nan, 2,'TEST'], ['Test', np.nan,1.5,  2]]
df = pd.DataFrame(L, columns=list('abcd'))
print (df)

      a     b    c     d
0   1.5  Test  NaN     2
1  Test   NaN  2.0  TEST
2  Test   NaN  1.5     2

cols = ['a','b']
#for python 2 change str to basestring
df[cols] = df[cols].applymap(lambda x: x.lower() if isinstance(x, str) else x)
print (df)
      a     b    c     d
0   1.5  test  NaN     2
1  test   NaN  2.0  TEST
2  test   NaN  1.5     2

0
你正在尝试映射一个Series,然后在lambda函数中获取整行数据。
你还应该检查整数、浮点数等是否没有.lower()方法。所以,在我看来,最好的做法是检查它是否为字符串,而不仅仅是检查它是否非空。
以下代码可以实现这个功能:
s = pd.DataFrame([{'A': 1.5, 'B':"Test", 'C': np.nan, 'D':2}])
s

        A   B   C   D
0   1.5 Test    NaN 2



s1 = s.apply(lambda x: x[0].lower() if isinstance(x[0], basestring) else x[0]).copy()

s1
    A     1.5
    B    test
    C     NaN
    D       2
    dtype: object

对于 Python 3,检查字符串是否为 isinstance(x[0], str)

为了能够选择列:

s1 = pd.DataFrame()
columns = ["A", "B"]
for column in columns:
    s1[column] = s[column].apply(lambda x: x.lower() if isinstance(x, str) else x).copy()
s1

    A   B
0   1.5 test

谢谢。这很有道理。我如何仅将其应用于数据框中的某些列? - ds_user

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