Skip to content

Latest commit

 

History

History
972 lines (726 loc) · 27.8 KB

File metadata and controls

972 lines (726 loc) · 27.8 KB

十、R 与 Pandas 的比较

本章着重于将 Pandas 与 R 进行比较,R 是对许多 Pandas 功能进行建模的统计包。 本手册旨在为希望使用 Pandas 的 R 用户以及希望复制他们在 Pandas R 代码中看到的功能的用户提供指南。 它着重介绍了 R 用户可用的一些关键功能,并通过使用一些说明性示例演示了如何在 Pandas 中实现类似功能。 本章假定您已安装 R 统计包。 如果没有,则可以从此处下载并安装

在本章的最后,数据分析用户应该比 Pandas 更好地掌握 R 的数据分析功能,从而使他们可以过渡到 Pandas 或使用 Pandas。 本章讨论的各个主题包括:

  • R 数据类型及其等效的 Pandas
  • 切片和选择
  • 数据类型列的算术运算
  • 聚合和分组
  • 匹配
  • 拆分合并
  • 熔化和重塑
  • 因子和类别数据

R 数据类型

R 具有五种原始或原子类型:

  • 字符
  • 数字
  • 整数
  • 复数
  • 逻辑/布尔

它还具有以下更复杂的容器类型:

  • 向量:类似于numpy.array。 它只能包含相同类型的对象。
  • 列表:这是一个异构容器。 相当于 Pandas 的序列。
  • 数据帧 :这是一个异构 2D 容器,等效于 Pandas 数据帧
  • 矩阵:它是向量的均质 2D 版本。 它类似于numpy.matrix

在本章中,我们将重点关注列表和数据帧,它们具有与序列和数据帧等效的 Pandas。

注意

有关 R 数据类型的更多信息,请参考这个文档

对于 NumPy 数据类型,请参考这个文档这个文档

R 列表

R 列表可以显式创建为列表声明,如下所示:

>h_lst<- list(23,'donkey',5.6,1+4i,TRUE)
>h_lst
[[1]]
[1] 23

[[2]]
[1] "donkey"

[[3]]
[1] 5.6

[[4]]
[1] 1+4i

[[5]]
[1] TRUE

>typeof(h_lst)
[1] "list"

以下是其在 Pandas 中的序列,包括创建列表和从中创建序列:

In [8]: h_list=[23, 'donkey', 5.6,1+4j, True]
In [9]: import pandas as pd
 h_ser=pd.Series(h_list)
In [10]: h_ser
Out[10]: 0        23
 1    donkey
 2       5.6
 3    (1+4j)
 4      True
dtype: object

Pandas 数组索引从 0 开始,而 R 则以 1 开始。下面是一个示例:

In [11]: type(h_ser)
Out[11]: pandas.core.series.Series

R 数据帧

我们可以通过调用data.frame()构造器来构造 R 数据帧,如下所示:

>stocks_table<- data.frame(Symbol=c('GOOG','AMZN','FB','AAPL',
 'TWTR','NFLX','LINKD'), 
 Price=c(518.7,307.82,74.9,109.7,37.1,
 334.48,219.9),
MarketCap=c(352.8,142.29,216.98,643.55,23.54,20.15,27.31))

>stocks_table
Symbol  PriceMarketCap
1   GOOG 518.70    352.80
2   AMZN 307.82    142.29
3     FB  74.90    216.98
4   AAPL 109.70    643.55
5   TWTR  37.10     23.54
6   NFLX 334.48     20.15
7  LINKD 219.90     27.31

在这里,我们构造一个 Pandas 数据帧并显示它:

In [29]: stocks_df=pd.DataFrame({'Symbol':['GOOG','AMZN','FB','AAPL', 
 'TWTR','NFLX','LNKD'],
 'Price':[518.7,307.82,74.9,109.7,37.1,
 334.48,219.9],
'MarketCap($B)' : [352.8,142.29,216.98,643.55,
 23.54,20.15,27.31]
 })
stocks_df=stocks_df.reindex_axis(sorted(stocks_df.columns,reverse=True),axis=1)
stocks_df
Out[29]:
Symbol  PriceMarketCap($B)
0       GOOG    518.70  352.80
1       AMZN    307.82  142.29
2       FB      74.90   216.98
3       AAPL    109.70  643.55
4       TWTR    37.10   23.54
5       NFLX    334.48  20.15
6       LNKD219.90  27.31

切片和选择

在 R 中,我们通过以下三种方式对对象进行切片:

  • [:这始终返回与原始对象相同类型的对象,并且可以用于选择多个元素。
  • [[:用于提取列表或数据帧的元素; 并且只能用于提取单个元素:返回的元素的类型不一定是列表或数据帧。
  • $:用于按名称提取列表或数据帧的元素,类似于[[

这是 R 中的一些切片示例及其在 Pandas 中的等效示例:

R 矩阵和 NumPy 数组比较

让我们看看 R 中的矩阵创建和选择:

>r_mat<- matrix(2:13,4,3)
>r_mat
 [,1] [,2] [,3]
[1,]    2    6   10
[2,]    3    7   11
[3,]    4    8   12
[4,]    5    9   13

要选择第一行,我们编写:

>r_mat[1,]
[1]  2  6 10

要选择第二列,我们使用以下命令:

>r_mat[,2]
[1] 6 7 8 9

现在让我们来看一下 NumPy 数组的创建和选择:

In [60]: a=np.array(range(2,6))
 b=np.array(range(6,10))
 c=np.array(range(10,14))
In [66]: np_ar=np.column_stack([a,b,c])
np_ar
Out[66]: array([[ 2,  6, 10],
[ 3,  7, 11],
[ 4,  8, 12],
[ 5,  9, 13]])

要选择第一行,请编写以下命令:

In [79]: np_ar[0,]
Out[79]: array([ 2,  6, 10])

索引在 R 和 pandas/NumPy 中是不同的。

在 R 中,索引从 1 开始,而在 pandas/NumPy 中,索引从 0 开始。因此,当从 R 转换到 pandas/NumPy 时,我们必须从所有索引中减去 1。

要选择第二列,请编写以下命令:

In [81]: np_ar[:,1]
Out[81]: array([6, 7, 8, 9])

另一个选择是先转置数组,然后选择列,如下所示:

In [80]: np_ar.T[1,]
Out[80]: array([6, 7, 8, 9])

R 列表和 Pandas 序列比较

这是在 R 中创建和选择列表的示例:

>cal_lst<- list(weekdays=1:8, mth='jan')
>cal_lst
$weekdays
[1] 1 2 3 4 5 6 7 8

$mth
[1] "jan"

>cal_lst[1]
$weekdays
[1] 1 2 3 4 5 6 7 8

>cal_lst[[1]]
[1] 1 2 3 4 5 6 7 8

>cal_lst[2]
$mth
[1] "jan"

Pandas 的序列创建和选择如下:

In [92]: cal_df= pd.Series({'weekdays':range(1,8), 'mth':'jan'})
In [93]: cal_df
Out[93]: mthjan
weekdays    [1, 2, 3, 4, 5, 6, 7]
dtype: object

In [97]: cal_df[0]
Out[97]: 'jan'

In [95]: cal_df[1]
Out[95]: [1, 2, 3, 4, 5, 6, 7]

In [96]: cal_df[[1]]
Out[96]: weekdays    [1, 2, 3, 4, 5, 6, 7]
dtype: object

在这里,从[][[]]运算符的角度来看,我们看到 R 列表和 Pandas 序列之间的差异。 我们可以通过考虑第二项(字符串)来看到差异。

对于 R,[]运算符产生一个容器类型,即包含字符串的列表,而[[]]产生一个原子类型:在这种情况下,一个字符如下:

>typeof(cal_lst[2])
[1] "list"
>typeof(cal_lst[[2]])
[1] "character"

对于 Pandas,情况恰恰相反:[]产生原子类型,而[[]]产生复杂类型,即序列的序列,如下所示:

In [99]: type(cal_df[0])
Out[99]: str

In [101]: type(cal_df[[0]])
Out[101]: pandas.core.series.Series

在 R 和 pandas 中,都可以指定列名称以获得元素。

在 R 中指定列名

在 R 中,可以使用$运算符前面的列名来完成此操作,如下所示:

>cal_lst$mth
[1] "jan"
> cal_lst$'mth'
[1] "jan"

在 Pandas 中指定列名

在 Pandas 中,我们以通常的方式将元素子集括在方括号中:

In [111]: cal_df['mth']
Out[111]: 'jan'

R 和 Pandas 不同的一个区域是嵌套元素的子集。 例如,要从工作日获得第 4 天,我们必须在 R 中使用[[]]运算符:

>cal_lst[[1]][[4]]
[1] 4

>cal_lst[[c(1,4)]]
[1] 4 

但是,对于 Pandas,我们可以使用双倍[]

In [132]: cal_df[1][3]
Out[132]: 4

R 的数据帧与 Pandas 的数据帧

在 R 数据帧和 Pandas 数据帧中选择数据遵循类似的脚本。 以下部分说明了我们如何从这两种方法中执行多列选择。

R 中的多列选择

在 R 中,我们通过在方括号内的向量中声明多列来指定要选择的列:

>stocks_table[c('Symbol','Price')]
Symbol  Price
1   GOOG 518.70
2   AMZN 307.82
3     FB  74.90
4   AAPL 109.70
5   TWTR  37.10
6   NFLX 334.48
7  LINKD 219.90

>stocks_table[,c('Symbol','Price')]
Symbol  Price
1   GOOG 518.70
2   AMZN 307.82
3     FB  74.90
4   AAPL 109.70
5   TWTR  37.10
6   NFLX 334.48
7  LINKD 219.90

Pandas 中的多列选择

在 Pandas 中,我们以通常的方式将元素子集括在方括号中:

In [140]: stocks_df[['Symbol','Price']]
Out[140]:Symbol Price
0        GOOG   518.70
1        AMZN   307.82
2        FB     74.90
3        AAPL   109.70
4        TWTR   37.10
5        NFLX   334.48
6        LNKD   219.90

In [145]: stocks_df.loc[:,['Symbol','Price']]
Out[145]: Symbol  Price
0         GOOG    518.70
1         AMZN    307.82
2         FB      74.90
3         AAPL    109.70
4         TWTR    37.10
5         NFLX    334.48
6         LNKD    219.90

列上的算术运算

在 R 和 pandas 中,我们可以类似的方式在数据列中应用算术运算。 因此,我们可以对两个或多个数据帧中相应位置的元素执行算术运算,例如加法或减法。

在这里,我们在 R 中构造一个带有xy列的数据帧,然后从x列中减去y列:

>norm_df<- data.frame(x=rnorm(7,0,1), y=rnorm(7,0,1))
>norm_df$x - norm_df$y
[1] -1.3870730  2.4681458 -4.6991395  0.2978311 -0.8492245  1.5851009 -1.4620324

R 中的with运算符也具有与算术运算相同的效果:

>with(norm_df,x-y)
[1] -1.3870730  2.4681458 -4.6991395  0.2978311 -0.8492245  1.5851009 -1.4620324

在 Pandas 中,可以对列执行相同的算术运算,并且等效运算符为eval

In [10]: import pandas as pd
 import numpy as np
df = pd.DataFrame({'x': np.random.normal(0,1,size=7), 'y': np.random.normal(0,1,size=7)})

In [11]: df.x-df.y
Out[11]: 0   -0.107313
 1    0.617513
 2   -1.517827
 3    0.565804
 4   -1.630534
 5    0.101900
 6    0.775186
dtype: float64

In [12]: df.eval('x-y')
Out[12]: 0   -0.107313
 1    0.617513
 2   -1.517827
 3    0.565804
 4   -1.630534
 5    0.101900
 6    0.775186
dtype: float64

聚合和分组

有时,我们可能希望将数据拆分为子集,并对每个子集应用平均值,最大值或最小值之类的函数。 在 R 中,我们可以通过aggregatetapply函数执行此操作。

在这里,我们将使用 2014 年欧洲冠军联赛半决赛进入的四家具乐部前五名前锋的统计数据集的示例。我们将使用它来说明 R 及其得分的聚合,在 Pandas 中具有等效的分组功能。

R 中的聚合

在 R 中,聚合是使用以下命令完成的:

> goal_stats=read.csv('champ_league_stats_semifinalists.csv')
>goal_stats
 Club                 Player Goals GamesPlayed
1  Atletico Madrid            Diego Costa     8           9
2  Atletico Madrid             ArdaTuran     4           9
3  Atletico Madrid            RaúlGarcía     4          12
4  Atletico Madrid           AdriánLópez     2           9
5  Atletico Madrid            Diego Godín     2          10
6      Real Madrid      Cristiano Ronaldo    17          11
7      Real Madrid            Gareth Bale     6          12
8      Real Madrid          Karim Benzema     5          11
9      Real Madrid                   Isco     3          12
10     Real Madrid         Ángel Di María     3          11
11   Bayern Munich          Thomas Müller     5          12
12   Bayern Munich           ArjenRobben     4          10
13   Bayern Munich            Mario Götze     3          11
14   Bayern Munich Bastian Schweinsteiger     3           8
15   Bayern Munich        Mario Mandžukić     3          10
16         Chelsea        Fernando Torres     4           9
17         Chelsea               Demba Ba     3           6
18         Chelsea           Samuel Eto'o     3           9
19         Chelsea            Eden Hazard     2           9
20         Chelsea                Ramires     2          10

现在,我们可以计算每个前锋的每场比赛进球数比例,以衡量他们在进球前的最后期限:

>goal_stats$GoalsPerGame<- goal_stats$Goals/goal_stats$GamesPlayed
>goal_stats
 Club   Player         Goals GamesPlayedGoalsPerGame
1  Atletico Madrid  Diego Costa     8           9    0.8888889
2  Atletico Madrid  ArdaTuran      4           9    0.4444444
3  Atletico Madrid  RaúlGarcía     4          12    0.3333333
4  Atletico Madrid  AdriánLópez    2           9    0.2222222
5  Atletico Madrid  Diego Godín     2          10    0.2000000
6  Real Madrid  Cristiano Ronaldo  17          11    1.5454545
7  Real Madrid  Gareth Bale         6          12    0.5000000
8  Real Madrid    Karim Benzema     5          11    0.4545455
9  Real Madrid       Isco           3          12    0.2500000
10 Real Madrid  Ángel Di María     3          11    0.2727273
11 Bayern Munich Thomas Müller     5          12    0.4166667
12 Bayern Munich  ArjenRobben     4          10    0.4000000
13 Bayern Munich  MarioGötze      3          11    0.2727273
14 Bayern Munich Bastian Schweinsteiger 3      8    0.3750000
15 Bayern Munich  MarioMandžukić  3          10    0.3000000
16 Chelsea       Fernando Torres   4           9    0.4444444
17 Chelsea           Demba Ba      3           6    0.5000000
18 Chelsea           Samuel Eto'o  3           9    0.3333333
19 Chelsea            Eden Hazard  2           9    0.2222222
20 Chelsea                Ramires  2          10    0.2000000

假设我们想知道每个团队的最高进球率。 我们将计算如下:

>aggregate(x=goal_stats[,c('GoalsPerGame')], by=list(goal_stats$Club),FUN=max)
 Group.1         x
1 Atletico Madrid 0.8888889
2   Bayern Munich 0.4166667
3         Chelsea 0.5000000
4     Real Madrid 1.5454545

tapply函数用于将函数应用于由一个或多个列定义的数组或向量的子集。 tapply函数还可以如下使用:

>tapply(goal_stats$GoalsPerGame,goal_stats$Club,max)
Atletico Madrid   Bayern Munich         Chelsea     Real Madrid 
 0.8888889       0.4166667       0.5000000       1.5454545

Pandas 的分组操作

在 Pandas 中,我们可以使用GroupBy函数获得相同的结果:

In [6]: import pandas as pd
importnumpy as np
In [7]: goal_stats_df=pd.read_csv('champ_league_stats_semifinalists.csv')

In [27]: goal_stats_df['GoalsPerGame']=     goal_stats_df['Goals']/goal_stats_df['GamesPlayed']

In [27]: goal_stats_df['GoalsPerGame']= goal_stats_df['Goals']/goal_stats_df['GamesPlayed']

In [28]: goal_stats_df
Out[28]: Club           Player      Goals GamesPlayedGoalsPerGame
0       Atletico Madrid Diego Costa   8       9        0.888889
1       Atletico Madrid ArdaTuran    4       9         0.444444
2       Atletico Madrid RaúlGarcía   4       12        0.333333
3       Atletico Madrid AdriánLópez  2       9         0.222222
4       Atletico Madrid Diego Godín   2       10        0.200000
5       Real Madrid  Cristiano Ronaldo 17      11        1.545455
6       Real Madrid     Gareth Bale   6       12        0.500000
7       Real Madrid     Karim Benzema 5       11        0.454545
8       Real Madrid     Isco          3       12        0.250000
9       Real Madrid     Ángel Di María 3      11        0.272727
10      Bayern Munich   Thomas Müller  5       12        0.416667
11      Bayern Munich   ArjenRobben   4       10        0.400000
12      Bayern Munich   Mario Götze    3       11        0.272727
13      Bayern Munich  BastianSchweinsteiger 3   8     0.375000
14      Bayern Munich  MarioMandžukić  3       10        0.300000
15      Chelsea        Fernando Torres  4       9         0.444444
16      Chelsea        Demba Ba         3       6         0.500000
17      Chelsea        Samuel Eto'o     3       9         0.333333
18      Chelsea        Eden Hazard      2       9         0.222222
19      Chelsea        Ramires          2       10        0.200000

In [30]: grouped = goal_stats_df.groupby('Club')

In [17]: grouped['GoalsPerGame'].aggregate(np.max)
Out[17]: Club
 Atletico Madrid    0.888889
 Bayern Munich      0.416667
 Chelsea            0.500000
 Real Madrid        1.545455
 Name: GoalsPerGame, dtype: float64

In [22]: grouped['GoalsPerGame'].apply(np.max)

Out[22]: Club
 Atletico Madrid    0.888889
 Bayern Munich      0.416667
 Chelsea            0.500000
 Real Madrid        1.545455
 Name: GoalsPerGame, dtype: float64

比较 R 和 Panda 中的匹配运算符

在这里,我们将证明 R(%in%)和 Pandas(isin())之间匹配运算符的等价性。 在这两种情况下,都会生成逻辑向量或序列(Pandas),该逻辑向量或序列指示找到匹配项的位置。

R %in%运算符

在这里,我们将演示 R 中%in%运算符的用法:

>stock_symbols=stocks_table$Symbol
>stock_symbols
[1] GOOG  AMZN  FB  AAPL  TWTR  NFLX  LINKD
Levels: AAPL AMZN FB GOOG LINKD NFLX TWTR

>stock_symbols %in% c('GOOG','NFLX')
[1]  TRUE FALSE FALSE FALSE FALSE  TRUE FALSE

Pandas isin()函数

这是使用 Pandasisin()函数的示例:

In [11]: stock_symbols=stocks_df.Symbol
stock_symbols
Out[11]: 0    GOOG
 1    AMZN
 2      FB
 3    AAPL
 4    TWTR
 5    NFLX
 6    LNKD
 Name: Symbol, dtype: object
In [10]: stock_symbols.isin(['GOOG','NFLX'])
Out[10]: 0     True
 1    False
 2    False
 3    False
 4    False
 5     True
 6    False
 Name: Symbol, dtype: bool

逻辑子集

在 R 和 Pandas 中,执行逻辑子设置的方法不止一种。 假设我们希望显示所有平均进球数大于或等于 0.5 的球员; 也就是说,他们每两场比赛平均至少有一个进球。

R 中的逻辑子集

我们可以在 R 中执行以下操作:

  • 通过逻辑切片:

    >goal_stats[goal_stats$GoalsPerGame>=0.5,]
     Club            Player        Goals GamesPlayedGoalsPerGame
    1  Atletico Madrid Diego Costa     8           9    0.8888889
    6  Real Madrid Cristiano Ronaldo  17          11    1.5454545
    7  Real Madrid       Gareth Bale   6          12    0.5000000
    17 Chelsea          Demba Ba     3           6    0.5000000
  • 通过subset()函数:

    >subset(goal_stats,GoalsPerGame>=0.5)
     Club            Player      Goals GamesPlayedGoalsPerGame
    1  Atletico Madrid Diego Costa    8           9    0.8888889
    6  Real Madrid Cristiano Ronaldo 17          11    1.5454545
    7  Real Madrid     Gareth Bale    6          12    0.5000000
    17 Chelsea          Demba Ba     3           6    0.5000000

Pandas 中的逻辑子集

在 Pandas 中,我们也做类似的事情:

  • 逻辑切片:

    In [33]: goal_stats_df[goal_stats_df['GoalsPerGame']>=0.5]
    Out[33]:     Club        Player            Goals GamesPlayedGoalsPerGame
    0    Atletico Madrid Diego Costa     8     9          0.888889
    5    Real Madrid   Cristiano Ronaldo 17    11         1.545455
    6    Real Madrid     Gareth Bale     6     12         0.500000
    16   Chelsea         Demba Ba        3     6           0.500000
  • DataFrame.query()运算符:

    In [36]:  goal_stats_df.query('GoalsPerGame>= 0.5')
    Out[36]:
    Club              Player   Goals GamesPlayedGoalsPerGame
    0    Atletico Madrid Diego Costa   8     9            0.888889
    5    Real Madrid  Cristiano Ronaldo 17    11           1.545455
    6    Real Madrid     Gareth Bale    6     12           0.500000
    16   Chelsea         Demba Ba       3     6            0.500000

拆分合并

R 有一个名为plyr的库,用于拆分应用合并数据分析。 plyr库具有一个称为ddply的函数,该函数可用于将函数应用于数据帧的子集,然后将结果组合到另一个数据帧中。

有关ddply的更多信息,您可以参考这个内容

为说明起见,让我们考虑一个最近在 R 中创建的数据集的子集,其中包含 2013 年离开纽约市的航班数据

在 R 中执行

在这里,我们将在 R 中安装该包并实例化该库:

>install.packages('nycflights13')
...

>library('nycflights13')
>dim(flights)
[1] 336776     16

>head(flights,3)
year month day dep_timedep_delayarr_timearr_delay carrier tailnum flight
1 2013     1   1      517         2      830        11      UA  N14228   1545
2 2013     1   1      533         4      850        20      UA  N24211   1714
3 2013     1   1      542         2      923        33      AA  N619AA   1141
origindestair_time distance hour minute
1    EWR  IAH      227     1400    5     17
2    LGA  IAH      227     1416    5     33
3    JFK  MIA      160     1089    5     42

> flights.data=na.omit(flights[,c('year','month','dep_delay','arr_delay','distance')])
>flights.sample<- flights.data[sample(1:nrow(flights.data),100,replace=FALSE),]

>head(flights.sample,5)
year month dep_delayarr_delay distance
155501 2013     3         2         5      184
2410   2013     1         0         4      762
64158  2013    11        -7       -27      509
221447 2013     5        -5       -12      184
281887 2013     8        -1       -10      937

ddply函数使我们能够按年和月聚合离港延误(均值,标准差):

>ddply(flights.sample,.(year,month),summarize, mean_dep_delay=round(mean(dep_delay),2), s_dep_delay=round(sd(dep_delay),2))
year month mean_dep_delaysd_dep_delay
1  2013     1          -0.20         2.28
2  2013     2          23.85        61.63
3  2013     3          10.00        34.72
4  2013     4           0.88        12.56
5  2013     5           8.56        32.42
6  2013     6          58.14       145.78
7  2013     7          25.29        58.88
8  2013     8          25.86        59.38
9  2013     9          -0.38        10.25
10 2013    10           9.31        15.27
11 2013    11          -1.09         7.73
12 2013    12           0.00         8.58

让我们将flights.sample数据集保存到 CSV 文件中,以便我们可以使用该数据向我们展示如何在 Pandas 中执行相同的操作:

>write.csv(flights.sample,file='nycflights13_sample.csv', quote=FALSE,row.names=FALSE)

在 Pandas 中实现

为了在 Pandas 中做同样的事情,我们阅读了上一节中保存的 CSV 文件:

In [40]: flights_sample=pd.read_csv('nycflights13_sample.csv')

In [41]: flights_sample.head()
Out[41]: year   month   dep_delayarr_delay       distance
0        2013   3       2       5       184
1        2013   1       0       4       762
2        2013   11      -7      -27     509
3        2013   5       -5      -12     184
4        2013   8       -1      -10     937

通过使用GroupBy()运算符,可以达到与ddply相同的效果:

In [44]: pd.set_option('precision',3)
In [45]: grouped = flights_sample_df.groupby(['year','month'])

In [48]: grouped['dep_delay'].agg([np.mean, np.std])

Out[48]:        mean    std
year    month 
2013    1       -0.20   2.28
 2       23.85   61.63
 3       10.00   34.72
 4       0.88    12.56
 5       8.56    32.42
 6       58.14   145.78
 7       25.29   58.88
 8       25.86   59.38
 9       -0.38   10.25
 10      9.31    15.27
 11      -1.09   7.73
 12      0.00    8.58

熔化和重塑

melt函数将数据转换为宽格式,以单列组成唯一的 ID 变量组合。

R 的melt()函数

在这里,我们演示了 R 中melt()函数的用法。它生成长格式数据,其中的行是唯一的变量值组合:

>sample4=head(flights.sample,4)[c('year','month','dep_delay','arr_delay')]
> sample4
 year month dep_delay arr_delay
 155501 2013     3          2         5
 2410   2013     1          0         4
 64158  2013    11         -7       -27
 221447 2013     5         -5       -12

>melt(sample4,id=c('year','month'))
 year month  variable value
 1 2013     3 dep_delay     2
 2 2013     1 dep_delay     0
 3 2013    11 dep_delay    -7
 4 2013     5 dep_delay    -5
 5 2013     3 arr_delay     5
 6 2013     1 arr_delay     4
 7 2013    11 arr_delay   -27
 8 2013     5 arr_delay   -12
>

有关更多信息,您可以参考这个内容

Pandas 的melt()函数

在 Pandas 中,melt函数类似:

In [55]: sample_4_df=flights_sample_df[['year','month','dep_delay', \
'arr_delay']].head(4)
In [56]: sample_4_df
Out[56]:    year   month dep_delay arr_delay
 0   2013   3       2       5
 1   2013   1       0       4
 2   2013   11      -7      -27
 3   2013   5       -5      -12

In [59]: pd.melt(sample_4_df,id_vars=['year','month'])
Out[59]: year   month   variable        value
 0   2013   3       dep_delay        2
 1   2013   1       dep_delay        0
 2   2013   11      dep_delay       -7
 3   2013   5       dep_delay       -5
 4   2013   3       arr_delay        5
 5   2013   1       arr_delay        4
 6   2013   11      arr_delay       -27
 7   2013   5       arr_delay       -12

此信息的参考来自这里

因子/类别数据

R 将类别变量称为因子,并且cut()函数使我们能够将连续的数值变量划分为范围,并将范围视为因子或类别变量,或者将类别变量分类为更大的桶。

使用cut()的 R 示例

这是 R 中的示例:

clinical.trial<- data.frame(patient = 1:1000,
age = rnorm(1000, mean = 50, sd = 5),
year.enroll = sample(paste("19", 80:99, sep = ""),
 1000, replace = TRUE))

>clinical.trial<- data.frame(patient = 1:1000,
+                              age = rnorm(1000, mean = 50, sd = 5),
+                              year.enroll = sample(paste("19", 80:99, sep = ""),
+                              1000, replace = TRUE))
>summary(clinical.trial)
patient            age         year.enroll
 Min.   :   1.0   Min.   :31.14   1995   : 61 
 1st Qu.: 250.8   1st Qu.:46.77   1989   : 60 
Median : 500.5   Median :50.14   1985   : 57 
 Mean   : 500.5   Mean   :50.14   1988   : 57 
 3rd Qu.: 750.2   3rd Qu.:53.50   1990   : 56 
 Max.   :1000.0   Max.   :70.15   1991   : 55 
 (Other):654 
>ctcut<- cut(clinical.trial$age, breaks = 5)> table(ctcut)
ctcut
(31.1,38.9] (38.9,46.7] (46.7,54.6] (54.6,62.4] (62.4,70.2]
 15         232         558         186           9

可以在这个位置找到上述数据的参考。

Pandas 解决方案

这等效于先前在 Pandas 中介绍的cut()函数(仅适用于 0.15+版本):

In [79]: pd.set_option('precision',4)
clinical_trial=pd.DataFrame({'patient':range(1,1001), 
 'age' : np.random.normal(50,5,size=1000),
 'year_enroll': [str(x) for x in np.random.choice(range(1980,2000),size=1000,replace=True)]})

In [80]: clinical_trial.describe()
Out[80]:        age       patient
count   1000.000  1000.000
mean    50.089    500.500
std     4.909     288.819
min     29.944    1.000
 25%     46.572    250.750
 50%     50.314    500.500
 75%     53.320    750.250
max     63.458    1000.000

In [81]: clinical_trial.describe(include=['O'])
Out[81]:        year_enroll
count   1000
unique  20
top     1992
freq    62

In [82]: clinical_trial.year_enroll.value_counts()[:6]
Out[82]: 1992    62
 1985    61
 1986    59
 1994    59
 1983    58
 1991    58
dtype: int64
In [83]: ctcut=pd.cut(clinical_trial['age'], 5)
In [84]: ctcut.head()
Out[84]: 0    (43.349, 50.052]
 1    (50.052, 56.755]
 2    (50.052, 56.755]
 3    (43.349, 50.052]
 4    (50.052, 56.755]
 Name: age, dtype: category
 Categories (5, object): [(29.91, 36.646] < (36.646, 43.349] < (43.349, 50.052] < (50.052, 56.755] < (56.755, 63.458]]

In [85]: ctcut.value_counts().sort_index()
Out[85]: (29.91, 36.646]       3
 (36.646, 43.349]     82
 (43.349, 50.052]    396
 (50.052, 56.755]    434
 (56.755, 63.458]     85
dtype: int64

总结

在本章中,我们试图将 R 中的关键特征与其等效的 Pandas 进行比较,以实现以下目标:

  • 帮助可能希望在 Pandas 中复制相同功能的 R 用户
  • 帮助阅读了一些 R 代码,并可能希望将其重写为 Pandas 代码的任何用户

在下一章中,我们将通过对scikit-learn库进行机器学习的简要介绍来结束本书,并展示 Pandas 如何适合该框架。 可在以下位置找到本章的参考文档