如何根据名称而不是索引选择一系列列和行来切片数据框?
How to slice a dataframe by selecting a range of columns and rows based on names and not indexes?
这是我提出的问题 的后续问题。在那里我学会了 a) 如何对列执行此操作(见下文)和 b) 行和列的 selection 在 R 中的处理方式似乎完全不同,这意味着我不能对行使用相同的方法。
所以假设我有一个这样的 pandas 数据框:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(10, size=(6, 6)),
columns=['c' + str(i) for i in range(6)],
index=["r" + str(i) for i in range(6)])
c0 c1 c2 c3 c4 c5
r0 4 2 3 9 9 0
r1 9 0 8 1 7 5
r2 2 6 7 5 4 7
r3 6 9 9 1 3 4
r4 1 1 1 3 0 3
r5 0 8 5 8 2 9
然后我可以很容易地 select 行和列的名称,如下所示:
print df.loc['r3':'r5', 'c1':'c4']
哪个returns
c1 c2 c3 c4
r3 9 9 1 3
r4 1 1 3 0
r5 8 5 8 2
我如何在 R 中执行此操作?给定这样的数据框
df <- data.frame(c1=1:6, c2=2:7, c3=3:8, c4=4:9, c5=5:10, c6=6:11)
rownames(df) <- c('r1', 'r2', 'r3', 'r4', 'r5', 'r6')
c1 c2 c3 c4 c5 c6
r1 1 2 3 4 5 6
r2 2 3 4 5 6 7
r3 3 4 5 6 7 8
r4 4 5 6 7 8 9
r5 5 6 7 8 9 10
r6 6 7 8 9 10 11
显然,如果我知道我想要的 rows/columns 的索引,我可以简单地做:
df[3:5, 1:4]
但我可能会在整个分析过程中删除 rows/columns,这样我宁愿按名称而不是按索引 select。从上面的 link 中,我了解到对于列,以下内容将起作用:
subset(df, select=c1:c4)
哪个returns
c1 c2 c3 c4
r1 1 2 3 4
r2 2 3 4 5
r3 3 4 5 6
r4 4 5 6 7
r5 5 6 7 8
r6 6 7 8 9
但我怎么能同时 select 一系列按名称排列的行呢?
在这种特殊情况下,我当然可以使用 grep
但是具有任意名称的列呢?
而且我不想使用
df[c('r3', 'r4' 'r5'), c('c1','c2', 'c3', 'c4')]
但实际切片。
您可以将 which()
与 rownames
一起使用:
subset(df[which(rownames(df)=='r3'):which(rownames(df)=='r5'),], select=c1:c4)
c1 c2 c3 c4
r3 3 4 5 6
r4 4 5 6 7
r5 5 6 7 8
使用match
查找特定行名称的位置。
df[match("r3", rownames(df)):match("r5", rownames(df)), match("c1", colnames(df)):match("c4", colnames(df))]
c1 c2 c3 c4
r3 3 4 5 6
r4 4 5 6 7
r5 5 6 7 8
您可以编写一个函数来提供相同的行为
'%:%' <- function(object, range) {
FUN <- if (!is.null(dim(object))) {
if (is.matrix(object)) colnames else names
} else identity
wh <- if (is.numeric(range)) range else which(FUN(object) %in% range)
FUN(object)[seq(wh[1], wh[2])]
}
df <- data.frame(c1=1:6, c2=2:7, c3=3:8, c4=4:9, c5=5:10, c6=6:11)
rownames(df) <- c('r1', 'r2', 'r3', 'r4', 'r5', 'r6')
像这样使用
df %:% c('c2', 'c4')
# [1] "c2" "c3" "c4"
rownames(df) %:% c('r2', 'r4')
# [1] "r2" "r3" "r4"
针对您的问题
df[rownames(df) %:% c('r3', 'r5'), df %:% c('c1', 'c5')]
# c1 c2 c3 c4 c5
# r3 3 4 5 6 7
# r4 4 5 6 7 8
# r5 5 6 7 8 9
这是我提出的问题
所以假设我有一个这样的 pandas 数据框:
import pandas as pd
import numpy as np
df = pd.DataFrame(np.random.randint(10, size=(6, 6)),
columns=['c' + str(i) for i in range(6)],
index=["r" + str(i) for i in range(6)])
c0 c1 c2 c3 c4 c5
r0 4 2 3 9 9 0
r1 9 0 8 1 7 5
r2 2 6 7 5 4 7
r3 6 9 9 1 3 4
r4 1 1 1 3 0 3
r5 0 8 5 8 2 9
然后我可以很容易地 select 行和列的名称,如下所示:
print df.loc['r3':'r5', 'c1':'c4']
哪个returns
c1 c2 c3 c4
r3 9 9 1 3
r4 1 1 3 0
r5 8 5 8 2
我如何在 R 中执行此操作?给定这样的数据框
df <- data.frame(c1=1:6, c2=2:7, c3=3:8, c4=4:9, c5=5:10, c6=6:11)
rownames(df) <- c('r1', 'r2', 'r3', 'r4', 'r5', 'r6')
c1 c2 c3 c4 c5 c6
r1 1 2 3 4 5 6
r2 2 3 4 5 6 7
r3 3 4 5 6 7 8
r4 4 5 6 7 8 9
r5 5 6 7 8 9 10
r6 6 7 8 9 10 11
显然,如果我知道我想要的 rows/columns 的索引,我可以简单地做:
df[3:5, 1:4]
但我可能会在整个分析过程中删除 rows/columns,这样我宁愿按名称而不是按索引 select。从上面的 link 中,我了解到对于列,以下内容将起作用:
subset(df, select=c1:c4)
哪个returns
c1 c2 c3 c4
r1 1 2 3 4
r2 2 3 4 5
r3 3 4 5 6
r4 4 5 6 7
r5 5 6 7 8
r6 6 7 8 9
但我怎么能同时 select 一系列按名称排列的行呢?
在这种特殊情况下,我当然可以使用 grep
但是具有任意名称的列呢?
而且我不想使用
df[c('r3', 'r4' 'r5'), c('c1','c2', 'c3', 'c4')]
但实际切片。
您可以将 which()
与 rownames
一起使用:
subset(df[which(rownames(df)=='r3'):which(rownames(df)=='r5'),], select=c1:c4)
c1 c2 c3 c4
r3 3 4 5 6
r4 4 5 6 7
r5 5 6 7 8
使用match
查找特定行名称的位置。
df[match("r3", rownames(df)):match("r5", rownames(df)), match("c1", colnames(df)):match("c4", colnames(df))]
c1 c2 c3 c4
r3 3 4 5 6
r4 4 5 6 7
r5 5 6 7 8
您可以编写一个函数来提供相同的行为
'%:%' <- function(object, range) {
FUN <- if (!is.null(dim(object))) {
if (is.matrix(object)) colnames else names
} else identity
wh <- if (is.numeric(range)) range else which(FUN(object) %in% range)
FUN(object)[seq(wh[1], wh[2])]
}
df <- data.frame(c1=1:6, c2=2:7, c3=3:8, c4=4:9, c5=5:10, c6=6:11)
rownames(df) <- c('r1', 'r2', 'r3', 'r4', 'r5', 'r6')
像这样使用
df %:% c('c2', 'c4')
# [1] "c2" "c3" "c4"
rownames(df) %:% c('r2', 'r4')
# [1] "r2" "r3" "r4"
针对您的问题
df[rownames(df) %:% c('r3', 'r5'), df %:% c('c1', 'c5')]
# c1 c2 c3 c4 c5
# r3 3 4 5 6 7
# r4 4 5 6 7 8
# r5 5 6 7 8 9