引言
每种编程语言里都有条件语句和循环语句,今天把R和python的放到一起打打架!没办法现在就是这么卷,学不了两个也得学一个吧~
如果x >0 就输出pos,否则就什么都不做
x <- 1
if (x > 0) {
print("pos")
}
## [1] "pos"
#只有一行代码也可以不写大括号
if (x > 0) print("pos")
## [1] "pos"
如果x >0 就输出pos,否则就输出neg
x <- 1
if (x > 0) {
print("pos")
} else {
print("neg")
}
## [1] "pos"
if语句是不支持直接向量化计算的,也就是说,小括号里的逻辑值只能是一个,不能是多个,否则报错。
y = c(3,5,-1,0)
if (y > 0) {
print("pos")
} else {
print("neg")
}
## Error in if (y > 0) {: the condition has length > 1
多不方便呐!
所以必须祭出两个神器:ifelse和case_when,可以支持向量化运算,一次搞定多个逻辑值没有问题。
y = c(3,5,-1,0)
ifelse(y>0,"pos","neg")
## [1] "pos" "pos" "neg" "neg"
如果有多个条件,可以使用dplyr
包中的case_when
。
library(dplyr)
case_when(
y > 0 ~ "pos",
y < 0 ~ "neg",
TRUE ~ "0"
)
## [1] "pos" "pos" "neg" "0"
case_when会从第一个条件开始判断,是T就输出相应的值,是F就再判断下一个条件。最后一行就是前面所有条件都不满足,剩下的所有情况对应的值。
for循环的本质就是代数,in后面的向量长度是几,代码就会执行几次,分别是代入z里面的每个值。
i是一个代称,代指z里面的每个元素,无需提前赋值,也可以换成别的单词,只需要注意内外统一即可。
z = 1:5
for (i in z) {
print(i)
}
## [1] 1
## [1] 2
## [1] 3
## [1] 4
## [1] 5
下面这个for循环里,大括号里的代码总共是执行了3次,第一次执行时,p就是tidyr,第二次执行时,p就是dplyr,第三次执行时,p就是stringr。
ps = c("tidyr","dplyr","stringr")
for (p in ps) {
print(p)
}
## [1] "tidyr"
## [1] "dplyr"
## [1] "stringr"
for循环有一个重要的应用就是批量装包!
本质上就是把ps里的每个包名代入大括号里的代码的p处,判断每个包是否能够成功加载,能成功加载就不安装,不能成功加载就安装。
for (p in ps){
if (! require(p,character.only=T,quietly = T)) {
install.packages(p,ask = F,update = F)
}
}
x = 1
if x > 0:
print("pos")
pos
x = 1
if x > 0:
print("pos")
else:
print("neg")
python的if语句也是不支持直接批量计算的,也就是说,小括号里的逻辑值只能是一个,不能是多个,否则报错。
import numpy as np
y = np.array([3, 5, -1, 0])
if (y > 0) :
print("pos")
else:
print("neg")
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
Cell In[4], line 3
1 import numpy as np
2 y = np.array([3, 5, -1, 0])
----> 3 if (y > 0) :
4 print("pos")
5 else:
ValueError: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Python中的`numpy`库提供了一个类似于R语言`ifelse`的函数`np.where`,支持数组运算,比在if语句外面套for循环都要简单一些。
import numpy as np
y = np.array([3, 5, -1, 0])
np.where(y > 0, "pos", "neg")
array(['pos', 'pos', 'neg', 'neg'], dtype='<U3')
如果是多个条件,那就使用pandas里的case_when方法
import pandas as pd
y = pd.Series([3,5,-1,0])
y.case_when([
(y > 0, "pos"),
(y < 0, "neg"),
(pd.Series(True), "0")
])
0 pos
1 pos
2 neg
3 0
dtype: object
z = range(1, 6) # range函数不包括结束值,所以返回5个值
for i in z:
print(i)
ps = ["tidyr", "dplyr", "stringr"]
for p in ps:
print(p)
1
2
3
4
5
tidyr
dplyr
stringr
列表推导式是Python中一个强大的功能,可以用更简洁的方式来创建列表。相比传统的for循环,列表推导式更加简洁和易读,可以把结果直接存为列表或者是字典。
numbers = [1, 2, 3, 4, 5]
[x**2 for x in numbers] # 计算平方
[1, 4, 9, 16, 25]
{x: x**2 for x in numbers}
{1: 1, 2: 4, 3: 9, 4: 16, 5: 25}
先把iris拆成3个文件,来做示例文件。
library(rio)
dat = split(iris,iris$Species)
sapply(1:3, function(i){
write.csv(dat[[i]],row.names = F,
file = paste0(names(dat)[i],".csv"))
})
## [[1]]
## NULL
##
## [[2]]
## NULL
##
## [[3]]
## NULL
在R语言中,我们可以用dir
函数获取目录下的所有文件名,然后用for
循环批量读取。
files <- dir(pattern = "\\.csv$") # 用正则表达式匹配以csv为结尾的文件
result = list()
for (i in 1:length(files)) {
result[[i]] <- read.csv(files[[i]])
}
re2 = do.call(rbind,result)
head(re2)
## Sepal.Length Sepal.Width Petal.Length Petal.Width Species
## 1 5.1 3.5 1.4 0.2 setosa
## 2 4.9 3.0 1.4 0.2 setosa
## 3 4.7 3.2 1.3 0.2 setosa
## 4 4.6 3.1 1.5 0.2 setosa
## 5 5.0 3.6 1.4 0.2 setosa
## 6 5.4 3.9 1.7 0.4 setosa
dim(re2)
## [1] 150 5
Python中,我们可以使用类似的方式来批量读取文件:
from glob import glob
import pandas as pd
# 用正则表达式匹配以csv为结尾的文件
files = glob("*.csv")
result = []
for i in range(len(files)):
result.append(pd.read_csv(files[i]))
re2 = pd.concat(result, ignore_index=True)
re2.head()
Sepal.Length Sepal.Width Petal.Length Petal.Width Species
0 5.1 3.5 1.4 0.2 setosa
1 4.9 3.0 1.4 0.2 setosa
2 4.7 3.2 1.3 0.2 setosa
3 4.6 3.1 1.5 0.2 setosa
4 5.0 3.6 1.4 0.2 setosa
好啦,今天的R语言与Python控制流大比拼就到这里了!光看不练啥也不是,赶紧打开你的RStudio或者Jupyter Notebook,咔咔敲代码吧~