58_Pandas中mode获取pandas的每一行和列

使用pandas.Series和pandas.DataFrame的mode()方法,可以得到每一列每一行的mode。

在此,对以下内容进行说明。

  • pandas.Series 中的mode()
  • pandas.DataFrame 中的mode()
  • 按列获取模式
  • 每行获取模式
  • 获取模式的频率(出现次数)

pandas.Series 中的mode()

从 pandas.Series 调用 mode() 返回 pandas.Series。

import pandas as pd

s = pd.Series(['X', 'X', 'Y', 'X'])
print(s)
# 0    X
# 1    X
# 2    Y
# 3    X
# dtype: object

print(s.mode())
# 0    X
# dtype: object

print(type(s.mode()))
# <class 'pandas.core.series.Series'>

pandas.Series 的元素是模式本身的值。

mode_value = s.mode()[0]
print(mode_value)
# X

print(type(mode_value))
# <class 'str'>

如果有多种模式,则:

s_same = pd.Series(['X', 'Y', 'Y', 'X'])
print(s_same)
# 0    X
# 1    Y
# 2    Y
# 3    X
# dtype: object

print(s_same.mode())
# 0    X
# 1    Y
# dtype: object

print(s_same.mode()[0])
# X

如果要获取最频繁值的列表,请使用 tolist() 方法。

l_modes = s_same.mode().tolist()
print(l_modes)
# ['X', 'Y']

print(type(l_modes))
# <class 'list'>

pandas.DataFrame 中的mode()

pandas.DataFrame 也有一个 mode() 方法。
以下面的 pandas.DataFrame 为例。

df = pd.DataFrame({'col1': ['X', 'X', 'Y', 'X'],
                   'col2': ['X', 'Y', 'Y', 'X']},
                  index=['row1', 'row2', 'row3', 'row4'])
print(df)
#      col1 col2
# row1    X    X
# row2    X    Y
# row3    Y    Y
# row4    X    X

按列获取模式

从pandas.DataFrame调用mode()方法返回一个pandas.DataFrame,其元素默认为每一列的众数值。请注意,即使只有一种模式,也会返回一行的 pandas.DataFrame,如上面的 pandas.Series 示例所示。

如果模式数因列而异,则空白部分将成为缺失值 NaN。

print(df.mode())
#   col1 col2
# 0    X    X
# 1  NaN    Y

print(type(df.mode()))
# <class 'pandas.core.frame.DataFrame'>

可以通过count()方法获取每一列中模态值的个数,该方法统计的是不为缺失值NaN的元素个数。

print(df.mode().count())
# col1    1
# col2    2
# dtype: int64

生成的 pandas.DataFrame 的第一行将是每列的模式(如果有多个,则为其中一个)。第一行可以通过iloc[0]获得。

  • 04_Pandas获取和修改任意位置的值(at,iat,loc,iloc)
print(df.mode().iloc[0])
# col1    X
# col2    X
# Name: 0, dtype: object

从pandas.DataFrame中调用mode()选择列可能会包含缺失值NaN,但是先选择列再调用mode()作为pandas.Series是不包含缺失值NaN的

print(df.mode()['col1'])
# 0      X
# 1    NaN
# Name: col1, dtype: object

print(df['col1'].mode())
# 0    X
# dtype: object

它可能不是很有用,但是如果你用 apply() 方法从每一列调用 mode() 并用 tolist() 列出它,也可以得到一个以列表(列表类型)作为元素的 pandas.Series。

l_mode = df.apply(lambda x: x.mode().tolist())
print(l_mode)
# col1       [X]
# col2    [X, Y]
# dtype: object

print(l_mode.iat[1])
# ['X', 'Y']

print(type(l_mode.iat[1]))
# <class 'list'>

print(l_mode.iat[1][1])
# Y

print(type(l_mode.iat[1][1]))
# <class 'str'>

此时,生成的 pandas.Series 的行名索引变成了原始 pandas.DataFrame 的列名。注意,如果原来的列名是数字,选择结果pandas.Series的值为[number]会报错,必须是iat[number]。例子中是字符串,所以[Number]没有问题。

每行获取模式

如果设置参数 axis=1,则可以获得每一行的模式。

print(df.mode(axis=1))
#       0    1
# row1  X  NaN
# row2  X    Y
# row3  Y  NaN
# row4  X  NaN

计数不是缺失值 NaN 的元素数量的 count() 方法也有一个参数轴。

print(df.mode(axis=1).count(axis=1))
# row1    1
# row2    2
# row3    1
# row4    1
# dtype: int64

在 pandas 中,每一列都有一个类型 dtype,所以基本上假设每一列都排列了相同类型的数据。

因此,通常不需要获取每一行的众数,如果每一行排列的是同类数据,转置可能会更好。

df_t = df.T
print(df_t)
#      row1 row2 row3 row4
# col1    X    X    Y    X
# col2    X    Y    Y    X

print(df_t.mode())
#   row1 row2 row3 row4
# 0    X    X    Y    X
# 1  NaN    Y  NaN  NaN

获取模式的频率(出现次数)

可以使用 pandas.Series 的 value_counts() 方法获取模式的频率(出现次数)。

value_counts() 返回一个 pandas.Series,其唯一元素值为 index,其频率(出现次数)为 data。

默认情况下,pandas.Series 按出现的降序排序,因此 value_counts() 方法返回的 pandas.Series 中的第一个值是模式的频率。

print(df['col1'].value_counts())
# X    3
# Y    1
# Name: col1, dtype: int64

print(df['col1'].value_counts().iat[0])
# 3

原始 pandas.Series 的元素成为生成的 pandas.Series 的索引。如果数值为index,则不能用[number]指定值(会报错),所以使用iat [number]严格指定。 (由于上面的例子是字符串,所以[number]是没有问题的)

使用 apply() 获取每列模式的频率。

print(df.apply(lambda x: x.value_counts().iat[0]))
# col1    3
# col2    2
# dtype: int64

describe() 方法计算每一列的汇总统计信息,还获取众数及其频率。

print(df.describe())
#        col1 col2
# count     4    4
# unique    2    2
# top       X    Y
# freq      3    2

项目 top 是模式, freq 是它的频率。如果有多种模式,则只返回其中一种。结果是一个 pandas.DataFrame,因此您可以使用 loc、at 等获取行和元素。

print(df.describe().loc['freq'])
# col1    3
# col2    2
# Name: freq, dtype: object

print(df.describe().at['freq', 'col2'])
# 2

describe() 没有参数轴,因此如果要将它应用于一条线,请在调用它之前转置它。

print(df.T.describe())
#        row1 row2 row3 row4
# count     2    2    2    2
# unique    1    2    1    1
# top       X    Y    Y    X
# freq      2    1    2    2