使用Idmax的Pandas错误地将混合对象列转换为浮点数

时间:2017-03-28 21:10:44

标签: python python-3.x pandas grouping

所以我的数据集中有各种各样的列,它们是整数和字符串的混合。尝试删除重复项,我将行中的每一列转换为字符串,获取它的长度,并将该长度添加为额外的列:

import pandas as pd
import datetime

r1 = [datetime.date(2016, 7, 10), 'M']
r2 = [datetime.date(2014, 11, 26), 0]
r3 = [datetime.date(2015, 8, 13), 'M']
r4 = [datetime.date(2015, 5, 11), 'OPSTC']
r5 = [datetime.date(2014, 1, 31), 'FMS']
df = pd.DataFrame([r1, r2, r3, r4, r5], columns=['date', 'mix'])
df['date'] = pd.to_datetime(df['date'])

def f(row):
    return(row.apply(lambda x: len(str(x))).sum())

df['width'] = df.apply(f, axis=1)
df

    date        mix     width
0   2016-07-10  M       20
1   2014-11-26  0       20
2   2015-08-13  M       20
3   2015-05-11  OPSTC   24
4   2014-01-31  FMS     22

for column in df.columns:
    print(column, df[column].dtype)

date  datetime64[ns]
mix   object
width int64

这不会造成任何问题。当我对行进行分组并消除那些没有最高行总数的行时,就会出现问题:

def f(rows):
    rows.applymap(str) # Even putting this in here has no effect!

    return(rows.ix[rows['width'].idxmax()])

df = df.groupby(['date'], as_index=False).apply(f)
df = df.reset_index(drop=True)
df

    date        mix width
0   2014-01-31  NaN 22
1   2014-11-26  0.0 20
2   2015-05-11  NaN 24
3   2015-08-13  NaN 20
4   2016-07-10  NaN 20

它将混合对象列转换为浮点数。您可以按混合或日期分组以重现问题。将列转换为字符串(使用.apply(str).astype(str))无效。

我使用的是Python 3.5.2.final.0和Pandas 0.18.1。

1 个答案:

答案 0 :(得分:1)

这里有几点失败

  • 未能分配给变量

    def f(rows):
        rows.applymap(str)  # this doesn't get assigned
        return rows.ix[rows['width'].idxmax()]
    
  • 请勿使用ix。在这里没有任何影响。但它将被弃用。

  • 超级微妙且危险的一点...... row.ix[rows['width'].idxmax()]会返回pd.Series。为什么这很重要?目前我无法确定整个故事(我正在研究它)。但是,当您返回时,pd.Series pandas正在进行一些推理,并确定'mix'应该是数字。 apply对象的groupby方法将pd.DataFrame对象传递给正在应用的函数。您可以通过将标量rows['width'].idxmax()更改为类似数组的[rows['width'].idxmax()]

    来解决此问题
    def f(rows):
        return rows.loc[[rows['width'].idxmax()]] 
    
    print(df.groupby(['date'], as_index=False).apply(f))
    
               date    mix  width
    0 4 2014-01-31    FMS     22
    1 1 2014-11-26      0     20
    2 3 2015-05-11  OPSTC     24
    3 2 2015-08-13      M     20
    4 0 2016-07-10      M     20
    
  • 好的,所以dtypes再次有意义,但你没有消除任何东西,因为你按date分组,其中所有都是唯一的。不知道你想要什么,但这是猜测。

    df.query('width == @df.width.max()')
    # equivalently
    # df[df.width == df.width.max()]  
    
            date    mix  width
    3 2015-05-11  OPSTC     24