如何根据数据框的名称而不是索引选择数据框中的列范围?

时间:2016-06-08 22:45:41

标签: r dataframe subset code-conversion

在像这样创建的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   2   7   3   3   2   8
r1   6   9   6   7   9   1
r2   4   0   9   8   4   2
r3   9   0   4   3   5   4
r4   7   6   8   8   0   8
r5   0   6   1   8   2   2

我可以使用.loc轻松选择某些行和/或一系列列:

print df.loc[['r1', 'r5'], 'c1':'c4']

那会回来:

    c1  c2  c3  c4
r1   9   6   7   9
r5   6   1   8   2

因此,我可以在列表中选择特定的行/列,使用冒号的行/列范围。

如何在R中做到这一点? Herehere总是必须按索引指定所需的列范围,但不能 - 或者至少我没有找到它 - 按名称访问这些列。举个例子:

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('r1', 'r5'),'c1':'c4']

不起作用并抛出错误。唯一对我有用的是

df[c('r1', 'r5'), 1:4]

返回

   c1 c2 c3 c4
r1  1  2  3  4
r5  5  6  7  8

但是我如何按名称而不是按索引选择列(当我在整个分析过程中删除某些列时,这可能很重要)?在这种特殊情况下,我当然可以使用grep但是如何使用具有任意名称的列?

所以我不想使用

df[c('r1', 'r5'),c('c1','c2', 'c3', 'c4')]

但实际切片。

编辑:

可以找到后续问题here

5 个答案:

答案 0 :(得分:9)

看起来您可以使用subset

来完成此操作
> 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')
> subset(df, select=c1:c4)
   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
> subset(df, select=c1:c2)
   c1 c2
r1  1  2
r2  2  3
r3  3  4
r4  4  5
r5  5  6
r6  6  7

如果你想按行名称范围进行子集化,那么这个hack会这样做:

> gRI <- function(df, rName) {which(match(rNames, rName) == 1)}
> df[gRI(df,"r2"):gRI(df,"r4"),]
   c1 c2 c3 c4 c5 c6
r2  2  3  4  5  6  7
r3  3  4  5  6  7  8
r4  4  5  6  7  8  9

答案 1 :(得分:2)

如果您不介意使用data.table,那么subset的另一种方法是:

data.table::setDT(df)
df[1:3, c2:c4, with=F]
   c2 c3 c4
1:  2  3  4
2:  3  4  5
3:  4  5  6

但这仍然无法解决行范围子集的问题。

答案 2 :(得分:1)

添加到@ evan058的答案:

subset(df[rownames(df) %in% c("r3", "r4", "r5"),], select=c1:c4)

c1 c2 c3 c4
r3  3  4  5  6
r4  4  5  6  7
r5  5  6  7  8

但请注意,:运算符可能无法在此处运行;您必须写出要明确包含的每一行的名称。可能更容易按其他列的某个特定值进行分组,或者创建索引列,如评论中提到的@ evan058。

答案 3 :(得分:1)

使用dplyr软件包的解决方案,但您需要在手动

之前指定要选择的行
rowName2Match <- c("r1", "r5")

df1 <- df %>% 
  select(matches("2"):matches("4")) %>% 
  add_rownames() %>% 
  mutate(idRow = match(rowname, rowName2Match)) %>% 
  slice(which(!is.na(idRow))) %>% 
  select(-idRow)
df1

> df1
Source: local data frame [2 x 4]

  rowname    c2    c3    c4
   <chr> <int> <int> <int>
1      r1     2     3     4
2      r5     6     7     8

答案 4 :(得分:-1)

这似乎太容易了,所以也许我做错了。

df <- data.frame(c1=1:6, c2=2:7, c3=3:8, c4=4:9, c5=5:10, c6=6:11,
                 row.names=c('r1', 'r2', 'r3', 'r4', 'r5', 'r6'))


df[c('r1','r2'),c('c1','c2')]

   c1 c2
r1  1  2
r2  2  3