晚上在微信群看到有人提问:
这其实是数据处理中经常遇到的数据集「长」「宽」格式转换问题。看起来似乎挺难,有很多细节要考虑。实际上这个问题也的确不简单,如果从零开始码要花不少精力,效果还不好保证。
但是,因为这个问题太常见了,所以 Python / R 都提供了对应的函数来专门解决这个问题。
利用 Python 进行「长」「宽」转换
Python 的 pandas package 提供了.melt( ) / .pivot( )两个函数来做「长」「宽」转换。前者将宽数据集转换为长数据集,后者将长数据集转换为宽数据集。
import pandas as pd
data = {'username':['张三','李四','王五'],
'数学':[34,45,76],
'语文':[58,87,34],
'英语':[578,45,89]}
df = pd.DataFrame(data)
df
观察上表,我们很容易想到它还可以组织成 username,subject,score 这种形式:
melted = pd.melt(df,['username'])
一行代码就能实现我们想要的操作。 .melt( ) 接收两个参数,第一个参数是需要变换的数据集。第二个参数是一个列表,列表中指定的数据集的列作为分组的指标,剩下的所有列名合并为转换后的数据集的一列,默认列名是 variable。分组指标和列名共同定位一个唯一的值,所有的这些值合并为一列,默认列名是 value。
最后,按需对变换后的数据集重命名。
melted.rename(columns = {'variable':'subject','value':'score'})
.melt( ) 的逆操作是.pivot( )
pivoted = melted.pivot('username','subject','score')
.pivot() 的第一、二参数分别用作转换后的数据集行和列索引,可选列作为转换后的 dataframe 的值。如果不想将第一个参数作为行索引,可以将索引重置:
pivoted.columns = ['数学','英语','语文']
pivoted.reset_index()
利用 R 进行「长」「宽」转换
R 的 tidyr package 提供了 spread( ) / gather( )两个函数来做「长」「宽」转换。前者将宽数据集转换为长数据集,后者将长数据集转换为宽数据集。
library(tidyr)
data <- data.frame(username =c('张三','李四','王五'),
数学 =c(34,45,76),
语文 =c(58,87,34),
英语 =c(78,45,89))
data复制代码
我们需要按照 username 将数学、语文、英文三个列名融合成一列 subject,并将对应的值融合成一列 score
gathered <- data %>% gather(subject,score,-username)复制代码
gather() 的逆操作是 spread()
spreaded <- gathered %>% spread(subject,score)复制代码
spread() 接收两个参数,第一个参数对应的列的值转换为宽数据集的列名,第二个参数对应的列的值转换为宽数据集新建列的值。
阅读原文可观看在线 Python /R 版本 notebook,亲自动手尝试使用 R 对数据集进行「长」「宽」转换。
扫码关注「数据科学与技术」(微信号:read_csv)