与R/R库的比较#

由于Pandas的目标是提供人们使用的大量数据操作和分析功能 R ,这一页是为了更详细地了解 R language 以及它的许多第三方类库,因为它们与Pandas有关。与R和CRAN库相比,我们关心以下几点:

  • Functionality / flexibility :每个工具能做什么,不能做什么

  • 性能 :运营有多快。最好是硬数字/基准

  • Ease-of-use :是一种更容易使用的工具还是更难使用的工具(考虑到代码的并排比较,您可能不得不对此进行判断)

这个页面也为这些R包的用户提供了一点翻译指南。

适用于转让 DataFrame 从Pandas到R的对象,一种选择是使用HDF5文件,请参见 外部兼容性 举个例子。

快速参考#

我们将从快速参考指南开始,将一些常见的R操作与 dplyr 与大Pandas的同类。

查询、过滤、采样#

R

Pandas

dim(df)

df.shape

head(df)

df.head()

slice(df, 1:10)

df.iloc[:9]

filter(df, col1 == 1, col2 == 1)

df.query('col1 == 1 & col2 == 1')

df[df$col1 == 1 & df$col2 == 1,]

df[(df.col1 == 1) & (df.col2 == 1)]

select(df, col1, col2)

df[['col1', 'col2']]

select(df, col1:col3)

df.loc[:, 'col1':'col3']

select(df, -(col1:col3))

df.drop(cols_to_drop, axis=1) 但是你看 1

distinct(select(df, col1))

df[['col1']].drop_duplicates()

distinct(select(df, col1, col2))

df[['col1', 'col2']].drop_duplicates()

sample_n(df, 10)

df.sample(n=10)

sample_frac(df, 0.01)

df.sample(frac=0.01)

1

R是列子范围的缩写 (select(df, col1:col3) )可以在Pandas中干净利落地接近,例如,如果您有列的列表 df[cols[1:3]]df.drop(cols[1:3]) ,但按列名执行此操作有点麻烦。

分选#

R

Pandas

arrange(df, col1, col2)

df.sort_values(['col1', 'col2'])

arrange(df, desc(col1))

df.sort_values('col1', ascending=False)

转型#

R

Pandas

select(df, col_one = col1)

df.rename(columns={'col1': 'col_one'})['col_one']

rename(df, col_one = col1)

df.rename(columns={'col1': 'col_one'})

mutate(df, c=a-b)

df.assign(c=df['a']-df['b'])

分组和汇总#

R

Pandas

summary(df)

df.describe()

gdf <- group_by(df, col1)

gdf = df.groupby('col1')

summarise(gdf, avg=mean(col1, na.rm=TRUE))

df.groupby('col1').agg({'col1': 'mean'})

summarise(gdf, total=sum(col1))

df.groupby('col1').sum()

底座R#

用R‘s切片 c#

R使其更易于访问 data.frame 按名称列出的列

df <- data.frame(a=rnorm(5), b=rnorm(5), c=rnorm(5), d=rnorm(5), e=rnorm(5))
df[, c("a", "c", "e")]

或按整数位置

df <- data.frame(matrix(rnorm(1000), ncol=100))
df[, c(1:10, 25:30, 40, 50:100)]

在Pandas中按名称选择多个列非常简单

In [1]: df = pd.DataFrame(np.random.randn(10, 3), columns=list("abc"))

In [2]: df[["a", "c"]]
Out[2]: 
          a         c
0  0.469112 -1.509059
1 -1.135632 -0.173215
2  0.119209 -0.861849
3 -2.104569  1.071804
4  0.721555 -1.039575
5  0.271860  0.567020
6  0.276232 -0.673690
7  0.113648  0.524988
8  0.404705 -1.715002
9 -1.039268 -1.157892

In [3]: df.loc[:, ["a", "c"]]
Out[3]: 
          a         c
0  0.469112 -1.509059
1 -1.135632 -0.173215
2  0.119209 -0.861849
3 -2.104569  1.071804
4  0.721555 -1.039575
5  0.271860  0.567020
6  0.276232 -0.673690
7  0.113648  0.524988
8  0.404705 -1.715002
9 -1.039268 -1.157892

按整数位置选择多个不连续的列可以通过组合 iloc 索引器属性和 numpy.r_

In [4]: named = list("abcdefg")

In [5]: n = 30

In [6]: columns = named + np.arange(len(named), n).tolist()

In [7]: df = pd.DataFrame(np.random.randn(n, n), columns=columns)

In [8]: df.iloc[:, np.r_[:10, 24:30]]
Out[8]: 
           a         b         c         d         e         f         g         7         8         9        24        25        26        27        28        29
0  -1.344312  0.844885  1.075770 -0.109050  1.643563 -1.469388  0.357021 -0.674600 -1.776904 -0.968914 -1.170299 -0.226169  0.410835  0.813850  0.132003 -0.827317
1  -0.076467 -1.187678  1.130127 -1.436737 -1.413681  1.607920  1.024180  0.569605  0.875906 -2.211372  0.959726 -1.110336 -0.619976  0.149748 -0.732339  0.687738
2   0.176444  0.403310 -0.154951  0.301624 -2.179861 -1.369849 -0.954208  1.462696 -1.743161 -0.826591  0.084844  0.432390  1.519970 -0.493662  0.600178  0.274230
3   0.132885 -0.023688  2.410179  1.450520  0.206053 -0.251905 -2.213588  1.063327  1.266143  0.299368 -2.484478 -0.281461  0.030711  0.109121  1.126203 -0.977349
4   1.474071 -0.064034 -1.282782  0.781836 -1.071357  0.441153  2.353925  0.583787  0.221471 -0.744471 -1.197071 -1.066969 -0.303421 -0.858447  0.306996 -0.028665
..       ...       ...       ...       ...       ...       ...       ...       ...       ...       ...       ...       ...       ...       ...       ...       ...
25  1.492125 -0.068190  0.681456  1.221829 -0.434352  1.204815 -0.195612  1.251683 -1.040389 -0.796211  1.944517  0.042344 -0.307904  0.428572  0.880609  0.487645
26  0.725238  0.624607 -0.141185 -0.143948 -0.328162  2.095086 -0.608888 -0.926422  1.872601 -2.513465 -0.846188  1.190624  0.778507  1.008500  1.424017  0.717110
27  1.262419  1.950057  0.301038 -0.933858  0.814946  0.181439 -0.110015 -2.364638 -1.584814  0.307941 -1.341814  0.334281 -0.162227  1.007824  2.826008  1.458383
28 -1.585746 -0.899734  0.921494 -0.211762 -0.059182  0.058308  0.915377 -0.696321  0.150664 -3.060395  0.403620 -0.026602 -0.240481  0.577223 -1.088417  0.326687
29 -0.986248  0.169729 -1.158091  1.019673  0.646039  0.917399 -0.010435  0.366366  0.922729  0.869610 -1.209247 -0.671466  0.332872 -2.013086 -1.602549  0.333109

[30 rows x 16 columns]

aggregate#

在R中,您可能希望将数据拆分成多个子集并计算每个子集的平均值。使用名为 df 然后把它分成几组 by1by2

df <- data.frame(
  v1 = c(1,3,5,7,8,3,5,NA,4,5,7,9),
  v2 = c(11,33,55,77,88,33,55,NA,44,55,77,99),
  by1 = c("red", "blue", 1, 2, NA, "big", 1, 2, "red", 1, NA, 12),
  by2 = c("wet", "dry", 99, 95, NA, "damp", 95, 99, "red", 99, NA, NA))
aggregate(x=df[, c("v1", "v2")], by=list(mydf2$by1, mydf2$by2), FUN = mean)

这个 groupby() 方法类似于基数R aggregate 功能。

In [9]: df = pd.DataFrame(
   ...:     {
   ...:         "v1": [1, 3, 5, 7, 8, 3, 5, np.nan, 4, 5, 7, 9],
   ...:         "v2": [11, 33, 55, 77, 88, 33, 55, np.nan, 44, 55, 77, 99],
   ...:         "by1": ["red", "blue", 1, 2, np.nan, "big", 1, 2, "red", 1, np.nan, 12],
   ...:         "by2": [
   ...:             "wet",
   ...:             "dry",
   ...:             99,
   ...:             95,
   ...:             np.nan,
   ...:             "damp",
   ...:             95,
   ...:             99,
   ...:             "red",
   ...:             99,
   ...:             np.nan,
   ...:             np.nan,
   ...:         ],
   ...:     }
   ...: )
   ...: 

In [10]: g = df.groupby(["by1", "by2"])

In [11]: g[["v1", "v2"]].mean()
Out[11]: 
            v1    v2
by1  by2            
1    95    5.0  55.0
     99    5.0  55.0
2    95    7.0  77.0
     99    NaN   NaN
big  damp  3.0  33.0
blue dry   3.0  33.0
red  red   4.0  44.0
     wet   1.0  11.0

有关更多详细信息和示例,请参阅 the groupby documentation

match / %in%#

在R中选择数据的一种常见方法是使用 %in% 它是使用函数定义的 match 。操作员 %in% 用于返回指示是否匹配的逻辑向量:

s <- 0:4
s %in% c(2,4)

这个 isin() 方法类似于R %in% 操作员:

In [12]: s = pd.Series(np.arange(5), dtype=np.float32)

In [13]: s.isin([2, 4])
Out[13]: 
0    False
1    False
2     True
3    False
4     True
dtype: bool

这个 match 函数返回其第二个参数中第一个参数匹配位置的向量:

s <- 0:4
match(s, c(2,4))

有关更多详细信息和示例,请参阅 the reshaping documentation

tapply#

tapply 类似于 aggregate ,但数据可能在一个参差不齐的数组中,因为子类大小可能是不规则的。使用名为 baseball ,以及基于该数组检索信息 team

baseball <-
  data.frame(team = gl(5, 5,
             labels = paste("Team", LETTERS[1:5])),
             player = sample(letters, 25),
             batting.average = runif(25, .200, .400))

tapply(baseball$batting.average, baseball.example$team,
       max)

在Pandas身上,我们可能会使用 pivot_table() 方法来处理此问题:

In [14]: import random

In [15]: import string

In [16]: baseball = pd.DataFrame(
   ....:     {
   ....:         "team": ["team %d" % (x + 1) for x in range(5)] * 5,
   ....:         "player": random.sample(list(string.ascii_lowercase), 25),
   ....:         "batting avg": np.random.uniform(0.200, 0.400, 25),
   ....:     }
   ....: )
   ....: 

In [17]: baseball.pivot_table(values="batting avg", columns="team", aggfunc=np.max)
Out[17]: 
team           team 1    team 2    team 3    team 4    team 5
batting avg  0.352134  0.295327  0.397191  0.394457  0.396194

有关更多详细信息和示例,请参阅 the reshaping documentation

subset#

这个 query() 方法类似于基数R subset 功能。在R中,您可能想要获取 data.frame 其中一列的值小于另一列的值:

df <- data.frame(a=rnorm(10), b=rnorm(10))
subset(df, a <= b)
df[df$a <= df$b,]  # note the comma

在大Pandas身上,有几种方法可以进行字幕定位。您可以使用 query() 或者传递一个表达式,就像它是一个索引/切片以及标准布尔索引一样:

In [18]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)})

In [19]: df.query("a <= b")
Out[19]: 
          a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

In [20]: df[df["a"] <= df["b"]]
Out[20]: 
          a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

In [21]: df.loc[df["a"] <= df["b"]]
Out[21]: 
          a         b
1  0.174950  0.552887
2 -0.023167  0.148084
3 -0.495291 -0.300218
4 -0.860736  0.197378
5 -1.134146  1.720780
7 -0.290098  0.083515
8  0.238636  0.946550

有关更多详细信息和示例,请参阅 the query documentation

with#

使用名为的data.Frame的表达式 df 在R中加上柱子 ab 将使用以下方法进行评估 with 如下所示:

df <- data.frame(a=rnorm(10), b=rnorm(10))
with(df, a + b)
df$a + df$b  # same as the previous expression

在Pandas中,等效的表达式使用 eval() 方法,应该是:

In [22]: df = pd.DataFrame({"a": np.random.randn(10), "b": np.random.randn(10)})

In [23]: df.eval("a + b")
Out[23]: 
0   -0.091430
1   -2.483890
2   -0.252728
3   -0.626444
4   -0.261740
5    2.149503
6   -0.332214
7    0.799331
8   -2.377245
9    2.104677
dtype: float64

In [24]: df["a"] + df["b"]  # same as the previous expression
Out[24]: 
0   -0.091430
1   -2.483890
2   -0.252728
3   -0.626444
4   -0.261740
5    2.149503
6   -0.332214
7    0.799331
8   -2.377245
9    2.104677
dtype: float64

在某些情况下 eval() 将比纯Python中的求值速度快得多。有关更多详细信息和示例,请参阅 the eval documentation

多层#

plyr 是一个R库,用于数据分析的拆分-应用-组合策略。函数围绕R中的三个数据结构, aarraysllists ,以及 ddata.frame 。下表显示了如何在Python中映射这些数据结构。

R

Python

阵列

列表

列表

词典或对象列表

data.frame

数据帧

傻乎乎的#

使用名为的data.Frame的表达式 df 在R中,您想要总结 x 通过 month

require(plyr)
df <- data.frame(
  x = runif(120, 1, 168),
  y = runif(120, 7, 334),
  z = runif(120, 1.7, 20.7),
  month = rep(c(5,6,7,8),30),
  week = sample(1:4, 120, TRUE)
)

ddply(df, .(month, week), summarize,
      mean = round(mean(x), 2),
      sd = round(sd(x), 2))

在Pandas中,等效的表达式使用 groupby() 方法,应该是:

In [25]: df = pd.DataFrame(
   ....:     {
   ....:         "x": np.random.uniform(1.0, 168.0, 120),
   ....:         "y": np.random.uniform(7.0, 334.0, 120),
   ....:         "z": np.random.uniform(1.7, 20.7, 120),
   ....:         "month": [5, 6, 7, 8] * 30,
   ....:         "week": np.random.randint(1, 4, 120),
   ....:     }
   ....: )
   ....: 

In [26]: grouped = df.groupby(["month", "week"])

In [27]: grouped["x"].agg([np.mean, np.std])
Out[27]: 
                  mean        std
month week                       
5     1      63.653367  40.601965
      2      78.126605  53.342400
      3      92.091886  57.630110
6     1      81.747070  54.339218
      2      70.971205  54.687287
      3     100.968344  54.010081
7     1      61.576332  38.844274
      2      61.733510  48.209013
      3      71.688795  37.595638
8     1      62.741922  34.618153
      2      91.774627  49.790202
      3      73.936856  60.773900

有关更多详细信息和示例,请参阅 the groupby documentation

重塑/重塑2#

梅尔塔雷#

使用名为的三维数组的表达式 a 在R中,您想要将其融化到数据中。帧:

a <- array(c(1:23, NA), c(2,3,4))
data.frame(melt(a))

在Python中,因为 a 是一个列表,你可以简单地使用列表理解。

In [28]: a = np.array(list(range(1, 24)) + [np.NAN]).reshape(2, 3, 4)

In [29]: pd.DataFrame([tuple(list(x) + [val]) for x, val in np.ndenumerate(a)])
Out[29]: 
    0  1  2     3
0   0  0  0   1.0
1   0  0  1   2.0
2   0  0  2   3.0
3   0  0  3   4.0
4   0  1  0   5.0
.. .. .. ..   ...
19  1  1  3  20.0
20  1  2  0  21.0
21  1  2  1  22.0
22  1  2  2  23.0
23  1  2  3   NaN

[24 rows x 4 columns]

熔化列表#

使用名为的列表的表达式 a 在R中,您想要将其融化到数据中。帧:

a <- as.list(c(1:4, NA))
data.frame(melt(a))

在Python中,此列表将是一个元组列表,因此 DataFrame() 方法会根据需要将其转换为数据帧。

In [30]: a = list(enumerate(list(range(1, 5)) + [np.NAN]))

In [31]: pd.DataFrame(a)
Out[31]: 
   0    1
0  0  1.0
1  1  2.0
2  2  3.0
3  3  4.0
4  4  NaN

有关更多详细信息和示例,请参阅 the Into to Data Structures documentation

熔融#

使用名为的data.Frame的表达式 cheese 在R中,您要重塑数据。帧:

cheese <- data.frame(
  first = c('John', 'Mary'),
  last = c('Doe', 'Bo'),
  height = c(5.5, 6.0),
  weight = c(130, 150)
)
melt(cheese, id=c("first", "last"))

在Python语言中, melt() 方法是R等效项:

In [32]: cheese = pd.DataFrame(
   ....:     {
   ....:         "first": ["John", "Mary"],
   ....:         "last": ["Doe", "Bo"],
   ....:         "height": [5.5, 6.0],
   ....:         "weight": [130, 150],
   ....:     }
   ....: )
   ....: 

In [33]: pd.melt(cheese, id_vars=["first", "last"])
Out[33]: 
  first last variable  value
0  John  Doe   height    5.5
1  Mary   Bo   height    6.0
2  John  Doe   weight  130.0
3  Mary   Bo   weight  150.0

In [34]: cheese.set_index(["first", "last"]).stack()  # alternative way
Out[34]: 
first  last        
John   Doe   height      5.5
             weight    130.0
Mary   Bo    height      6.0
             weight    150.0
dtype: float64

有关更多详细信息和示例,请参阅 the reshaping documentation

演员阵容#

在R中 acast 是使用名为data.Frame的表达式 df 在R中转换为更高维数组:

df <- data.frame(
  x = runif(12, 1, 168),
  y = runif(12, 7, 334),
  z = runif(12, 1.7, 20.7),
  month = rep(c(5,6,7),4),
  week = rep(c(1,2), 6)
)

mdf <- melt(df, id=c("month", "week"))
acast(mdf, week ~ month ~ variable, mean)

在Python中,最好的方法是利用 pivot_table()

In [35]: df = pd.DataFrame(
   ....:     {
   ....:         "x": np.random.uniform(1.0, 168.0, 12),
   ....:         "y": np.random.uniform(7.0, 334.0, 12),
   ....:         "z": np.random.uniform(1.7, 20.7, 12),
   ....:         "month": [5, 6, 7] * 4,
   ....:         "week": [1, 2] * 6,
   ....:     }
   ....: )
   ....: 

In [36]: mdf = pd.melt(df, id_vars=["month", "week"])

In [37]: pd.pivot_table(
   ....:     mdf,
   ....:     values="value",
   ....:     index=["variable", "week"],
   ....:     columns=["month"],
   ....:     aggfunc=np.mean,
   ....: )
   ....: 
Out[37]: 
month                  5           6           7
variable week                                   
x        1     93.888747   98.762034   55.219673
         2     94.391427   38.112932   83.942781
y        1     94.306912  279.454811  227.840449
         2     87.392662  193.028166  173.899260
z        1     11.016009   10.079307   16.170549
         2      8.476111   17.638509   19.003494

同样,对于 dcast 它使用一个名为 df 在R中,根据以下条件聚合信息 AnimalFeedType

df <- data.frame(
  Animal = c('Animal1', 'Animal2', 'Animal3', 'Animal2', 'Animal1',
             'Animal2', 'Animal3'),
  FeedType = c('A', 'B', 'A', 'A', 'B', 'B', 'A'),
  Amount = c(10, 7, 4, 2, 5, 6, 2)
)

dcast(df, Animal ~ FeedType, sum, fill=NaN)
# Alternative method using base R
with(df, tapply(Amount, list(Animal, FeedType), sum))

Python可以通过两种不同的方式来实现这一点。首先,与上面类似,使用 pivot_table()

In [38]: df = pd.DataFrame(
   ....:     {
   ....:         "Animal": [
   ....:             "Animal1",
   ....:             "Animal2",
   ....:             "Animal3",
   ....:             "Animal2",
   ....:             "Animal1",
   ....:             "Animal2",
   ....:             "Animal3",
   ....:         ],
   ....:         "FeedType": ["A", "B", "A", "A", "B", "B", "A"],
   ....:         "Amount": [10, 7, 4, 2, 5, 6, 2],
   ....:     }
   ....: )
   ....: 

In [39]: df.pivot_table(values="Amount", index="Animal", columns="FeedType", aggfunc="sum")
Out[39]: 
FeedType     A     B
Animal              
Animal1   10.0   5.0
Animal2    2.0  13.0
Animal3    6.0   NaN

第二种方法是使用 groupby() 方法:

In [40]: df.groupby(["Animal", "FeedType"])["Amount"].sum()
Out[40]: 
Animal   FeedType
Animal1  A           10
         B            5
Animal2  A            2
         B           13
Animal3  A            6
Name: Amount, dtype: int64

有关更多详细信息和示例,请参阅 the reshaping documentationthe groupby documentation

factor#

Pandas有一种分类数据的数据类型。

cut(c(1,2,3,4,5,6), 3)
factor(c(1,2,3,2,2,3))

在Pandas身上,这是通过 pd.cutastype("category")

In [41]: pd.cut(pd.Series([1, 2, 3, 4, 5, 6]), 3)
Out[41]: 
0    (0.995, 2.667]
1    (0.995, 2.667]
2    (2.667, 4.333]
3    (2.667, 4.333]
4      (4.333, 6.0]
5      (4.333, 6.0]
dtype: category
Categories (3, interval[float64, right]): [(0.995, 2.667] < (2.667, 4.333] < (4.333, 6.0]]

In [42]: pd.Series([1, 2, 3, 2, 2, 3]).astype("category")
Out[42]: 
0    1
1    2
2    3
3    2
4    2
5    3
dtype: category
Categories (3, int64): [1, 2, 3]

有关更多详细信息和示例,请参阅 categorical introduction 以及 API documentation 。此外,还有一份关于 differences to R's factor