数据规整:连接、联合和重塑

数据规整:连接、联合和重塑

层次化索引

# 创建一个Series,并用一个由列表(或数组)构成的列表作为索引
data = pd.Series(
    np.random.uniform(size=9),
    index=[['a','a','a','b','b','c','c','d','d'],
           [1,2,3,1,3,1,2,2,3]])
# a  1    0.522148
#    2    0.218709
#    3    0.090737
# b  1    0.935800
#    3    0.019236
# c  1    0.521339
#    2    0.132961
# d  2    0.370182
#    3    0.368036
# dtype: float64

# 层次化索引对象,可以使用部分索引
data["b"]
# 1    0.802418
# 3    0.384905
# dtype: float64
data["b":"c"]
data.loc[["b","d"]]
# 在“内部”层级中进行选取也是可行的;下面选取第二层索引值为2的数据
data.loc[:,2]

# 通过unstack方法将数据重排到DataFrame中
data.unstack()
#           1         2         3
# a  0.179548  0.259897  0.511953
# b  0.545412       NaN  0.899350
# c  0.276509  0.232216       NaN
# d       NaN  0.219718  0.258017

# unstack的逆运算是stack
data.unstack().stack()

# DataFrame,每个轴都可以有分层索引
frame = pd.DataFrame(np.arange(12).reshape((4,3)),
                     index=[['a','a','b','b'],[1,2,1,2]],
                     columns=[['Ohio','Ohio','Colorado'],['Green','Red','Green']])
#      Ohio     Colorado
#     Green Red    Green
# a 1     0   1        2
#   2     3   4        5
# b 1     6   7        8
#   2     9  10       11

# 各层都可以有名称(可以是字符串,也可以是任意Python对象)
frame.index.names=['key1','key2']
frame.columns.names=['state','color']
# nlevels属性,可以知道索引有多少层
frame.index.nlevels
# 使用部分列索引,可以轻松选取列分组
frame["Ohio"]
# 可以单独创建MultiIndex,然后复用
pd.MultiIndex.from_arrays([
    ["Ohio","Ohio","Colorado"],
    ["Green","Red","Green"]],
    names=["state","color"]
    )

重排序和层级排序

# waplevel方法接收两个层级编号或名称,并返回一个层级互换的新对象(但数据不会发生变化)
frame.swaplevel("key1","key2")
# sort_index默认根据所有索引层级中的字母顺序对数据进行排序,但你也可以通过传入level参数只选取单层级或层级的子集
frame.sort_index(level=1)
frame.swaplevel(0,1).sort_index(level=0)

如果索引从最外层开始是按字母顺序排序的,即数据是执行了sort_index(level=0)或sort_index()之后的结果,则对数据进行选取的性能会高得多。

按层级进行汇总统计

许多对DataFrame和Series的描述性和汇总性统计都有一个level选项,用于指定在某条轴的特定层级进行聚合。

frame.groupby(level="key2").sum()
# state  Ohio     Colorado
# color Green Red    Green
# key2
# 1         6   8       10
# 2        12  14       16
frame.groupby(level="color",axis="columns").sum()

使用DataFrame的列进行索引

人们通常不会将DataFrame的单列或多列用作行索引,但是可能将行索引用作DataFrame的列。

frame = pd.DataFrame({
    "a":range(7),
    "b":range(7,0,-1),
    "c":["one","one","one","two","two","two","two"],
    "d":[0,1,2,0,1,2,3]
})
#    a  b    c  d
# 0  0  7  one  0
# 1  1  6  one  1
# 2  2  5  one  2
# 3  3  4  two  0
# 4  4  3  two  1
# 5  5  2  two  2
# 6  6  1  two  3

# set_index函数会将单列或多列转换为行索引
frame2 = frame.set_index(["c","d"])
#        a  b
# c   d
# one 0  0  7
#     1  1  6
#     2  2  5
# two 0  3  4
#     1  4  3
#     2  5  2
#     3  6  1

# 默认情况下,这些列会从DataFrame中移除,但也可以通过传入drop=False将其保留下来
frame3 = frame.set_index(["c","d"],drop=False)
# reset_index的功能与set_index相反,它将层次化索引的层级转移到列
frame2.reset_index()

联合与合并数据集

pandas对象中的数据可以通过多种方式进行联合:

  • pandas.merge

    可根据单个或多个键将不同DataFrame中的行连接起来。SQL或其他关系型数据库的用户对此应该会比较熟悉,因为它实现的就是数据库的join(连接)操作。

  • pandas.concat

    沿一条轴将多个对象连接或“堆叠”到一起。

  • combine_first

    将重复数据拼接在一起,用一个对象中的值填充另一个对象中的缺失值。

数据库风格的DataFrame连接

df1 = pd.DataFrame({
    "key":["b","b","a","c","a","a","b"],
    "data1":pd.Series(range(7),dtype="Int64")
})
df2 = pd.DataFrame({
    "key":["a","b","d"],
    "data2":pd.Series(range(3),dtype="Int64")
})
# 没有指明要用哪个列进行连接,pandas.merge就会将重叠的列名当作键
# 通常,pandas.merge输出结果的列顺序是未指定的。
pd.merge(df1,df2)
#   key  data1  data2
# 0   b      0      1
# 1   b      1      1
# 2   a      2      0
# 3   a      4      0
# 4   a      5      0
# 5   b      6      1

# 指定列链接
df3 = pd.DataFrame({
    "lkey":["b","b","a","c","a","a","b"],
    "data1":pd.Series(range(7),dtype="Int64")
})
df4 = pd.DataFrame({
    "rkey":["a","b","d"],
    "data2":pd.Series(range(3),dtype="Int64")
})
pd.merge(df3,df4,left_on="lkey",right_on="rkey")

pd.merge(df1,df2,how="outer") # 外连接
pd.merge(df1,df2,how="left") # 左连接
pd.merge(df1,df2,how="right") # 右链接

how参数的不同的连接类型:

  • how="inner":只使用两张表都有的键
  • how="left":使用左表中所有的键
  • how="right":使用右表中所有的键
  • how="outer":使用两张表中所有的键
left = pd.DataFrame({
    "key1":["foo","foo","bar"],
    "key2":["one","two","one"],
    "lval":pd.Series([1,2,3],dtype="Int64")
})
right = pd.DataFrame({
    "key1":["foo","foo","bar","bar"],
    "key2":["one","one","one","two"],
    "rval":pd.Series([4,5,6,7],dtype="Int64")
})
# 多个键进行合并
pd.merge(left,right,on=["key1","key2"],how="outer")
#   key1 key2  lval  rval
# 0  bar  one     3     6
# 1  bar  two  <NA>     7
# 2  foo  one     1     4
# 3  foo  one     1     5
# 4  foo  two     2  <NA>

# 重复列
pd.merge(left,right,on="key1") # pandas.merge有一个更实用的suffixes选项,用于在左右两个DataFrame对象的重叠列名后指定需要添加的字符串
#   key1 key2_x  lval key2_y  rval
# 0  foo    one     1    one     4
# 1  foo    one     1    one     5
# 2  foo    two     2    one     4
# 3  foo    two     2    one     5
# 4  bar    one     3    one     6
# 5  bar    one     3    two     7

pandas.merge的函数参数:

  • left:参与合并的左侧DataFrame
  • right:参与合并的右侧DataFrame
  • how:连接方式,"inner""outer""left""right"其中之一。默认为"inner"
  • on:用于连接的列名。必须存在于左右两个 DataFrame 对象中。如果未指定且也未指定其他连接键,则以 left 和 right 列名的交集作为连接键
  • left_on:left DataFrame 中用作连接键的列。可以是单列列名或列名的组
    right_on:rightDataFrame中用作连接键的列
  • left_index:将left 的行索引用作连接键(如果是MultiIndex,则为多个键)
  • right_index:将right 的行索引用作连接键sort根据连接键,对合并后的数据进行排序,默认为False
  • suffixes:如果列名重合,将字符串元组追加到列名的末尾,默认为("_x","_y例如,如果左右两个DataFrame 对象都有"data",则结果中就是"data_x"和 "data_y"
  • copy:如果为False,可以在某些特殊情况下避免将数据复制到结果数据结构中。默认总是复制
  • validate:确认是否为特定类型的合并,即一对一、一对多或多对多。完整细节请查看该选项的文档字符串
  • indicator:添加特殊的列_merge,用于指明每个行的来源。根据每行的连接数据的来源,它的值为"left_only""left_only"或"both"其中之一。

根据索引合并

在某些情况下,DataFrame中的连接键位于其索引(行标签)中。在这种情况下,可以传入left_index=True或right_index=True(也可以两个都传)以说明将索引用作连接键:

left1 = pd.DataFrame({"key":["a","b","a","a","b","c"],"value":pd.Series(range(6),dtype="Int64")})
right1 = pd.DataFrame({"group_val":[3.5,7]},index=["a","b"])
pd.merge(left1,right1,left_on="key",right_index=True)
#    key  value  group_val
# 0    a      0        3.5
# 1    b      1        7.0
# 2    a      2        3.5
# 3    a      3        3.5
# 4    b      4        7.0

# 获取到并集
pd.merge(left1,right1,left_on="key",right_index=True,how="outer")

# 对于层次化索引的数据,事情就有点复杂了,因为索引的连接实际上是多键合并
left = pd.DataFrame({"key1":["Ohio","Ohio","Ohio","Nevada","Nevada"],
                     "key2":[2000,2001,2002,2001,2002],
                     "data":pd.Series(range(5),dtype="Int64")})
right_index = pd.MultiIndex.from_arrays([
    ["Nevada","Nevada","Ohio","Ohio","Ohio","Ohio"],
    [2001,2000,2000,2000,2001,2002]
])
right = pd.DataFrame({"event1":pd.Series([0,2,4,6,8,10],dtype="Int64",index=right_index),
                      "event2":pd.Series([1,3,5,7,9,11],dtype="Int64",index=right_index)})
# 以列表的形式指明用作合并键的多个列(注意,使用how="outer"处理重复索引值):
pd.merge(left,right,left_on=["key1","key2"],right_index=True)
#      key1  key2  data  event1  event2
# 0    Ohio  2000     0       4       5
# 0    Ohio  2000     0       6       7
# 1    Ohio  2001     1       8       9
# 2    Ohio  2002     2      10      11
# 3  Nevada  2001     3       0       1
pd.merge(left,right,left_on=["key1","key2"],right_index=True,how="outer")

# 同时使用双方索引
left2 = pd.DataFrame([[1.,2.],[3.,4.],[5.,6.]],index=["a","b","c"],columns=["Ohio","Nevada"]).astype("Int64")
right2 = pd.DataFrame([[7.,8.],[9.,10.],[11.,12.],[12,14]],index=["b","c","d","e"],columns=["Missouri","Alabama"]).astype("Int64")
pd.merge(left2,right2,how="outer",left_index=True,right_index=True)
#    Ohio  Nevada  Missouri  Alabama
# a     1       2      <NA>     <NA>
# b     3       4         7        8
# c     5       6         9       10
# d  <NA>    <NA>        11       12
# e  <NA>    <NA>        12       14

# DataFrame还有一个join实例方法,能更加方便地实现按索引合并。它还可用于合并多个带有相同或相似索引的DataFrame对象,但要求没有重叠的列。
left2.join(right2,how="outer") # 等同上面(DataFrame的join方法默认使用的是左连接)
left1.join(right1,on="key") # 支持在调用的DataFrame的列上连接传入DataFrame的索引

# 对于简单的索引合并,你还可以向join传入一组DataFrame
another = pd.DataFrame([[7.,8.],[9.,10.],[11.,12.],[16.,17.]],index=["a", "c", "e", "f"],columns=["New York", "Oregon"])
left2.join([right2,another])
left2.join([right2,another],how="outer")

轴向拼接

# NumPy的concatenate函数可以实现对NumPy数组的拼接
arr = np.arange(12).reshape((3,4))
np.concatenate([arr,arr],axis=1)
np.concatenate([arr,arr],axis=1)
# [[ 0  1  2  3  0  1  2  3]
#  [ 4  5  6  7  4  5  6  7]
#  [ 8  9 10 11  8  9 10 11]]

s1 = pd.Series([0,1],index=["a","b"],dtype="Int64")
s2 = pd.Series([2,3,4],index=["c","d","e"],dtype="Int64")
s3 = pd.Series([5,6],index=["f","g"],dtype="Int64")
pd.concat([s1,s2,s3]) # 默认情况下,pandas.concat是在axis="index"上工作的,最终生成一个新Series
# a    0
# b    1
# c    2
# d    3
# e    4
# f    5
# g    6
pd.concat([s1,s2,s3],axis="columns") # 这种情况下,另外的轴上没有重叠,实际上就是索引的并集(即外连接)
#       0     1     2
# a     0  <NA>  <NA>
# b     1  <NA>  <NA>
# c  <NA>     2  <NA>
# d  <NA>     3  <NA>
# e  <NA>     4  <NA>
# f  <NA>  <NA>     5
# g  <NA>  <NA>     6

s4 = pd.concat([s1,s3])
pd.concat([s1,s4],axis="columns",join="inner") # 传入join="inner"即可得到它们的交集
# 在拼接轴上创建层次化索引。可以使用参数keys来实现
pd.concat([s1,s2,s3],keys=["one","two","three"])
pd.concat([s1,s2,s3],axis="columns",keys=["one","two","three"])

# dataframe
df1 = pd.DataFrame(np.arange(6).reshape((3,2)),index=["a","b","c"],columns=["one","two"])
df2 = pd.DataFrame(5+np.arange(4).reshape((2,2)),index=["a","c"],columns=["three","four"])
pd.concat([df1,df2],axis="columns",keys=["level1","level2"])
#   level1     level2     
#      one two  three four
# a      0   1    5.0  6.0
# b      2   3    NaN  NaN
# c      4   5    7.0  8.0

# 传入的不是列表而是对象字典,则字典的键就会用于keys选项
pd.concat({"level1":df1,"level2":df2},axis="columns")
# 还有用于管理层次化索引创建方式的参数,可以用names参数命名创建的轴层级
pd.concat([df1,df2],axis="columns",keys=["level1","level2"],names=["upper","lower"])
# upper level1     level2     
# lower    one two  three four
# a          0   1    5.0  6.0
# b          2   3    NaN  NaN
# c          4   5    7.0  8.0

# ignore_index=True,它丢弃了两个DataFrame的索引,只是将列数据做了拼接,并赋值创建了一个默认的新索引
df1 = pd.DataFrame(np.random.standard_normal((3,4)),columns=["a","b","c","d"])
df2 = pd.DataFrame(np.random.standard_normal((2,3)),columns=["b","d","a"])
pd.concat([df1,df2],ignore_index=True)
#           a         b         c         d
# 0  1.705795  1.924797  0.968727  2.559045
# 1 -2.114243 -0.027911 -0.140382 -1.792394
# 2  0.746318  1.315602 -0.913124  0.945428
# 3 -0.111784  1.013329       NaN -2.247821
# 4  0.900988 -0.139223       NaN -0.063431

pandas.concat函数的参数:

  • objs:参与连接的 pandas 对象的列表或字典,这是唯一的必需参数
  • axis:指明拼接的轴,默认为沿着行拼接(axis="index")
  • join:连接方式,"inner"或"outer"(默认为"outer")。指明其他轴向上的索引是按交集("inner")还是并集("outer")进行合并
  • keys:与要拼接的对象有关的值,用于形成连接轴向上的层次化索引。可以是任意值的列表或数组、任意元组数组或数组列表(如果向levels 参数传入多层级数组)
  • levels:如果传入了keys,则指定用作层次化索引各层级上的索引
  • names:如果设置了keys和(或)levels,则用作多层索引l的层级名称
  • verify_integrity:检查拼接得到的对象新轴是否存在重复项,如果发现重复则抛出异常。默认(False)允许重复项
  • ignore_index:不保留拼接轴上的索引l,而是产生一个新索引丨range(total_length)

联合重叠数据

还有一种数据联合场景不能用合并或拼接来处理。比如说,你可能有索引全部或部分重叠的两个数据集。

# 对于NumPy的where函数,它可以实现面向数组且等价于if-else表达式的操作
a = pd.Series([np.nan,2.5,0.0,3.5,4.5,np.nan],index=["f","e","d","c","b","a"])
b = pd.Series([0.,np.nan,2.,np.nan,np.nan,5.],index=["a","b","c","d","e","f"])
np.where(pd.isna(a),b,a) # [0.  2.5 0.  3.5 4.5 5. ]
# 按照索引排列值,需要使用Series的combine_first方法
a.combine_first(b)
# a    0.0
# b    4.5
# c    3.5
# d    0.0
# e    2.5
# f    5.0
# dtype: float64

# 对于DataFrame,combine_first也会逐列做同样的操作,因此可以认为用传入对象的数据为调用对象的缺失数据“打补丁”​:
df1 = pd.DataFrame({"a": [1., np.nan, 5., np.nan],"b": [np.nan, 2., np.nan, 6.],"c": range(2, 18, 4)})
df2 = pd.DataFrame({"a":[5., 4., np.nan, 3.,7.],"b": [np.nan, 3., 4., 6., 8.]})
df1.combine_first(df2)
#      a    b     c
# 0  1.0  NaN   2.0
# 1  4.0  2.0   6.0
# 2  5.0  4.0  10.0
# 3  3.0  6.0  14.0
# 4  7.0  8.0   NaN

重塑和透视

有多种基础操作用于重新排列表格型数据。这些操作也称作重塑或透视。

使用层次化索引进行重塑

层次化索引为重排DataFrame数据提供了一种具有良好一致性的方式。主要有两种操作:

  • stack:将数据的列“旋转”为行。
  • unstack:将数据的行透视为列。
data = pd.DataFrame(np.arange(6).reshape((2,3)),
                    index=pd.Index(["Ohio","Colorado"],name="state"),
                    columns=pd.Index(["one","two","three"],name="number"))
# number    one  two  three
# state
# Ohio        0    1      2
# Colorado    3    4      5
result = data.stack()
# state     number
# Ohio      one       0
#           two       1
#           three     2
# Colorado  one       3
#           two       4
#           three     5
# dtype: int64
result.unstack()
# number    one  two  three
# state
# Ohio        0    1      2
# Colorado    3    4      5

# 默认情况下,unstack操作的是最内层(stack也是如此)​。传入层级编号或名称,即可对其他层级进行unstack操作:
result.unstack(level=0)
state   Ohio  Colorado
number
one        0         3
two        1         4
three      2         5

result.unstack(level="state")
# state   Ohio  Colorado
# number
# one        0         3
# two        1         4
# three      2         5

# 如果在各子分组中不能找到所有层级的值,则unstack操作可能会导入缺失数据:
s1 = pd.Series([0,1,2,3],index=["a","b","c","d"],dtype="Int64")
s2 = pd.Series([4,5,6],index=["c","d","e"],dtype="Int64")
data2 = pd.concat([s1,s2],keys=["one","two"])
# one  a    0
#      b    1
#      c    2
#      d    3
# two  c    4
#      d    5
#      e    6

data2.unstack()
#         a     b  c  d     e
# one     0     1  2  3  <NA>
# two  <NA>  <NA>  4  5     6

# stack操作会默认过滤缺失数据,因此该运算是可逆的
data2.unstack().stack()
# one  a    0
#      b    1
#      c    2
#      d    3
# two  c    4
#      d    5
#      e    6
# dtype: Int64

data2.unstack().stack(dropna=False)
# one  a       0
#      b       1
#      c       2
#      d       3
#      e    <NA>
# two  a    <NA>
#      b    <NA>
#      c       4
#      d       5
#      e       6
# dtype: Int64

# 在对DataFrame进行unstack操作时,被拆分的层级将成为结果中的最低层级:
df = pd.DataFrame({"left":result,"right":result+5},
                  columns=pd.Index(["left","right"],name="side"))
# side             left  right
# state    number
# Ohio     one        0      5
#          two        1      6
#          three      2      7
# Colorado one        3      8
#          two        4      9
#          three      5     10

df.unstack(level="state")
# side   left          right
# state  Ohio Colorado  Ohio Colorado
# number
# one       0        3     5        8
# two       1        4     6        9
# three     2        5     7       10

df.unstack(level="state").stack(level="side")
# state         Ohio  Colorado
# number side
# one    left      0         3
#        right     5         8
# two    left      1         4
#        right     6         9
# three  left      2         5
#        right     7        10

将“长格式”透视为“宽格式”

多个时间序列数据通常是以所谓的“长格式”或“堆叠格式”存储在数据库和CSV中的。对于这种格式,表中的每行表示单个值,而不是表示多个值。

002

data = pd.read_csv("007.csv")
data = data.loc[:,["year","quarter","realgdp","infl","unemp"]]
#    year  quarter   realgdp  infl  unemp
# 0  1959        1  2710.349  0.00    5.8
# 1  1959        2  2778.801  2.34    5.1
# 2  1959        3  2775.488  2.74    5.3
# 3  1959        4  2785.204  0.27    5.6
# 4  1960        1  2847.699  2.31    5.2

# 首先,我使用pandas.PeriodIndex(来表示时间区间,而非时间点)将year和quarter列联合并设置索引,让索引包含每个季度末的datetime值
# DataFrame上使用了pop方法,返回一列的同时将其从DataFrame删除
periods = pd.PeriodIndex(year=data.pop("year"),quarter=data.pop("quarter"),name="date") # 
# PeriodIndex(['1959Q1', '1959Q2', '1959Q3', '1959Q4', '1960Q1'], dtype='period[Q-DEC]', name='date')

data.index = periods.to_timestamp("D")
#              realgdp  infl  unemp
# date
# 1959-01-01  2710.349  0.00    5.8
# 1959-04-01  2778.801  2.34    5.1
# 1959-07-01  2775.488  2.74    5.3
# 1959-10-01  2785.204  0.27    5.6
# 1960-01-01  2847.699  2.31    5.2

data = data.reindex(columns=["realgdp","infl","unemp"])
data.columns.name="item"

# 使用stack操作进行重塑,并使用reset_index将新的索引层级移到列,最后将包含数据值的列命名为"value"
long_data = (data.stack().reset_index().rename(columns={0:"value"}))
#          date     item     value
# 0  1959-01-01  realgdp  2710.349
# 1  1959-01-01     infl     0.000
# 2  1959-01-01    unemp     5.800
# 3  1959-04-01  realgdp  2778.801
# 4  1959-04-01     infl     2.340
# 5  1959-04-01    unemp     5.100
# 6  1959-07-01  realgdp  2775.488
# 7  1959-07-01     infl     2.740
# 8  1959-07-01    unemp     5.300
# 9  1959-10-01  realgdp  2785.204
# 10 1959-10-01     infl     0.270
# 11 1959-10-01    unemp     5.600
# 12 1960-01-01  realgdp  2847.699
# 13 1960-01-01     infl     2.310
# 14 1960-01-01    unemp     5.200

# 行转列
pivoted = long_data.pivot(index="date",columns="item",values="value")
# item        infl   realgdp  unemp
# date
# 1959-01-01  0.00  2710.349    5.8
# 1959-04-01  2.34  2778.801    5.1
# 1959-07-01  2.74  2775.488    5.3
# 1959-10-01  0.27  2785.204    5.6
# 1960-01-01  2.31  2847.699    5.2

long_data["value2"] = np.random.standard_normal(len(long_data))
pivoted = long_data.pivot(index="date",columns="item") # 带有层次化索引的列
#            value                    value2
# item        infl   realgdp unemp      infl   realgdp     unemp
# date
# 1959-01-01  0.00  2710.349   5.8 -0.665122 -2.792897  0.220848
# 1959-04-01  2.34  2778.801   5.1  0.334898  1.479825 -0.261793
# 1959-07-01  2.74  2775.488   5.3 -1.937168 -0.440664  1.504955
# 1959-10-01  0.27  2785.204   5.6 -0.385309  1.003587  0.520601
# 1960-01-01  2.31  2847.699   5.2  0.183695 -0.190552 -0.499543

pivoted["value"]
# item        infl   realgdp  unemp
# date
# 1959-01-01  0.00  2710.349    5.8
# 1959-04-01  2.34  2778.801    5.1
# 1959-07-01  2.74  2775.488    5.3
# 1959-10-01  0.27  2785.204    5.6
# 1960-01-01  2.31  2847.699    5.2

# pivot其实就等价于先用set_index创建层次化索引,再用unstack重塑
unstacked = long_data.set_index(["date","item"]).unstack(level="item")

将“宽格式”透视为“长格式”

对于DataFrame,pivot操作的逆运算是pandas.melt。它不是将一列转换为新DataFrame中的多列,而是将多个列合并成一列,并生成比输入更长的DataFrame。

df = pd.DataFrame({"key":["foo","bar","baz"],"A":[1,2,3],"B":[4,5,6],"C":[7,8,9]})
#    key  A  B  C
# 0  foo  1  4  7
# 1  bar  2  5  8
# 2  baz  3  6  9

# 当使用pandas.melt时,必须指明哪些列(如果有的话)是分组指标。下面使用"key"作为唯一的分组指标
melted = pd.melt(df,id_vars="key")  # 就是行转列吧
#    key variable  value
# 0  foo        A      1
# 1  bar        A      2
# 2  baz        A      3
# 3  foo        B      4
# 4  bar        B      5
# 5  baz        B      6
# 6  foo        C      7
# 7  bar        C      8
# 8  baz        C      9

# pivot,可以将其重塑回原来的形式
reshaped = melted.pivot(index="key",columns="variable",values="value")
# variable  A  B  C
# key
# bar       2  5  8
# baz       3  6  9
# foo       1  4  7

reshaped = reshaped.reset_index() # 所以我们可以使用reset_index将数据再移回到列
# variable  key  A  B  C
# 0         bar  2  5  8
# 1         baz  3  6  9
# 2         foo  1  4  7

pd.melt(df,id_vars="key",value_vars=["A","B"]) # 指定列的子集用作value列
#    key variable  value
# 0  foo        A      1
# 1  bar        A      2
# 2  baz        A      3
# 3  foo        B      4
# 4  bar        B      5
# 5  baz        B      6

# pandas.melt也可以不使用任何分组指标
pd.melt(df,value_vars=["A","B","c"])
#   variable  value
# 0        A      1
# 1        A      2
# 2        A      3
# 3        B      4
# 4        B      5
# 5        B      6
# 6        C      7
# 7        C      8
# 8        C      9
pd.melt(df,value_vars=["key","A","B"])
#   variable value
# 0      key   foo
# 1      key   bar
# 2      key   baz
# 3        A     1
# 4        A     2
# 5        A     3
# 6        B     4
# 7        B     5
# 8        B     6
posted @ 2025-05-11 11:02  huihui_teresa  阅读(15)  评论(0)    收藏  举报