Pandas 2.2 中文官方教程和指南(十四)(4)

简介: Pandas 2.2 中文官方教程和指南(十四)

Pandas 2.2 中文官方教程和指南(十四)(3)https://developer.aliyun.com/article/1509845

melt()wide_to_long()


顶级melt()函数及其对应的DataFrame.melt()对于将DataFrame整理成一个格式很有用,其中一个或多个列是标识变量,而所有其他列,被认为是测量变量,都被“展开”到行轴上,仅留下两个非标识列,“变量”和“值”。这些列的名称可以通过提供 var_namevalue_name 参数进行自定义。

In [47]: cheese = pd.DataFrame(
 ....:    {
 ....:        "first": ["John", "Mary"],
 ....:        "last": ["Doe", "Bo"],
 ....:        "height": [5.5, 6.0],
 ....:        "weight": [130, 150],
 ....:    }
 ....: )
 ....: 
In [48]: cheese
Out[48]: 
 first last  height  weight
0  John  Doe     5.5     130
1  Mary   Bo     6.0     150
In [49]: cheese.melt(id_vars=["first", "last"])
Out[49]: 
 first last variable  value
0  John  Doe   height    5.5
1  Mary   Bo   height    6.0
2  John  Doe   weight  130.0
3  Mary   Bo   weight  150.0
In [50]: cheese.melt(id_vars=["first", "last"], var_name="quantity")
Out[50]: 
 first last quantity  value
0  John  Doe   height    5.5
1  Mary   Bo   height    6.0
2  John  Doe   weight  130.0
3  Mary   Bo   weight  150.0 

使用melt()转换 DataFrame 时,索引会被忽略。通过将 ignore_index=False 参数设置为 False(默认为 True),可以保留原始索引值。ignore_index=False 会导致索引值重复。

In [51]: index = pd.MultiIndex.from_tuples([("person", "A"), ("person", "B")])
In [52]: cheese = pd.DataFrame(
 ....:    {
 ....:        "first": ["John", "Mary"],
 ....:        "last": ["Doe", "Bo"],
 ....:        "height": [5.5, 6.0],
 ....:        "weight": [130, 150],
 ....:    },
 ....:    index=index,
 ....: )
 ....: 
In [53]: cheese
Out[53]: 
 first last  height  weight
person A  John  Doe     5.5     130
 B  Mary   Bo     6.0     150
In [54]: cheese.melt(id_vars=["first", "last"])
Out[54]: 
 first last variable  value
0  John  Doe   height    5.5
1  Mary   Bo   height    6.0
2  John  Doe   weight  130.0
3  Mary   Bo   weight  150.0
In [55]: cheese.melt(id_vars=["first", "last"], ignore_index=False)
Out[55]: 
 first last variable  value
person A  John  Doe   height    5.5
 B  Mary   Bo   height    6.0
 A  John  Doe   weight  130.0
 B  Mary   Bo   weight  150.0 

wide_to_long() 类似于 melt() ,但具有更多的列匹配自定义选项。

In [56]: dft = pd.DataFrame(
 ....:    {
 ....:        "A1970": {0: "a", 1: "b", 2: "c"},
 ....:        "A1980": {0: "d", 1: "e", 2: "f"},
 ....:        "B1970": {0: 2.5, 1: 1.2, 2: 0.7},
 ....:        "B1980": {0: 3.2, 1: 1.3, 2: 0.1},
 ....:        "X": dict(zip(range(3), np.random.randn(3))),
 ....:    }
 ....: )
 ....: 
In [57]: dft["id"] = dft.index
In [58]: dft
Out[58]: 
 A1970 A1980  B1970  B1980         X  id
0     a     d    2.5    3.2  1.519970   0
1     b     e    1.2    1.3 -0.493662   1
2     c     f    0.7    0.1  0.600178   2
In [59]: pd.wide_to_long(dft, ["A", "B"], i="id", j="year")
Out[59]: 
 X  A    B
id year 
0  1970  1.519970  a  2.5
1  1970 -0.493662  b  1.2
2  1970  0.600178  c  0.7
0  1980  1.519970  d  3.2
1  1980 -0.493662  e  1.3
2  1980  0.600178  f  0.1 

get_dummies()from_dummies()

Series的分类变量转换为“虚拟”或“指示符”时,get_dummies()会创建一个新的DataFrame,其中包含唯一变量的列,值表示每行中这些变量的存在情况。

In [60]: df = pd.DataFrame({"key": list("bbacab"), "data1": range(6)})
In [61]: pd.get_dummies(df["key"])
Out[61]: 
 a      b      c
0  False   True  False
1  False   True  False
2   True  False  False
3  False  False   True
4   True  False  False
5  False   True  False
In [62]: df["key"].str.get_dummies()
Out[62]: 
 a  b  c
0  0  1  0
1  0  1  0
2  1  0  0
3  0  0  1
4  1  0  0
5  0  1  0 

prefix 为列名添加一个前缀,这对于将结果与原始DataFrame合并很有用:

In [63]: dummies = pd.get_dummies(df["key"], prefix="key")
In [64]: dummies
Out[64]: 
 key_a  key_b  key_c
0  False   True  False
1  False   True  False
2   True  False  False
3  False  False   True
4   True  False  False
5  False   True  False
In [65]: df[["data1"]].join(dummies)
Out[65]: 
 data1  key_a  key_b  key_c
0      0  False   True  False
1      1  False   True  False
2      2   True  False  False
3      3  False  False   True
4      4   True  False  False
5      5  False   True  False 

这个函数经常与诸如 cut() 这样的离散化函数一起使用:

In [66]: values = np.random.randn(10)
In [67]: values
Out[67]: 
array([ 0.2742,  0.1329, -0.0237,  2.4102,  1.4505,  0.2061, -0.2519,
 -2.2136,  1.0633,  1.2661])
In [68]: bins = [0, 0.2, 0.4, 0.6, 0.8, 1]
In [69]: pd.get_dummies(pd.cut(values, bins))
Out[69]: 
 (0.0, 0.2]  (0.2, 0.4]  (0.4, 0.6]  (0.6, 0.8]  (0.8, 1.0]
0       False        True       False       False       False
1        True       False       False       False       False
2       False       False       False       False       False
3       False       False       False       False       False
4       False       False       False       False       False
5       False        True       False       False       False
6       False       False       False       False       False
7       False       False       False       False       False
8       False       False       False       False       False
9       False       False       False       False       False 

get_dummies() 也接受一个DataFrame。默认情况下,objectstringcategorical类型的列会被编码为虚拟变量,其他列不变。

In [70]: df = pd.DataFrame({"A": ["a", "b", "a"], "B": ["c", "c", "b"], "C": [1, 2, 3]})
In [71]: pd.get_dummies(df)
Out[71]: 
 C    A_a    A_b    B_b    B_c
0  1   True  False  False   True
1  2  False   True  False   True
2  3   True  False   True  False 

指定 columns 关键字会编码任何类型的列。

In [72]: pd.get_dummies(df, columns=["A"])
Out[72]: 
 B  C    A_a    A_b
0  c  1   True  False
1  c  2  False   True
2  b  3   True  False 

Series版本一样,可以为 prefixprefix_sep 传递值。默认情况下,列名用作前缀,_ 用作前缀分隔符。可以以 3 种方式指定 prefixprefix_sep

  • 字符串:对于要编码的每列,使用相同的值作为 prefixprefix_sep
  • 列表:必须与被编码的列数相同。
  • 字典:将列名映射到前缀。
In [73]: simple = pd.get_dummies(df, prefix="new_prefix")
In [74]: simple
Out[74]: 
 C  new_prefix_a  new_prefix_b  new_prefix_b  new_prefix_c
0  1          True         False         False          True
1  2         False          True         False          True
2  3          True         False          True         False
In [75]: from_list = pd.get_dummies(df, prefix=["from_A", "from_B"])
In [76]: from_list
Out[76]: 
 C  from_A_a  from_A_b  from_B_b  from_B_c
0  1      True     False     False      True
1  2     False      True     False      True
2  3      True     False      True     False
In [77]: from_dict = pd.get_dummies(df, prefix={"B": "from_B", "A": "from_A"})
In [78]: from_dict
Out[78]: 
 C  from_A_a  from_A_b  from_B_b  from_B_c
0  1      True     False     False      True
1  2     False      True     False      True
2  3      True     False      True     False 

在将结果提供给统计模型时,为避免共线性,请指定 drop_first=True

In [79]: s = pd.Series(list("abcaa"))
In [80]: pd.get_dummies(s)
Out[80]: 
 a      b      c
0   True  False  False
1  False   True  False
2  False  False   True
3   True  False  False
4   True  False  False
In [81]: pd.get_dummies(s, drop_first=True)
Out[81]: 
 b      c
0  False  False
1   True  False
2  False   True
3  False  False
4  False  False 

当列只包含一个级别时,结果中将省略该列。

In [82]: df = pd.DataFrame({"A": list("aaaaa"), "B": list("ababc")})
In [83]: pd.get_dummies(df)
Out[83]: 
 A_a    B_a    B_b    B_c
0  True   True  False  False
1  True  False   True  False
2  True   True  False  False
3  True  False   True  False
4  True  False  False   True
In [84]: pd.get_dummies(df, drop_first=True)
Out[84]: 
 B_b    B_c
0  False  False
1   True  False
2  False  False
3   True  False
4  False   True 

可以使用 dtype 参数将值转换为不同类型。

In [85]: df = pd.DataFrame({"A": list("abc"), "B": [1.1, 2.2, 3.3]})
In [86]: pd.get_dummies(df, dtype=np.float32).dtypes
Out[86]: 
B      float64
A_a    float32
A_b    float32
A_c    float32
dtype: object 

版本 1.5.0 中的新功能。

from_dummies()get_dummies() 的输出转换回指示值的分类值 Series

In [87]: df = pd.DataFrame({"prefix_a": [0, 1, 0], "prefix_b": [1, 0, 1]})
In [88]: df
Out[88]: 
 prefix_a  prefix_b
0         0         1
1         1         0
2         0         1
In [89]: pd.from_dummies(df, sep="_")
Out[89]: 
 prefix
0      b
1      a
2      b 

虚拟编码数据只需要包含 k - 1 个类别,此时最后一个类别是默认类别。默认类别可以使用 default_category 修改。

In [90]: df = pd.DataFrame({"prefix_a": [0, 1, 0]})
In [91]: df
Out[91]: 
 prefix_a
0         0
1         1
2         0
In [92]: pd.from_dummies(df, sep="_", default_category="b")
Out[92]: 
 prefix
0      b
1      a
2      b 

explode()

对于具有嵌套、类似列表的值的 DataFrame 列,explode() 将每个类似列表的值转换为单独的行。生成的 Index 将根据原始行的索引标签重复:

In [93]: keys = ["panda1", "panda2", "panda3"]
In [94]: values = [["eats", "shoots"], ["shoots", "leaves"], ["eats", "leaves"]]
In [95]: df = pd.DataFrame({"keys": keys, "values": values})
In [96]: df
Out[96]: 
 keys            values
0  panda1    [eats, shoots]
1  panda2  [shoots, leaves]
2  panda3    [eats, leaves]
In [97]: df["values"].explode()
Out[97]: 
0      eats
0    shoots
1    shoots
1    leaves
2      eats
2    leaves
Name: values, dtype: object 

DataFrame.explode 也可以将 DataFrame 中的列扩展。

In [98]: df.explode("values")
Out[98]: 
 keys  values
0  panda1    eats
0  panda1  shoots
1  panda2  shoots
1  panda2  leaves
2  panda3    eats
2  panda3  leaves 

Series.explode() 将空列表替换为缺失值指示符,并保留标量条目。

In [99]: s = pd.Series([[1, 2, 3], "foo", [], ["a", "b"]])
In [100]: s
Out[100]: 
0    [1, 2, 3]
1          foo
2           []
3       [a, b]
dtype: object
In [101]: s.explode()
Out[101]: 
0      1
0      2
0      3
1    foo
2    NaN
3      a
3      b
dtype: object 

逗号分隔的字符串值可以拆分为列表中的单个值,然后扩展到新行。

In [102]: df = pd.DataFrame([{"var1": "a,b,c", "var2": 1}, {"var1": "d,e,f", "var2": 2}])
In [103]: df.assign(var1=df.var1.str.split(",")).explode("var1")
Out[103]: 
 var1  var2
0    a     1
0    b     1
0    c     1
1    d     2
1    e     2
1    f     2 

crosstab()

使用 crosstab() 计算两个(或更多)因子的交叉制表。默认情况下,crosstab() 计算因子的频率表,除非传递了值数组和聚合函数。

任何传递的 Series 将使用其名称属性,除非为交叉制表指定了行或列名称

In [104]: a = np.array(["foo", "foo", "bar", "bar", "foo", "foo"], dtype=object)
In [105]: b = np.array(["one", "one", "two", "one", "two", "one"], dtype=object)
In [106]: c = np.array(["dull", "dull", "shiny", "dull", "dull", "shiny"], dtype=object)
In [107]: pd.crosstab(a, [b, c], rownames=["a"], colnames=["b", "c"])
Out[107]: 
b    one        two 
c   dull shiny dull shiny
a 
bar    1     0    0     1
foo    2     1    1     0 

如果 crosstab() 只接收两个 Series,它将提供一个频率表。

In [108]: df = pd.DataFrame(
 .....:    {"A": [1, 2, 2, 2, 2], "B": [3, 3, 4, 4, 4], "C": [1, 1, np.nan, 1, 1]}
 .....: )
 .....: 
In [109]: df
Out[109]: 
 A  B    C
0  1  3  1.0
1  2  3  1.0
2  2  4  NaN
3  2  4  1.0
4  2  4  1.0
In [110]: pd.crosstab(df["A"], df["B"])
Out[110]: 
B  3  4
A 
1  1  0
2  1  3 

crosstab() 还可以总结为Categorical数据。

In [111]: foo = pd.Categorical(["a", "b"], categories=["a", "b", "c"])
In [112]: bar = pd.Categorical(["d", "e"], categories=["d", "e", "f"])
In [113]: pd.crosstab(foo, bar)
Out[113]: 
col_0  d  e
row_0 
a      1  0
b      0  1 

对于Categorical数据,要包含所有数据类别,即使实际数据不包含特定类别的任何实例,使用dropna=False

In [114]: pd.crosstab(foo, bar, dropna=False)
Out[114]: 
col_0  d  e  f
row_0 
a      1  0  0
b      0  1  0
c      0  0  0 

标准化

频率表也可以通过normalize参数显示百分比而不是计数:

In [115]: pd.crosstab(df["A"], df["B"], normalize=True)
Out[115]: 
B    3    4
A 
1  0.2  0.0
2  0.2  0.6 

normalize还可以在每行或每列内规范化值:

In [116]: pd.crosstab(df["A"], df["B"], normalize="columns")
Out[116]: 
B    3    4
A 
1  0.5  0.0
2  0.5  1.0 

crosstab() 还可以接受第三个Series和一个聚合函数(aggfunc),该函数将应用于第三个Series的值,这些值在由前两个Series定义的每个组内:

In [117]: pd.crosstab(df["A"], df["B"], values=df["C"], aggfunc="sum")
Out[117]: 
B    3    4
A 
1  1.0  NaN
2  1.0  2.0 

添加边际

margins=True 将添加一个带有All标签的行和列,该标签在行和列上的类别中部分组聚合:

In [118]: pd.crosstab(
 .....:    df["A"], df["B"], values=df["C"], aggfunc="sum", normalize=True, margins=True
 .....: )
 .....: 
Out[118]: 
B       3    4   All
A 
1    0.25  0.0  0.25
2    0.25  0.5  0.75
All  0.50  0.5  1.00 

标准化

频率表也可以通过normalize参数显示百分比而不是计数:

In [115]: pd.crosstab(df["A"], df["B"], normalize=True)
Out[115]: 
B    3    4
A 
1  0.2  0.0
2  0.2  0.6 

normalize还可以在每行或每列内规范化值:

In [116]: pd.crosstab(df["A"], df["B"], normalize="columns")
Out[116]: 
B    3    4
A 
1  0.5  0.0
2  0.5  1.0 

crosstab() 还可以接受第三个Series和一个聚合函数(aggfunc),该函数将应用于第三个Series的值,这些值在由前两个Series定义的每个组内:

In [117]: pd.crosstab(df["A"], df["B"], values=df["C"], aggfunc="sum")
Out[117]: 
B    3    4
A 
1  1.0  NaN
2  1.0  2.0 

添加边际

margins=True 将添加一个带有All标签的行和列,该标签在行和列上的类别中部分组聚合:

In [118]: pd.crosstab(
 .....:    df["A"], df["B"], values=df["C"], aggfunc="sum", normalize=True, margins=True
 .....: )
 .....: 
Out[118]: 
B       3    4   All
A 
1    0.25  0.0  0.25
2    0.25  0.5  0.75
All  0.50  0.5  1.00 

cut()

cut() 函数计算输入数组的值的分组,并经常用于将连续变量转换为离散或分类变量:

整数bins将形成等宽箱。

In [119]: ages = np.array([10, 15, 13, 12, 23, 25, 28, 59, 60])
In [120]: pd.cut(ages, bins=3)
Out[120]: 
[(9.95, 26.667], (9.95, 26.667], (9.95, 26.667], (9.95, 26.667], (9.95, 26.667], (9.95, 26.667], (26.667, 43.333], (43.333, 60.0], (43.333, 60.0]]
Categories (3, interval[float64, right]): [(9.95, 26.667] < (26.667, 43.333] < (43.333, 60.0]] 

一个有序的箱边列表将为每个变量分配一个区间。

In [121]: pd.cut(ages, bins=[0, 18, 35, 70])
Out[121]: 
[(0, 18], (0, 18], (0, 18], (0, 18], (18, 35], (18, 35], (18, 35], (35, 70], (35, 70]]
Categories (3, interval[int64, right]): [(0, 18] < (18, 35] < (35, 70]] 

如果bins关键字是一个IntervalIndex,那么这些将用于对传递的数据进行分箱。

In [122]: pd.cut(ages, bins=pd.IntervalIndex.from_breaks([0, 40, 70]))
Out[122]: 
[(0, 40], (0, 40], (0, 40], (0, 40], (0, 40], (0, 40], (0, 40], (40, 70], (40, 70]]
Categories (2, interval[int64, right]): [(0, 40] < (40, 70]] 

factorize()

factorize() 将一维数值编码为整数标签。缺失值被编码为-1

In [123]: x = pd.Series(["A", "A", np.nan, "B", 3.14, np.inf])
In [124]: x
Out[124]: 
0       A
1       A
2     NaN
3       B
4    3.14
5     inf
dtype: object
In [125]: labels, uniques = pd.factorize(x)
In [126]: labels
Out[126]: array([ 0,  0, -1,  1,  2,  3])
In [127]: uniques
Out[127]: Index(['A', 'B', 3.14, inf], dtype='object') 

Categorical 会类似地对一维值进行编码,以进行更多的分类操作。

In [128]: pd.Categorical(x)
Out[128]: 
['A', 'A', NaN, 'B', 3.14, inf]
Categories (4, object): [3.14, inf, 'A', 'B'] 


相关文章
|
20天前
|
SQL 数据采集 数据挖掘
Pandas 教程
10月更文挑战第25天
28 2
|
3月前
|
存储 JSON 数据格式
Pandas 使用教程 CSV - CSV 转 JSON
Pandas 使用教程 CSV - CSV 转 JSON
38 0
|
3月前
|
JSON 数据格式 Python
Pandas 使用教程 JSON
Pandas 使用教程 JSON
42 0
|
3月前
|
SQL 数据采集 JSON
Pandas 使用教程 Series、DataFrame
Pandas 使用教程 Series、DataFrame
68 0
|
5月前
|
数据采集 存储 数据可视化
Pandas高级教程:数据清洗、转换与分析
Pandas是Python的数据分析库,提供Series和DataFrame数据结构及数据分析工具,便于数据清洗、转换和分析。本教程涵盖Pandas在数据清洗(如缺失值、重复值和异常值处理)、转换(数据类型转换和重塑)和分析(如描述性统计、分组聚合和可视化)的应用。通过学习Pandas,用户能更高效地处理和理解数据,为数据分析任务打下基础。
650 3
|
6月前
|
索引 Python
Pandas 2.2 中文官方教程和指南(一)(4)
Pandas 2.2 中文官方教程和指南(一)
61 0
|
6月前
|
存储 SQL JSON
Pandas 2.2 中文官方教程和指南(一)(3)
Pandas 2.2 中文官方教程和指南(一)
97 0
|
6月前
|
XML 关系型数据库 PostgreSQL
Pandas 2.2 中文官方教程和指南(一)(2)
Pandas 2.2 中文官方教程和指南(一)
179 0
|
6月前
|
XML 关系型数据库 MySQL
Pandas 2.2 中文官方教程和指南(一)(1)
Pandas 2.2 中文官方教程和指南(一)
184 0
|
6月前
|
C++ 索引 Python
Pandas 2.2 中文官方教程和指南(五)(4)
Pandas 2.2 中文官方教程和指南(五)
51 0
下一篇
无影云桌面