Pandas 2.2 中文官方教程和指南(十四)(1)https://developer.aliyun.com/article/1509843
与Series
版本一样,您可以为prefix
和prefix_sep
传递值。默认情况下,列名用作前缀,_
用作前缀分隔符。您可以以 3 种方式指定prefix
���prefix_sep
:
- string: 对于要编码的每一列,使用相同的值作为
prefix
或prefix_sep
。 - list: 必须与要编码的列数相同长度。
- dict: 将列名映射到前缀。
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` 将与原始行的索引标签对应重复: ```py 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`都将使用其名称属性,除非为交叉制表指定了行或列名称 ```py 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 ```## `cut()` `cut()`函数计算输入数组的值的分组,并经常用于将连续变量转换为离散或分类变量: 整数`bins`将形成等宽箱。 ```py 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`。 ```py 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
将类似地对 1 维值进行编码以进行进一步的分类操作
In [128]: pd.Categorical(x) Out[128]: ['A', 'A', NaN, 'B', 3.14, inf] Categories (4, object): [3.14, inf, 'A', 'B']
pivot()
和 pivot_table()
pivot()
数据通常以所谓的“堆叠”或“记录”格式存储。在“记录”或“宽”格式中,通常每个主题都有一行。在“堆叠”或“长”格式中,每个主题(适用时)可能有多行。
In [1]: data = { ...: "value": range(12), ...: "variable": ["A"] * 3 + ["B"] * 3 + ["C"] * 3 + ["D"] * 3, ...: "date": pd.to_datetime(["2020-01-03", "2020-01-04", "2020-01-05"] * 4) ...: } ...: In [2]: df = pd.DataFrame(data)
要对每个唯一变量执行时间序列操作,更好的表示形式是 columns
是唯一变量,日期的 index
标识个别观察结果。为了将数据重塑为这种形式,我们使用 DataFrame.pivot()
方法(也实现为顶级函数 pivot()
):
In [3]: pivoted = df.pivot(index="date", columns="variable", values="value") In [4]: pivoted Out[4]: variable A B C D date 2020-01-03 0 3 6 9 2020-01-04 1 4 7 10 2020-01-05 2 5 8 11
如果省略 values
参数,并且输入的 DataFrame
有多列值,这些值不用作 pivot()
的列或索引输入,则生成的“透视” DataFrame
将具有分层列,其最顶层指示相应的值列:
In [5]: df["value2"] = df["value"] * 2 In [6]: pivoted = df.pivot(index="date", columns="variable") In [7]: pivoted Out[7]: value value2 variable A B C D A B C D date 2020-01-03 0 3 6 9 0 6 12 18 2020-01-04 1 4 7 10 2 8 14 20 2020-01-05 2 5 8 11 4 10 16 22
然后您可以从透视的 DataFrame
中选择子集:
In [8]: pivoted["value2"] Out[8]: variable A B C D date 2020-01-03 0 6 12 18 2020-01-04 2 8 14 20 2020-01-05 4 10 16 22
请注意,在数据是同质类型的情况下,这将返回对底层数据的视图。
注意
pivot()
只能处理由 index
和 columns
指定的唯一行。如果您的数据包含重复项,请使用 pivot_table()
。
pivot_table()
虽然 pivot()
提供了各种数据类型的通用数据透视,但 pandas 还提供了 pivot_table()
或 pivot_table()
用于对数值数据进行聚合的数据透视。
函数pivot_table()
可以用来创建类似电子表格的透视表。查看示例以获取一些高级策略。
In [9]: import datetime In [10]: df = pd.DataFrame( ....: { ....: "A": ["one", "one", "two", "three"] * 6, ....: "B": ["A", "B", "C"] * 8, ....: "C": ["foo", "foo", "foo", "bar", "bar", "bar"] * 4, ....: "D": np.random.randn(24), ....: "E": np.random.randn(24), ....: "F": [datetime.datetime(2013, i, 1) for i in range(1, 13)] ....: + [datetime.datetime(2013, i, 15) for i in range(1, 13)], ....: } ....: ) ....: In [11]: df Out[11]: A B C D E F 0 one A foo 0.469112 0.404705 2013-01-01 1 one B foo -0.282863 0.577046 2013-02-01 2 two C foo -1.509059 -1.715002 2013-03-01 3 three A bar -1.135632 -1.039268 2013-04-01 4 one B bar 1.212112 -0.370647 2013-05-01 .. ... .. ... ... ... ... 19 three B foo -1.087401 -0.472035 2013-08-15 20 one C foo -0.673690 -0.013960 2013-09-15 21 one A bar 0.113648 -0.362543 2013-10-15 22 two B bar -1.478427 -0.006154 2013-11-15 23 three C bar 0.524988 -0.923061 2013-12-15 [24 rows x 6 columns] In [12]: pd.pivot_table(df, values="D", index=["A", "B"], columns=["C"]) Out[12]: C bar foo A B one A -0.995460 0.595334 B 0.393570 -0.494817 C 0.196903 -0.767769 three A -0.431886 NaN B NaN -1.065818 C 0.798396 NaN two A NaN 0.197720 B -0.986678 NaN C NaN -1.274317 In [13]: pd.pivot_table( ....: df, values=["D", "E"], ....: index=["B"], ....: columns=["A", "C"], ....: aggfunc="sum", ....: ) ....: Out[13]: D ... E A one three ... three two C bar foo bar ... foo bar foo B ... A -1.990921 1.190667 -0.863772 ... NaN NaN -1.067650 B 0.787140 -0.989634 NaN ... 0.372851 1.63741 NaN C 0.393806 -1.535539 1.596791 ... NaN NaN -3.491906 [3 rows x 12 columns] In [14]: pd.pivot_table( ....: df, values="E", ....: index=["B", "C"], ....: columns=["A"], ....: aggfunc=["sum", "mean"], ....: ) ....: Out[14]: sum mean A one three two one three two B C A bar -0.471593 -2.008182 NaN -0.235796 -1.004091 NaN foo 0.761726 NaN -1.067650 0.380863 NaN -0.533825 B bar -1.665170 NaN 1.637410 -0.832585 NaN 0.818705 foo -0.097554 0.372851 NaN -0.048777 0.186425 NaN C bar -0.744154 -2.392449 NaN -0.372077 -1.196224 NaN foo 1.061810 NaN -3.491906 0.530905 NaN -1.745953
结果是一个可能具有索引或列上的MultiIndex
的DataFrame
。如果未提供values
列名称,则透视表将在列中包含所有数据的另一层次的层次结构:
In [15]: pd.pivot_table(df[["A", "B", "C", "D", "E"]], index=["A", "B"], columns=["C"]) Out[15]: D E C bar foo bar foo A B one A -0.995460 0.595334 -0.235796 0.380863 B 0.393570 -0.494817 -0.832585 -0.048777 C 0.196903 -0.767769 -0.372077 0.530905 three A -0.431886 NaN -1.004091 NaN B NaN -1.065818 NaN 0.186425 C 0.798396 NaN -1.196224 NaN two A NaN 0.197720 NaN -0.533825 B -0.986678 NaN 0.818705 NaN C NaN -1.274317 NaN -1.745953
此外,您可以将Grouper
用于index
和columns
关键字。有关Grouper
的详细信息,请参阅使用 Grouper 规范进行分组。
In [16]: pd.pivot_table(df, values="D", index=pd.Grouper(freq="ME", key="F"), columns="C") Out[16]: C bar foo F 2013-01-31 NaN 0.595334 2013-02-28 NaN -0.494817 2013-03-31 NaN -1.274317 2013-04-30 -0.431886 NaN 2013-05-31 0.393570 NaN 2013-06-30 0.196903 NaN 2013-07-31 NaN 0.197720 2013-08-31 NaN -1.065818 2013-09-30 NaN -0.767769 2013-10-31 -0.995460 NaN 2013-11-30 -0.986678 NaN 2013-12-31 0.798396 NaN
添加边距
将margins=True
传递给pivot_table()
将在行和列上添加具有部分组聚合的All
标签的行和列:
In [17]: table = df.pivot_table( ....: index=["A", "B"], ....: columns="C", ....: values=["D", "E"], ....: margins=True, ....: aggfunc="std" ....: ) ....: In [18]: table Out[18]: D E C bar foo All bar foo All A B one A 1.568517 0.178504 1.293926 0.179247 0.033718 0.371275 B 1.157593 0.299748 0.860059 0.653280 0.885047 0.779837 C 0.523425 0.133049 0.638297 1.111310 0.770555 0.938819 three A 0.995247 NaN 0.995247 0.049748 NaN 0.049748 B NaN 0.030522 0.030522 NaN 0.931203 0.931203 C 0.386657 NaN 0.386657 0.386312 NaN 0.386312 two A NaN 0.111032 0.111032 NaN 1.146201 1.146201 B 0.695438 NaN 0.695438 1.166526 NaN 1.166526 C NaN 0.331975 0.331975 NaN 0.043771 0.043771 All 1.014073 0.713941 0.871016 0.881376 0.984017 0.923568
此外,您可以调用DataFrame.stack()
将透视的 DataFrame 显示为具有多级索引:
In [19]: table.stack(future_stack=True) Out[19]: D E A B C one A bar 1.568517 0.179247 foo 0.178504 0.033718 All 1.293926 0.371275 B bar 1.157593 0.653280 foo 0.299748 0.885047 ... ... ... two C foo 0.331975 0.043771 All 0.331975 0.043771 All bar 1.014073 0.881376 foo 0.713941 0.984017 All 0.871016 0.923568 [30 rows x 2 columns]
pivot()
数据通常以所谓的“堆叠”或“记录”格式存储。在“记录”或“宽”格式中,通常每个主题都有一行。在“堆叠”或“长”格式中,每个主题(适用时)通常有多行。
In [1]: data = { ...: "value": range(12), ...: "variable": ["A"] * 3 + ["B"] * 3 + ["C"] * 3 + ["D"] * 3, ...: "date": pd.to_datetime(["2020-01-03", "2020-01-04", "2020-01-05"] * 4) ...: } ...: In [2]: df = pd.DataFrame(data)
要使用每个唯一变量执行时间序列操作,更好的表示形式是columns
是唯一变量,index
是日期,标识单个观察。要将数据重塑为这种形式,我们使用DataFrame.pivot()
方法(也实现为顶级函数pivot()
):
In [3]: pivoted = df.pivot(index="date", columns="variable", values="value") In [4]: pivoted Out[4]: variable A B C D date 2020-01-03 0 3 6 9 2020-01-04 1 4 7 10 2020-01-05 2 5 8 11
如果省略了values
参数,并且输入的DataFrame
具有多列值,这些值未用作列或索引输入到pivot()
,则生成的“透视”DataFrame
将具有层次化的列,其最顶层指示相应的值列:
In [5]: df["value2"] = df["value"] * 2 In [6]: pivoted = df.pivot(index="date", columns="variable") In [7]: pivoted Out[7]: value value2 variable A B C D A B C D date 2020-01-03 0 3 6 9 0 6 12 18 2020-01-04 1 4 7 10 2 8 14 20 2020-01-05 2 5 8 11 4 10 16 22
然后,您可以从透视的DataFrame
中选择子集:
In [8]: pivoted["value2"] Out[8]: variable A B C D date 2020-01-03 0 6 12 18 2020-01-04 2 8 14 20 2020-01-05 4 10 16 22
请注意,在数据类型均为同质类型的情况下,这将返回基础数据的视图。
注意
pivot()
只能处理由index
和columns
指定的唯一行。如果您的数据包含重复项,请使用pivot_table()
。
Pandas 2.2 中文官方教程和指南(十四)(3)https://developer.aliyun.com/article/1509845