Series [] 和 .loc[] 有时返回单个值,有时意外地返回包含相同值的单个元素 Series。

4
在下面的代码中,我试图找到DataFrame列中最长的字符串。
根据列的长度,下面的函数(maxstr)返回短列的单个值(如预期),并返回长列的单个元素系列(我没有预料到这一点)。
任何指针都将不胜感激。
我使用了Pandas dataframe列中查找最长字符串的长度中讨论的方法。
import numpy as np
import pandas as pd

由于数据量较大,我倾向于在处理过程中逐步显示数据框和系列信息。

从剪贴板读取数据框

df = pd.read_clipboard(sep='\t', index_col=[0, 1, 2, 3, 4], na_values='')

print(f'{type(df)=}')
print(f'{df.shape=}')
print(f'{df.dtypes=}')
print(f'{df.columns=}')

type(df)=<class 'pandas.core.frame.DataFrame'>
df.shape=(581, 6)
df.dtypes=CID           int64
TITLE        object
FIRSTNAME    object
FUNCTION     object
PHONE        object
EMAIL        object
dtype: object
df.columns=Index(['CID', 'TITLE', 'FIRSTNAME', 'FUNCTION', 'PHONE', 'EMAIL'], dtype='object')

函数返回列/系列中最长字符串的等效值
def maxstr(ser: pd.Series):
    print(f'{type(ser)=}')

    print(f'\n{type(ser.astype(str).str.len().idxmax())=}')
    print(f'{type(ser[ser.astype(str).str.len().idxmax()])=}')

    # should return a single value and not a series
    return ser[ser.astype(str).str.len().idxmax()]


使用短列(n=50)进行操作,我得到了一个整数(如预期)。
short = df.head(50)
short_return = maxstr(short['CID'])

type(ser)=<class 'pandas.core.series.Series'>

type(ser.astype(str).str.len().idxmax())=<class 'tuple'>
type(ser[ser.astype(str).str.len().idxmax()])=<class 'numpy.int64'>

使用相同的数据框(相同的数据)中的长列(n=100),我得到了一个系列(意料之外?)
long = df.head(100)
long_return = maxstr(long['CID'])

type(ser)=<class 'pandas.core.series.Series'>
    
type(ser.astype(str).str.len().idxmax())=<class 'tuple'>
type(ser[ser.astype(str).str.len().idxmax()])=<class 'pandas.core.series.Series'>

在这两种情况下,我们找到了相同的整数值(但一个是作为一系列中的一个值,另一个是作为单个值)。
short_return == long_return.iloc[0]

True

整数值是唯一的,因此在数据框列中只出现一次

value = short_return
print(f'The value: {value=}')
print(f'{sum(short["CID"] == value)=}')
print(f'{sum(long["CID"] == value)=}')

The value: value=1937
sum(short["CID"] == value)=1
sum(long["CID"] == value)=1

1
这个问题有5个屏幕那么长,请将其缩减为绝对最少的代码行数[mcve]。理想情况下,如果您有5个示例,则应该是5行长。 (我们不需要任何打印输出,文档字符串或注释。) - smci
谢谢,我会尝试缩短它。 - alant
1个回答

2

我认为问题出在重复的索引值,所以如果idxmax返回一个重复的元组,则会返回所有选择中的重复行而不是标量。

避免这个问题的简单解决方案是创建默认索引,这里需要进行更改:

df = pd.read_clipboard(sep='\t', index_col=[0, 1, 2, 3, 4], na_values='')

to:

df = pd.read_clipboard(sep='\t', na_values='')

如果没有MultiIndex,则默认为RangeIndex

如果是RangeIndex,请检查它:

print (df.index)

如果需要使用MultiIndex,解决方案是去除重复的值:

df = pd.read_clipboard(sep='\t', index_col=[0, 1, 2, 3, 4], na_values='')
df = df[~df.index.duplicated()]

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