import pandas as pd
import plotly.express as px
23 使用 melt() 和 pivot() 重新塑造数据
23.1 软件包
23.2 数据
运行下面的代码以加载和定义将在本课中使用的数据集。
# Temperatures dataset
= pd.DataFrame(
temperatures
{"country": ["Sweden", "Denmark", "Norway"],
"1994": [1, 2, 3],
"1995": [3, 4, 5],
"1996": [5, 6, 7],
}
)
# Fuels Wide dataset
= pd.read_csv(
fuels_wide "https://raw.githubusercontent.com/the-graph-courses/idap_book/main/data/oil_per_capita_wide.csv"
)
# Eurostat Births Wide dataset
= pd.read_csv(
euro_births_wide "https://raw.githubusercontent.com/the-graph-courses/idap_book/main/data/euro_births_wide.csv"
)
# Contracts dataset
= pd.read_csv(
contracts "https://raw.githubusercontent.com/the-graph-courses/idap_book/main/data/chicago_contracts_20_23.csv"
)
# Population dataset
= pd.read_csv(
population "https://raw.githubusercontent.com/the-graph-courses/idap_book/main/data/tidyr_population.csv"
)
23.3 介绍
重塑是一种数据操作技术,涉及重新定位数据集的行和列。这通常是为了使数据更易于分析或理解所需。
在本课中,我们将介绍如何使用 pandas
函数有效地重塑数据。
23.4 学习目标
- 理解宽数据格式和长数据格式的区别。
- 学习如何使用
melt()
将宽数据重塑为长数据。 - 学习如何使用
pivot()
将长数据重塑为宽数据。
23.5 “宽”和“长”意味着什么?
“宽”和“长”这两个术语最好在示例数据集的上下文中理解。现在让我们看看一些示例。
想象一下,你有三种产品,收集了这三个月的销售数据。
宽格式:
产品 | 一月 | 二月 | 三月 |
---|---|---|---|
A | 100 | 120 | 110 |
B | 90 | 95 | 100 |
C | 80 | 85 | 90 |
长格式:
产品 | 月份 | 销售 |
---|---|---|
A | 一月 | 100 |
A | 二月 | 120 |
A | 三月 | 110 |
B | 一月 | 90 |
B | 二月 | 95 |
B | 三月 | 100 |
C | 一月 | 80 |
C | 二月 | 85 |
C | 三月 | 90 |
花一分钟时间研究这两个数据集,以确保你理解它们之间的关系。
在宽数据集中,每个观测单位(每个产品)只占一行,每个测量(1月、2月、3月的销售)在单独的列中。
而在长数据集中,每个观测单位(每个产品)占多行,每个测量有一行。
这是另一个使用模拟数据的示例,其中观测单位是国家:
长格式:
国家 | 年份 | GDP |
---|---|---|
USA | 2020 | 21433 |
USA | 2021 | 22940 |
China | 2020 | 14723 |
China | 2021 | 17734 |
宽格式:
国家 | GDP_2020 | GDP_2021 |
---|---|---|
USA | 21433 | 22940 |
China | 14723 | 17734 |
上述示例都是时间序列数据集,因为测量值在时间上重复。但宽和长的概念也与其他类型的数据相关。
考虑下面的例子,显示三个公司的不同部门的员工数量:
宽格式:
公司 | 人力资源 | 销售 | IT |
---|---|---|---|
A | 10 | 20 | 15 |
B | 8 | 25 | 20 |
C | 12 | 18 | 22 |
长格式:
公司 | 部门 | 员工数量 |
---|---|---|
A | 人力资源 | 10 |
A | 销售 | 20 |
A | IT | 15 |
B | 人力资源 | 8 |
B | 销售 | 25 |
B | IT | 20 |
C | 人力资源 | 12 |
C | 销售 | 18 |
C | IT | 22 |
在宽数据集中,每个观测单位(每个公司)只占一行,重复的测量值(不同部门的员工数量)分布在多列中。
在长数据集中,每个观测单位分布在多行中。
观测单位,有时称为统计单位,是数据集描述的主要实体或项目。
在第一个示例中,观测单位是产品;在第二个示例中是国家;在第三个示例中是公司。
23.6 练习题:宽还是长?
考虑前面创建的 temperatures
数据集:
temperatures
country | 1994 | 1995 | 1996 | |
---|---|---|---|---|
0 | Sweden | 1 | 3 | 5 |
1 | Denmark | 2 | 4 | 6 |
2 | Norway | 3 | 5 | 7 |
这些数据是宽格式还是长格式?
23.7 何时应该使用宽数据和长数据?
事实上,这取决于你想做什么!宽格式非常适合 展示数据,因为这样便于视觉比较数值。长数据最适合一些数据分析任务,如分组和制图。
了解如何轻松地在这两种格式之间切换是至关重要的。从宽格式切换到长格式,或反之,则称为重塑。
23.8 使用 melt()
从宽到长
为了练习从宽到长的重塑,我们将考虑《世界数据》中关于人均化石燃料消费的数据。你可以在这里找到这些数据。
下面,我们查看人均化石燃料消费的数据:
fuels_wide
Entity | Code | y_1970 | y_1980 | y_1990 | y_2000 | y_2010 | y_2020 | |
---|---|---|---|---|---|---|---|---|
0 | Algeria | DZA | 1764.8470 | 3532.7976 | 4381.6636 | 3351.2180 | 5064.9863 | 4877.2680 |
1 | Argentina | ARG | 11677.9680 | 10598.3990 | 7046.2485 | 7146.8154 | 7966.7827 | 6399.2114 |
2 | Australia | AUS | 23040.4550 | 25007.4380 | 23046.9510 | 23976.3550 | 23584.3070 | 20332.4100 |
3 | Austria | AUT | 14338.8090 | 19064.0920 | 16595.1930 | 18189.0920 | 18424.1170 | 14934.0650 |
4 | Azerbaijan | AZE | NaN | NaN | 13516.0190 | 9119.3470 | 4031.9407 | 5615.1157 |
... | ... | ... | ... | ... | ... | ... | ... | ... |
76 | United States | USA | 40813.9530 | 42365.6500 | 37525.5160 | 37730.1600 | 31791.3070 | 26895.4770 |
77 | Uzbekistan | UZB | NaN | NaN | 6324.8677 | 3197.1330 | 1880.1338 | 1859.1548 |
78 | Venezuela | VEN | 11138.2210 | 16234.0960 | 12404.5570 | 11239.9260 | 14948.3070 | 4742.6226 |
79 | Vietnam | VNM | 1757.6117 | 439.9465 | 523.2565 | 1280.3065 | 2296.7590 | 2927.7446 |
80 | World | OWID_WRL | 7217.8340 | 8002.0854 | 7074.2583 | 6990.4272 | 6879.6110 | 6216.8060 |
81 rows × 8 columns
我们观察到,每个观测单位(每个国家)只占一行,重复的测量值(以千瓦时当量计的化石燃料消费)分布在多列中。因此,该数据集为宽格式。
为了将其转换为长格式,我们可以使用方便的 melt
函数。在 melt
中,可以定义不想重塑的 id 变量,如下所示:
= fuels_wide.melt(id_vars=["Entity", "Code"])
fuels_long fuels_long
Entity | Code | variable | value | |
---|---|---|---|---|
0 | Algeria | DZA | y_1970 | 1764.8470 |
1 | Argentina | ARG | y_1970 | 11677.9680 |
2 | Australia | AUS | y_1970 | 23040.4550 |
3 | Austria | AUT | y_1970 | 14338.8090 |
4 | Azerbaijan | AZE | y_1970 | NaN |
... | ... | ... | ... | ... |
481 | United States | USA | y_2020 | 26895.4770 |
482 | Uzbekistan | UZB | y_2020 | 1859.1548 |
483 | Venezuela | VEN | y_2020 | 4742.6226 |
484 | Vietnam | VNM | y_2020 | 2927.7446 |
485 | World | OWID_WRL | y_2020 | 6216.8060 |
486 rows × 4 columns
非常简单!
让我们排序一下,使其更易读:
= fuels_long.sort_values(by=['Entity', 'variable'])
fuels_long fuels_long
Entity | Code | variable | value | |
---|---|---|---|---|
0 | Algeria | DZA | y_1970 | 1764.8470 |
81 | Algeria | DZA | y_1980 | 3532.7976 |
162 | Algeria | DZA | y_1990 | 4381.6636 |
243 | Algeria | DZA | y_2000 | 3351.2180 |
324 | Algeria | DZA | y_2010 | 5064.9863 |
... | ... | ... | ... | ... |
161 | World | OWID_WRL | y_1980 | 8002.0854 |
242 | World | OWID_WRL | y_1990 | 7074.2583 |
323 | World | OWID_WRL | y_2000 | 6990.4272 |
404 | World | OWID_WRL | y_2010 | 6879.6110 |
485 | World | OWID_WRL | y_2020 | 6216.8060 |
486 rows × 4 columns
年份现在在 variable
变量中表示,所有的消费值占据单一变量 value
。我们可能希望将 variable
列重命名为 year
,将 value
列重命名为 oil_consumption
。这可以直接在 melt
函数中完成:
= fuels_wide.melt(
fuels_long =['Entity', 'Code'],
id_vars='year',
var_name='oil_consumption'
value_name=['Entity', 'year'])
).sort_values(by fuels_long
Entity | Code | year | oil_consumption | |
---|---|---|---|---|
0 | Algeria | DZA | y_1970 | 1764.8470 |
81 | Algeria | DZA | y_1980 | 3532.7976 |
162 | Algeria | DZA | y_1990 | 4381.6636 |
243 | Algeria | DZA | y_2000 | 3351.2180 |
324 | Algeria | DZA | y_2010 | 5064.9863 |
... | ... | ... | ... | ... |
161 | World | OWID_WRL | y_1980 | 8002.0854 |
242 | World | OWID_WRL | y_1990 | 7074.2583 |
323 | World | OWID_WRL | y_2000 | 6990.4272 |
404 | World | OWID_WRL | y_2010 | 6879.6110 |
485 | World | OWID_WRL | y_2020 | 6216.8060 |
486 rows × 4 columns
你还可能希望去掉每个年份前的 y_
。这可以通过字符串操作实现。
'year'] = fuels_long['year'].str.replace('y_', '').astype(int)
fuels_long[ fuels_long
Entity | Code | year | oil_consumption | |
---|---|---|---|---|
0 | Algeria | DZA | 1970 | 1764.8470 |
81 | Algeria | DZA | 1980 | 3532.7976 |
162 | Algeria | DZA | 1990 | 4381.6636 |
243 | Algeria | DZA | 2000 | 3351.2180 |
324 | Algeria | DZA | 2010 | 5064.9863 |
... | ... | ... | ... | ... |
161 | World | OWID_WRL | 1980 | 8002.0854 |
242 | World | OWID_WRL | 1990 | 7074.2583 |
323 | World | OWID_WRL | 2000 | 6990.4272 |
404 | World | OWID_WRL | 2010 | 6879.6110 |
485 | World | OWID_WRL | 2020 | 6216.8060 |
486 rows × 4 columns
以下是我们上面所做的事情:
- 使用
str.replace()
去除每个年份前的y_
前缀。 - 使用
astype(int)
将year
列转换为整数。 - 使用
sort_values()
按 “Entity” 和 “year” 对数据进行排序。
23.9 练习题:将 Temperatures 数据集转换为长格式
将下面显示的 temperatures
数据集转换为长格式。你的答案应包含以下列名:“country”, “year”, 和 “avg_temp”。
# Your code here
temperatures
country | 1994 | 1995 | 1996 | |
---|---|---|---|---|
0 | Sweden | 1 | 3 | 5 |
1 | Denmark | 2 | 4 | 6 |
2 | Norway | 3 | 5 | 7 |
23.10 练习题:将 Eurostat 的出生数据转换为长格式
在本练习题中,你将使用来自 Eurostat 的 euro_births_wide
数据集。它显示了 50 个欧洲国家的年度出生人数:
euro_births_wide.head()
country | x2015 | x2016 | x2017 | x2018 | x2019 | x2020 | x2021 | |
---|---|---|---|---|---|---|---|---|
0 | Belgium | 122274.0 | 121896.0 | 119690.0 | 118319.0 | 117695.0 | 114350.0 | 118349.0 |
1 | Bulgaria | 65950.0 | 64984.0 | 63955.0 | 62197.0 | 61538.0 | 59086.0 | 58678.0 |
2 | Czechia | 110764.0 | 112663.0 | 114405.0 | 114036.0 | 112231.0 | 110200.0 | 111793.0 |
3 | Denmark | 58205.0 | 61614.0 | 61397.0 | 61476.0 | 61167.0 | 60937.0 | 63473.0 |
4 | Germany | 737575.0 | 792141.0 | 784901.0 | 787523.0 | 778090.0 | 773144.0 | 795492.0 |
数据是宽格式。将其转换为长格式的 DataFrame,包含以下列名:“country”, “year”, 和 “births_count”。
去掉年份列名的 x
前缀,并将它们转换为整数。
23.11 使用长数据进行分析
让我们看看为什么长数据通常更适合分析。
再次考虑 fuels_wide
数据集:
fuels_wide.head()
Entity | Code | y_1970 | y_1980 | y_1990 | y_2000 | y_2010 | y_2020 | |
---|---|---|---|---|---|---|---|---|
0 | Algeria | DZA | 1764.847 | 3532.7976 | 4381.6636 | 3351.2180 | 5064.9863 | 4877.2680 |
1 | Argentina | ARG | 11677.968 | 10598.3990 | 7046.2485 | 7146.8154 | 7966.7827 | 6399.2114 |
2 | Australia | AUS | 23040.455 | 25007.4380 | 23046.9510 | 23976.3550 | 23584.3070 | 20332.4100 |
3 | Austria | AUT | 14338.809 | 19064.0920 | 16595.1930 | 18189.0920 | 18424.1170 | 14934.0650 |
4 | Azerbaijan | AZE | NaN | NaN | 13516.0190 | 9119.3470 | 4031.9407 | 5615.1157 |
fuels_long.head()
Entity | Code | year | oil_consumption | |
---|---|---|---|---|
0 | Algeria | DZA | 1970 | 1764.8470 |
81 | Algeria | DZA | 1980 | 3532.7976 |
162 | Algeria | DZA | 1990 | 4381.6636 |
243 | Algeria | DZA | 2000 | 3351.2180 |
324 | Algeria | DZA | 2010 | 5064.9863 |
如果我们想要找到每个国家的平均化石燃料消费,使用长格式非常容易:
'Entity')['oil_consumption'].mean() fuels_long.groupby(
Entity
Algeria 3828.796750
Argentina 8472.570833
Australia 23164.652667
Austria 16924.228000
Azerbaijan 8070.605600
...
United States 36187.010500
Uzbekistan 3315.322325
Venezuela 11784.621600
Vietnam 1537.604133
World 7063.503650
Name: oil_consumption, Length: 81, dtype: float64
但使用宽格式,这就不那么容易了:
'y_1970', 'y_1980', 'y_1990', 'y_2000', 'y_2010', 'y_2020']].mean(axis=1) fuels_wide[[
0 3828.796750
1 8472.570833
2 23164.652667
3 16924.228000
4 8070.605600
...
76 36187.010500
77 3315.322325
78 11784.621600
79 1537.604133
80 7063.503650
Length: 81, dtype: float64
想象一下如果你有 100 年的数据!
而均值是一个相当简单的操作。你如何计算每个国家的化石燃料消费标准差?
长数据对于制图也非常有用。
例如,要绘制每个国家随时间变化的平均化石燃料消费,我们可以使用以下代码:
= fuels_long.query('Entity in ["Peru", "Iran", "China"]')
subset ='year', y='oil_consumption', color='Entity', title='Average Fossil Fuel Consumption per Country') px.line(subset, x
使用宽格式无法直接创建类似的图,因为你要绘制的数据散布在多个列中。
因此,如你所见,虽然宽数据适合展示,但长数据对于分析和制图非常有用。
23.12 从长到宽
现在你已经知道如何使用 melt()
将宽格式重塑为长格式。那么如何从长格式转换为宽格式呢?为此,你可以使用 pivot()
函数。
但在我们看到如何使用这个函数来操作长数据之前,先考虑你可能在哪里会遇到长数据。
虽然宽数据往往来自外部来源(如上所示),但长数据则可能是在数据处理过程中由你创建的,特别是在分组聚合的过程中。
现在让我们看一个例子。
我们将使用芝加哥市从 2020 年到 2023 年授予的合同数据集。你可以在这里找到更多关于数据的信息。
contracts
year | approval_date | description | contract_num | revision_num | specification_num | contract_type | start_date | end_date | department | vendor_name | vendor_id | address_1 | address_2 | city | state | zip | award_amount | procurement_type | contract_pdf | |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020 | 2020-01-02 | LEASE | 24406 | 32 | 96136 | PROPERTY LEASE | NaN | NaN | NaN | 8700 BUILDING LLC | 89123305A | 7300 S NARRAGANSETT | NaN | BEDFORD PARK | Illinois | 60638 | 321.1 | NaN | NaN |
1 | 2020 | 2020-01-03 | DFSS-HHS-CS-CEL: | 113798 | 0 | 1070196 | DELEGATE AGENCY | 12/01/2019 | 11/30/2022 | DEPT OF FAMILY AND SUPPORT SERVICES | CATHOLIC CHARITIES OF THE ARCHDIOCESE OF CHICAGO | 102484615A | 1 E BANKS ST | NaN | CHICAGO | Illinois | 60670 | 17692515.0 | NaN | NaN |
2 | 2020 | 2020-01-03 | DFSS-HHS-CS-CEL: | 113819 | 0 | 1070196 | DELEGATE AGENCY | 12/01/2019 | 11/30/2022 | DEPT OF FAMILY AND SUPPORT SERVICES | KIMBALL DAYCARE CENTER & KINDERGARTEN INC | 105458567Z | 1636-1638 N KIMBALL AVE | NaN | CHICAGO | Illinois | 60647 | 11461500.0 | NaN | http://ecm.cityofchicago.org/eSMARTContracts/s... |
3 | 2020 | 2020-01-03 | DFSS-HHS-CS-CEL: | 113818 | 0 | 1070196 | DELEGATE AGENCY | 12/01/2019 | 11/30/2022 | DEPT OF FAMILY AND SUPPORT SERVICES | JUDAH INTERNATIONAL OUTREACH MINISTRIES, INC | 94219962X | 856 N PULASKI RD | NaN | CHICAGO | Illinois | 60651 | 2356515.0 | NaN | http://ecm.cityofchicago.org/eSMARTContracts/s... |
4 | 2020 | 2020-01-03 | DFSS-HHS-CS-CEL: | 113820 | 0 | 1070196 | DELEGATE AGENCY | 12/01/2019 | 11/30/2022 | DEPT OF FAMILY AND SUPPORT SERVICES | Marillac St. Vincent Family Services Inc DBA S... | 97791861L | 212 S FRANCISCO AVENUE EFT | NaN | CHICAGO | Illinois | 60612 | 3666015.0 | NaN | http://ecm.cityofchicago.org/eSMARTContracts/s... |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
28823 | 2023 | 2023-12-29 | DFSS-CORP-HL-PSH: | 220413 | 3 | 1221503 | DELEGATE AGENCY | NaN | NaN | DEPT OF FAMILY AND SUPPORT SERVICES | INNER VOICE INC. | 6231926M | 1621 W WALNUT ST FL 1ST | NaN | CHICAGO | Illinois | 60612 | 0.0 | NaN | NaN |
28824 | 2023 | 2023-12-29 | DFSS-CORP-YS-OST: | 253846 | 0 | 1247493 | DELEGATE AGENCY | NaN | NaN | DEPT OF FAMILY AND SUPPORT SERVICES | AFTER-SCHOOL MATTERS, INC.|CLEANED-UP | 72580818P | 66 E RANDOLPH ST FL 1ST | NaN | CHICAGO | Illinois | 60601 | 32000.0 | NaN | NaN |
28825 | 2023 | 2023-12-29 | DFSS-IDHS-HL-INTHS: | 253843 | 0 | 1235949 | DELEGATE AGENCY | NaN | NaN | DEPT OF FAMILY AND SUPPORT SERVICES | BREAKTHROUGH URBAN MINISTRIES, INC. | 94722896V | 402 N ST LOUIS AVENUE EFT | NaN | CHICAGO | Illinois | 60624 | 14400.0 | NaN | NaN |
28826 | 2023 | 2023-12-29 | CDPH-RW-PA: ESS-HRSA PO 116685 CHICAGO HOUSE A... | 192085 | 1 | 1095441 | DELEGATE AGENCY | NaN | NaN | DEPARTMENT OF HEALTH | CHICAGO HOUSE & SOCIAL SERVICE AGENCY | 105470138T | 2229 S MICHIGAN AVE 304 EFT | NaN | CHICAGO | Illinois | 60616 | -32025.2 | NaN | NaN |
28827 | 2023 | 2023-12-29 | DFSS-HHS-CS-CEL: | 222199 | 1 | 1070196 | DELEGATE AGENCY | NaN | NaN | DEPT OF FAMILY AND SUPPORT SERVICES | ALLISON'S INFANT & TODDLER CENTER INC | 62751817Z | 234 E 115TH ST FL 1ST | NaN | CHICAGO | Illinois | 60628 | 141923.0 | NaN | NaN |
28828 rows × 20 columns
每一行对应一个合同,我们有每个合同的编号、授予年份、合同金额、供应商的名称和地址等变量。
现在,考虑以下对 contracts
数据集的分组摘要,显示每年按供应商所在州的合同数量:
= contracts.groupby("state")["year"].value_counts().reset_index()
contracts_summary contracts_summary
state | year | count | |
---|---|---|---|
0 | Alabama | 2023 | 7 |
1 | Alabama | 2021 | 2 |
2 | Alabama | 2020 | 1 |
3 | Alabama | 2022 | 1 |
4 | Arizona | 2020 | 3 |
... | ... | ... | ... |
128 | Washington | 2021 | 1 |
129 | Wisconsin | 2023 | 25 |
130 | Wisconsin | 2020 | 18 |
131 | Wisconsin | 2022 | 17 |
132 | Wisconsin | 2021 | 15 |
133 rows × 3 columns
这个分组操作的输出是一个典型的“长”数据集。每个观测单位(每个州)占多行,每个测量(每年)有一行。
现在,让我们看看如何使用 pivot()
将长数据转换为宽格式。
代码相当简单:
= contracts_summary.pivot(
contracts_wide ="state", columns="year", values="count"
index
).reset_index() contracts_wide.head()
year | state | 2020 | 2021 | 2022 | 2023 |
---|---|---|---|---|---|
0 | Alabama | 1.0 | 2.0 | 1.0 | 7.0 |
1 | Arizona | 3.0 | 1.0 | 3.0 | 2.0 |
2 | Arkansas | 1.0 | NaN | 1.0 | NaN |
3 | British Columbia | NaN | 1.0 | NaN | NaN |
4 | California | 36.0 | 42.0 | 43.0 | 38.0 |
如你所见,pivot()
有三个重要的参数:
index
定义了哪些列将用作新的索引。在我们的例子中,是 “state”,因为我们希望每一行表示一个州。columns
确定了哪个变量用于定义宽格式中的列名。在我们的例子中,是 “year”。你可以看到年份现在是列名。values
指定了哪些值将成为宽数据格式的核心。在我们的例子中,是合同数量 “count”。
你也可能希望将年份作为主要的观测单位,每一年占一行。这可以类似于上述示例进行,但将 year
作为索引,state
作为列:
= contracts_summary.pivot(
contracts_wide_year ="year", columns="state", values="count"
index
).reset_index() contracts_wide_year
state | year | Alabama | Arizona | Arkansas | British Columbia | California | Canada | Colorado | Connecticut | Delaware | ... | Oregon | Pennsylvania | Rhode Island | South Carolina | Tennessee | Texas | Vermont | Virginia | Washington | Wisconsin |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | 2020 | 1.0 | 3.0 | 1.0 | NaN | 36.0 | 1.0 | 6.0 | 1.0 | NaN | ... | 5.0 | 20.0 | 1.0 | 2.0 | 2.0 | 25.0 | NaN | 4.0 | NaN | 18.0 |
1 | 2021 | 2.0 | 1.0 | NaN | 1.0 | 42.0 | 1.0 | 2.0 | 5.0 | NaN | ... | NaN | 24.0 | NaN | 3.0 | 2.0 | 24.0 | 1.0 | 4.0 | 1.0 | 15.0 |
2 | 2022 | 1.0 | 3.0 | 1.0 | NaN | 43.0 | 1.0 | 7.0 | 3.0 | 1.0 | ... | NaN | 31.0 | NaN | 2.0 | 3.0 | 37.0 | NaN | 7.0 | NaN | 17.0 |
3 | 2023 | 7.0 | 2.0 | NaN | NaN | 38.0 | NaN | 6.0 | 5.0 | 2.0 | ... | NaN | 37.0 | NaN | 1.0 | 3.0 | 28.0 | NaN | 9.0 | NaN | 25.0 |
4 rows × 44 columns
在这里,唯一的观测单位(我们的行)现在是年份(2020, 2021, 2022, 2023)。
23.13 练习题:将 Temperatures 长格式转换回宽格式
将你上面创建的长格式 temperatures_long
数据集转换回宽格式。你的答案应包含以下列名:“country”, “1994”, “1995”, 和 “1996”。
# Your code here
23.14 练习题:将 Population 数据转换为宽格式
population
数据集显示了 219 个国家随时间变化的人口。
将这些数据重塑为宽格式。
population
country | year | population | |
---|---|---|---|
0 | Afghanistan | 1995 | 17586073 |
1 | Afghanistan | 1996 | 18415307 |
2 | Afghanistan | 1997 | 19021226 |
3 | Afghanistan | 1998 | 19496836 |
4 | Afghanistan | 1999 | 19987071 |
... | ... | ... | ... |
4040 | Zimbabwe | 2009 | 12888918 |
4041 | Zimbabwe | 2010 | 13076978 |
4042 | Zimbabwe | 2011 | 13358738 |
4043 | Zimbabwe | 2012 | 13724317 |
4044 | Zimbabwe | 2013 | 14149648 |
4045 rows × 3 columns
23.15 重塑可能很难
我们这里主要看了一些非常简单的重塑示例,但在实际中,重塑可能很难准确地完成。
当遇到这种情况时,我们建议查看 pandas 团队的官方文档,因为它包含丰富的示例。
23.16 总结
恭喜!你已经掌握了使用 pandas 重塑数据的技巧。
你现在理解了宽格式和长格式之间的区别,并且能够熟练地使用 melt()
和 pivot()
根据需要转换你的数据。
23.17 练习题答案:宽还是长?
数据是宽格式。
23.18 练习题答案:将 Temperatures 转换为长格式
# Melt the wide data into long format
= temperatures.melt(
temperatures_long =["country"], var_name="year", value_name="avgtemp"
id_vars
)
# Display the long format data
temperatures_long
country | year | avgtemp | |
---|---|---|---|
0 | Sweden | 1994 | 1 |
1 | Denmark | 1994 | 2 |
2 | Norway | 1994 | 3 |
3 | Sweden | 1995 | 3 |
4 | Denmark | 1995 | 4 |
5 | Norway | 1995 | 5 |
6 | Sweden | 1996 | 5 |
7 | Denmark | 1996 | 6 |
8 | Norway | 1996 | 7 |
23.19 练习题答案:将 Eurostat 的出生数据转换为长格式
# Melt the wide data into long format
= euro_births_wide.melt(
births_long =["country"], var_name="year", value_name="births_count"
id_vars
)
# Display the long format data
births_long
country | year | births_count | |
---|---|---|---|
0 | Belgium | x2015 | 122274.0 |
1 | Bulgaria | x2015 | 65950.0 |
2 | Czechia | x2015 | 110764.0 |
3 | Denmark | x2015 | 58205.0 |
4 | Germany | x2015 | 737575.0 |
... | ... | ... | ... |
345 | Ukraine | x2021 | 212.0 |
346 | Armenia | x2021 | 271983.0 |
347 | Azerbaijan | x2021 | NaN |
348 | Georgia | x2021 | 112284.0 |
349 | NaN | x2021 | 45946.0 |
350 rows × 3 columns
23.20 练习题答案:将 Temperatures 转换回宽格式
# Pivot the long data into wide format
= temperatures_long.pivot(
temperatures_wide ="country", columns="year", values="avgtemp"
index
).reset_index()
# Display the wide format data
temperatures_wide
year | country | 1994 | 1995 | 1996 |
---|---|---|---|---|
0 | Denmark | 2 | 4 | 6 |
1 | Norway | 3 | 5 | 7 |
2 | Sweden | 1 | 3 | 5 |
23.21 练习题答案:将 Population 数据转换为宽格式
# Pivot the long data into wide format
= population.pivot(
population_wide ="country", columns="year", values="population"
index
).reset_index()
# Display the wide format data
population_wide
year | country | 1995 | 1996 | 1997 | 1998 | 1999 | 2000 | 2001 | 2002 | 2003 | 2004 | 2005 | 2006 | 2007 | 2008 | 2009 | 2010 | 2011 | 2012 | 2013 |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
0 | Afghanistan | 17586073.0 | 18415307.0 | 19021226.0 | 19496836.0 | 19987071.0 | 20595360.0 | 21347782.0 | 22202806.0 | 23116142.0 | 24018682.0 | 24860855.0 | 25631282.0 | 26349243.0 | 27032197.0 | 27708187.0 | 28397812.0 | 29105480.0 | 29824536.0 | 30551674.0 |
1 | Albania | 3357858.0 | 3341043.0 | 3331317.0 | 3325456.0 | 3317941.0 | 3304948.0 | 3286084.0 | 3263596.0 | 3239385.0 | 3216197.0 | 3196130.0 | 3179573.0 | 3166222.0 | 3156608.0 | 3151185.0 | 3150143.0 | 3153883.0 | 3162083.0 | 3173271.0 |
2 | Algeria | 29315463.0 | 29845208.0 | 30345466.0 | 30820435.0 | 31276295.0 | 31719449.0 | 32150198.0 | 32572977.0 | 33003442.0 | 33461345.0 | 33960903.0 | 34507214.0 | 35097043.0 | 35725377.0 | 36383302.0 | 37062820.0 | 37762962.0 | 38481705.0 | 39208194.0 |
3 | American Samoa | 52874.0 | 53926.0 | 54942.0 | 55899.0 | 56768.0 | 57522.0 | 58176.0 | 58729.0 | 59117.0 | 59262.0 | 59117.0 | 58652.0 | 57919.0 | 57053.0 | 56245.0 | 55636.0 | 55274.0 | 55128.0 | 55165.0 |
4 | Andorra | 63854.0 | 64274.0 | 64090.0 | 63799.0 | 64084.0 | 65399.0 | 68000.0 | 71639.0 | 75643.0 | 79060.0 | 81223.0 | 81877.0 | 81292.0 | 79969.0 | 78659.0 | 77907.0 | 77865.0 | 78360.0 | 79218.0 |
... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
212 | Wallis and Futuna Islands | 14143.0 | 14221.0 | 14309.0 | 14394.0 | 14460.0 | 14497.0 | 14501.0 | 14476.0 | 14422.0 | 14344.0 | 14246.0 | 14126.0 | 13988.0 | 13840.0 | 13697.0 | 13565.0 | 13451.0 | 13353.0 | 13272.0 |
213 | West Bank and Gaza Strip | 2598393.0 | 2722497.0 | 2851993.0 | 2980563.0 | 3099951.0 | 3204572.0 | 3291620.0 | 3363542.0 | 3426549.0 | 3489743.0 | 3559856.0 | 3638829.0 | 3725076.0 | 3817551.0 | 3914035.0 | 4012880.0 | 4114199.0 | 4218771.0 | 4326295.0 |
214 | Yemen | 15018201.0 | 15578640.0 | 16088019.0 | 16564235.0 | 17035531.0 | 17522537.0 | 18029989.0 | 18551068.0 | 19081306.0 | 19612696.0 | 20139661.0 | 20661714.0 | 21182162.0 | 21703571.0 | 22229625.0 | 22763008.0 | 23304206.0 | 23852409.0 | 24407381.0 |
215 | Zambia | 8841338.0 | 9073311.0 | 9320089.0 | 9577483.0 | 9839179.0 | 10100981.0 | 10362137.0 | 10625423.0 | 10894519.0 | 11174650.0 | 11470022.0 | 11781612.0 | 12109620.0 | 12456527.0 | 12825031.0 | 13216985.0 | 13633796.0 | 14075099.0 | 14538640.0 |
216 | Zimbabwe | 11639364.0 | 11846110.0 | 12045813.0 | 12229500.0 | 12384727.0 | 12503652.0 | 12586763.0 | 12640922.0 | 12673103.0 | 12693047.0 | 12710589.0 | 12724308.0 | 12740160.0 | 12784041.0 | 12888918.0 | 13076978.0 | 13358738.0 | 13724317.0 | 14149648.0 |
217 rows × 20 columns