R / Rライブラリとの比較#
pandasは、人々がRで使用しているデータ操作と分析機能の多くを提供することを目指しているため、このページは、pandasとの関連で、R言語とその多くのサードパーティライブラリをより詳細に比較するために作成されました。RおよびCRANライブラリとの比較では、次の点を重視します。
機能/柔軟性:各ツールで何ができて何ができないか
パフォーマンス:操作の速度。具体的な数値/ベンチマークが望ましい
使いやすさ:一方のツールが使いやすいか/使いにくいか(並べてコードを比較することで判断する必要があるかもしれません)
このページは、これらのRパッケージのユーザーのための翻訳ガイドも提供しています。
クイックリファレンス#
dplyrを使用した一般的なR操作とpandasの同等の操作を組み合わせたクイックリファレンスガイドから始めます。
クエリ、フィルタリング、サンプリング#
R |
pandas |
---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
ソート#
R |
pandas |
---|---|
|
|
|
|
変換#
R |
pandas |
---|---|
|
|
|
|
|
|
グループ化と集計#
R |
pandas |
---|---|
|
|
|
|
|
|
|
|
基本R#
Rの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 ... 27 28 29
0 -1.344312 0.844885 1.075770 ... 0.813850 0.132003 -0.827317
1 -0.076467 -1.187678 1.130127 ... 0.149748 -0.732339 0.687738
2 0.176444 0.403310 -0.154951 ... -0.493662 0.600178 0.274230
3 0.132885 -0.023688 2.410179 ... 0.109121 1.126203 -0.977349
4 1.474071 -0.064034 -1.282782 ... -0.858447 0.306996 -0.028665
.. ... ... ... ... ... ... ...
25 1.492125 -0.068190 0.681456 ... 0.428572 0.880609 0.487645
26 0.725238 0.624607 -0.141185 ... 1.008500 1.424017 0.717110
27 1.262419 1.950057 0.301038 ... 1.007824 2.826008 1.458383
28 -1.585746 -0.899734 0.921494 ... 0.577223 -1.088417 0.326687
29 -0.986248 0.169729 -1.158091 ... -2.013086 -1.602549 0.333109
[30 rows x 16 columns]
aggregate
#
Rでは、データをサブセットに分割し、それぞれについて平均値を計算したい場合があります。df
というdata.frameを使用して、by1
とby2
のグループに分割します
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
詳細と例については、groupbyのドキュメントを参照してください。
match
/ %in%
#
Rでデータを選択する一般的な方法は、match
関数を使用して定義された%in%
を使用することです。%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
関数は、最初の引数が2番目の引数に一致する位置のベクトルを返します
s <- 0:4
match(s, c(2,4))
詳細と例については、reshapingのドキュメントを参照してください。
tapply
#
tapply
はaggregate
に似ていますが、サブクラスのサイズが不規則である可能性があるため、データは不規則な配列にすることができます。baseball
というdata.frameを使用し、配列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="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
詳細と例については、reshapingのドキュメントを参照してください。
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
詳細と例については、queryのドキュメントを参照してください。
with
#
Rでa
列とb
列を持つdf
というdata.frameを使用する式は、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での評価よりもはるかに高速になります。詳細と例については、evalのドキュメントを参照してください。
plyr#
plyr
は、データ分析のための分割-適用-結合戦略を実現するRライブラリです。関数は、Rの3つのデータ構造、a
(arrays
:配列)、l
(lists
:リスト)、d
(data.frame
:データフレーム)を中心に展開します。以下の表は、これらのデータ構造がPythonでどのように対応付けられるかを示しています。
R |
Python |
---|---|
配列 |
リスト |
リスト |
辞書またはオブジェクトのリスト |
data.frame |
データフレーム |
ddply#
Rにおいて、df
というデータフレームを使用して、month
(月)ごとにx
を要約したい場合の式
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(["mean", "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
詳細と例については、groupbyのドキュメントを参照してください。
reshape / reshape2#
meltarray#
Rにおいて、a
という3次元配列をデータフレームに変換したい場合の式
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]
meltlist#
Rにおいて、a
というリストをデータフレームに変換したい場合の式
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
詳細と例については、データ構造入門のドキュメントを参照してください。
meltdf#
Rにおいて、cheese
というデータフレームの形状を変更したい場合の式
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(future_stack=True) # alternative way
Out[34]:
first last
John Doe height 5.5
weight 130.0
Mary Bo height 6.0
weight 150.0
dtype: float64
詳細と例については、形状変更のドキュメントを参照してください。
cast#
Rでは、acast
は、df
というデータフレームを使用して、より高次元の配列にキャストする式です。
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="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
同様に、Rでdf
というデータフレームを使用して、Animal
とFeedType
に基づいて情報を集計するdcast
についても同様です。
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では、これに対して2つの異なるアプローチがあります。1つ目は、上記と同様に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
2つ目のアプローチは、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
詳細と例については、形状変更のドキュメントまたはgroupbyのドキュメントを参照してください。
factor
#
pandasには、カテゴリデータ用のデータ型があります。
cut(c(1,2,3,4,5,6), 3)
factor(c(1,2,3,2,2,3))
pandasでは、これはpd.cut
とastype("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]
詳細と例については、カテゴリデータ入門とAPIドキュメントを参照してください。Rのfactorとの違いに関するドキュメントもあります。