pandas.wide_to_long#
- pandas.wide_to_long(df, stubnames, i, j, sep='', suffix='\\d+')[源代码][源代码]#
将 DataFrame 从宽格式透视为长格式。
不如melt灵活,但比melt更用户友好。
使用 stubnames [‘A’, ‘B’],此函数期望找到一个或多个列组,格式为 A-suffix1, A-suffix2,…, B-suffix1, B-suffix2,… 你可以用 j 指定在结果的长格式中调用此后缀的名称(例如 j=’year’)
这些宽变量的每一行都被假定为通过 i 唯一标识(可以是单个列名或列名列表)
数据框中所有剩余的变量保持不变。
- 参数:
- dfDataFrame
宽格式 DataFrame。
- stubnamesstr 或 类似列表
存根名称。宽格式变量假定以存根名称开始。
- istr 或 类似列表
用作id变量的列。
- jstr
子观测变量的名称。您希望在长格式中命名的后缀。
- sepstr, 默认 “”
一个表示宽格式中变量名称分隔的字符,将从长格式中的名称中去除。例如,如果你的列名是 A-suffix1, A-suffix2,你可以通过指定 sep=’-’ 来去除连字符。
- suffix : str, 默认 ‘d+’str, 默认 ‘d+’
一个捕获所需后缀的正则表达式。’d+’ 捕获数字后缀。没有数字的后缀可以用否定字符类 ‘D+’ 指定。你还可以进一步消除后缀的歧义,例如,如果你的宽变量形式为 A-one, B-two,..,并且你有一个不相关的列 A-rating,你可以通过指定 suffix=’(!?one|two)’ 来忽略最后一个。当所有后缀都是数字时,它们会被转换为 int64/float64。
- 返回:
- DataFrame
一个包含每个存根名称作为变量的 DataFrame,带有新的索引 (i, j)。
参见
melt
将 DataFrame 从宽格式透视为长格式,可选择保留标识符集。
pivot
创建一个电子表格样式的数据透视表作为 DataFrame。
DataFrame.pivot
无需聚合的枢轴,可以处理非数字数据。
DataFrame.pivot_table
可以处理一个索引/列对中重复值的枢轴泛化。
DataFrame.unstack
基于索引值而不是列进行透视。
备注
所有额外的变量都保持不变。这只是在底层使用了 pandas.melt,但在典型情况下被硬编码为“做正确的事情”。
例子
>>> np.random.seed(123) >>> df = 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))), ... } ... ) >>> df["id"] = df.index >>> df A1970 A1980 B1970 B1980 X id 0 a d 2.5 3.2 -1.085631 0 1 b e 1.2 1.3 0.997345 1 2 c f 0.7 0.1 0.282978 2 >>> pd.wide_to_long(df, ["A", "B"], i="id", j="year") ... X A B id year 0 1970 -1.085631 a 2.5 1 1970 0.997345 b 1.2 2 1970 0.282978 c 0.7 0 1980 -1.085631 d 3.2 1 1980 0.997345 e 1.3 2 1980 0.282978 f 0.1
带有多个 id 列
>>> df = pd.DataFrame( ... { ... "famid": [1, 1, 1, 2, 2, 2, 3, 3, 3], ... "birth": [1, 2, 3, 1, 2, 3, 1, 2, 3], ... "ht1": [2.8, 2.9, 2.2, 2, 1.8, 1.9, 2.2, 2.3, 2.1], ... "ht2": [3.4, 3.8, 2.9, 3.2, 2.8, 2.4, 3.3, 3.4, 2.9], ... } ... ) >>> df famid birth ht1 ht2 0 1 1 2.8 3.4 1 1 2 2.9 3.8 2 1 3 2.2 2.9 3 2 1 2.0 3.2 4 2 2 1.8 2.8 5 2 3 1.9 2.4 6 3 1 2.2 3.3 7 3 2 2.3 3.4 8 3 3 2.1 2.9 >>> long_format = pd.wide_to_long(df, stubnames="ht", i=["famid", "birth"], j="age") >>> long_format ... ht famid birth age 1 1 1 2.8 2 3.4 2 1 2.9 2 3.8 3 1 2.2 2 2.9 2 1 1 2.0 2 3.2 2 1 1.8 2 2.8 3 1 1.9 2 2.4 3 1 1 2.2 2 3.3 2 1 2.3 2 3.4 3 1 2.1 2 2.9
从长格式转换为宽格式只需一些创造性地使用 unstack
>>> wide_format = long_format.unstack() >>> wide_format.columns = wide_format.columns.map("{0[0]}{0[1]}".format) >>> wide_format.reset_index() famid birth ht1 ht2 0 1 1 2.8 3.4 1 1 2 2.9 3.8 2 1 3 2.2 2.9 3 2 1 2.0 3.2 4 2 2 1.8 2.8 5 2 3 1.9 2.4 6 3 1 2.2 3.3 7 3 2 2.3 3.4 8 3 3 2.1 2.9
不太方便的列名也会被处理
>>> np.random.seed(0) >>> df = pd.DataFrame( ... { ... "A(weekly)-2010": np.random.rand(3), ... "A(weekly)-2011": np.random.rand(3), ... "B(weekly)-2010": np.random.rand(3), ... "B(weekly)-2011": np.random.rand(3), ... "X": np.random.randint(3, size=3), ... } ... ) >>> df["id"] = df.index >>> df A(weekly)-2010 A(weekly)-2011 B(weekly)-2010 B(weekly)-2011 X id 0 0.548814 0.544883 0.437587 0.383442 0 0 1 0.715189 0.423655 0.891773 0.791725 1 1 2 0.602763 0.645894 0.963663 0.528895 1 2
>>> pd.wide_to_long(df, ["A(weekly)", "B(weekly)"], i="id", j="year", sep="-") ... X A(weekly) B(weekly) id year 0 2010 0 0.548814 0.437587 1 2010 1 0.715189 0.891773 2 2010 1 0.602763 0.963663 0 2011 0 0.544883 0.383442 1 2011 1 0.423655 0.791725 2 2011 1 0.645894 0.528895
如果我们有很多列,我们也可以使用正则表达式来找到我们的存根名称,并将该列表传递给 wide_to_long
>>> stubnames = sorted( ... set( ... [ ... match[0] ... for match in df.columns.str.findall(r"[A-B]\(.*\)").values ... if match != [] ... ] ... ) ... ) >>> list(stubnames) ['A(weekly)', 'B(weekly)']
上述所有示例的后缀都是整数。也可以使用非整数作为后缀。
>>> df = pd.DataFrame( ... { ... "famid": [1, 1, 1, 2, 2, 2, 3, 3, 3], ... "birth": [1, 2, 3, 1, 2, 3, 1, 2, 3], ... "ht_one": [2.8, 2.9, 2.2, 2, 1.8, 1.9, 2.2, 2.3, 2.1], ... "ht_two": [3.4, 3.8, 2.9, 3.2, 2.8, 2.4, 3.3, 3.4, 2.9], ... } ... ) >>> df famid birth ht_one ht_two 0 1 1 2.8 3.4 1 1 2 2.9 3.8 2 1 3 2.2 2.9 3 2 1 2.0 3.2 4 2 2 1.8 2.8 5 2 3 1.9 2.4 6 3 1 2.2 3.3 7 3 2 2.3 3.4 8 3 3 2.1 2.9
>>> long_format = pd.wide_to_long( ... df, stubnames="ht", i=["famid", "birth"], j="age", sep="_", suffix=r"\w+" ... ) >>> long_format ... ht famid birth age 1 1 one 2.8 two 3.4 2 one 2.9 two 3.8 3 one 2.2 two 2.9 2 1 one 2.0 two 3.2 2 one 1.8 two 2.8 3 one 1.9 two 2.4 3 1 one 2.2 two 3.3 2 one 2.3 two 3.4 3 one 2.1 two 2.9