R语言与pandas的爱恨情仇(注:摘抄)

具体内容可以上pandas下载PDF文档进行学习,本人在这里仅仅是摘抄它的内容。用于学习,无商业用途。请支持原创。(文档62页起)

一:一些函数的用法比较。

Querying,filtering,sampling,sorting,transforming,grouping,summarizing

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)
distanct(select(df,col1)) df[['col1']].drop_duplicates()
distance(select(df,col1,col2)) df[['col1','col2']].drop_duplicates()
sample_n(df,10) df.sample(n=10)
sample_frac(df,0.01) df.sample(frc=0.01)
arrange(df,col1,col2) df.sort_values(['col1','col2'])
arrange(df,desc(col1)) df.sort_values('col1',ascending=False)
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'])
summary(df) df.describe()
gdf<-group_by(df,col1) gdf = df.groupby('col1')
summarise(gdf,avg=mean(col,na.rm=TRUE)) df.groupby('col1').agg({'col1':'mean'})
summarise(gdf) df.groupby('col1').sum()

二:基本的R

R语言的一些语句是这样的:

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的表达是这样的:

import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randn(10, 3), columns=list("abc"))
df[["a","b"]]
df.loc[:,["a","c"]]

通过整数位置选择多个非连续列可以通过iloc索引属性 和 numpy.r _ 的组合来实现。

named = list("abcdefg")
n = 30
columns = named + np.arange(len(named),n).tolist()
df = pd.DataFrame(np.random.randn(n,n),columns = columns)
df.head()
df.iloc[:, np.r_[:10, 24:30]]

np.r_的使用方法要注意一下子。

R 中,你可能想把数据分割成子集,并计算每个子集的平均值。使用一个名为 df data.frame并将它分成 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)

在pandas中我们可以使用groupby()函数来类似与R中的aggregate函数。

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],
    }
)
g = df.groupby(["by1","by2"])
g[["v1","v2"]].mean()

R 中选择数据的一种常见方法是使用%in% ,这是使用函数匹配定义的。%in% 中的运算符 用于返回一个逻辑向量,指示是否有匹配项:例如:

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

pandas中使用isin()来代替%in%,式例如下:

s = pd.Series(np.arange(5),dtype=np.float32)
s.isin([2,4])

Match 函数返回第二个参数中第一个参数的匹配位置向量

tapply 类似于aggregate,但数据可能是不规则的数组,因为子类大小可能是不规则的。使用一个叫棒球的数据框架,根据数组小组检索信息。

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()方法来处理它:

import random
import string
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),
}
)
baseball.pivot_table(values="batting avg",columns = "team", aggfunc = np.max)

更多的一些信息:

import datetime
df = pd.DataFrame(
{
    "A":["one","one","two","three"] * 6,
    "B":["A","B","C"]*8,
    "C":["foo","foo","foo","bar","bar","bar"] * 4,
    "D":np.random.randn(24),
    "E":np.random.randn(24),
    "F":[datetime.datetime(2013,i,1) for i in range(1,13)]+
     [datetime.datetime(2013,i,15) for i in range(1, 13)],
}
)
pd.pivot_table(df,values = "D", index = ["A","B"],columns = ["C"])
pd.pivot_table(df,index=["A","B"], columns = ["C"])

query ()方法类似于基 R 子集函数。在 R 中,你可能想要得到一个 data.frameas 的行,其中一列的值小于另一列的值,R的表达方式为:

df <- data.frame(a=rnoorm(10),b=rnorm(10))
subset(df,a<= b)
df[df$a <= df$b,]

在pandas中有几种方法可以执行子设置,你能够使用query()或者传递一个表达式,就好像它是一个索引/片段以及标准的布尔索引,其代码表达式为:

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

在 r 中使用一个名为 dfdata.frame 表达式,其中包含列 a 和列 b,可以使用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()函数的方法,代码表达式为:

df = pd.DataFrame({"a":np.random.randn(10),"b":np.random.randn(10)})
df.eval("a+b")

在某些情况下 eval ()会比纯 python 中的计算快得多。更多细节和例子请参见 eval 文档。

plyr 是一个用于数据分析的split-apply-combine策略的 R库。函数围绕 R 中的三个数据结构运行,a 用于数组,l 用于列表,d 用于 data.frame。下面的表格显示了这些数据结构是如何用 python 映射的:

R python
array list
lists dictionary or list of objects
data.frame dataframe

R中使用一个名为 dfdata.frame 表达式,在这里你需要按月汇总 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()的方法,如下:

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),
}
)
grouped = df.groupby(["month","week"])
grouped["x"].agg([np.mean,np.std])

R使用一个三维数组的表达式把它融合成一个 data.frame.

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

在python中,因为a是一个表格,所以我们可以使用表格的表达式。

a = np.array(list(range(1,24))+[np.NAN]).reshape(2,3,4)
pd.DataFrame([tuple(list(x)+[val]) for x, val in np.ndenumerate(a)])

R中融合表格方法:

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

pandas中的方法为:

a = list(enumerate(list(range(1,5))+ [np.NAN]))
pd.DataFrame(a)

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"))

pandas中的方法为:

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

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"))

pandas中的方法为:

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

R中方法(cast):

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()

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,
}
)
mdf = pd.melt(df,id_vars=["month","week"])
pd.pivot_table(
	mdf,
  values = "value",
  index = ["variable","week"],
  columns = ["month"],
  aggfunc = np.mean,
)

R中方法:

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().

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],
}
)
df.pivot_table(values="Amount", index="Animal", columns="FeedType", aggfunc="sum")

方法二:

df.groupby(["Animal", "FeedType"])["Amount"].sum()

pandas有分类数据的数据类型,例如,在R中是这样的:

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

而在pandas中是这样的:

pd.cut(pd.Series([1, 2, 3, 4, 5, 6]), 3)
pd.Series([1, 2, 3, 2, 2, 3]).astype("category")