如何通过基于名称而不是索引选择一系列列和行来对数据框进行切片?

Posted

技术标签:

【中文标题】如何通过基于名称而不是索引选择一系列列和行来对数据框进行切片?【英文标题】:How to slice a dataframe by selecting a range of columns and rows based on names and not indexes? 【发布时间】:2016-10-09 11:09:01 【问题描述】:

这是我提出的问题here 的后续问题。在那里我学到了a)如何对列执行此操作(见下文)和b)行和列的选择似乎在R中的处理方式完全不同,这意味着我不能对行使用相同的方法。

所以假设我有一个这样的熊猫数据框:

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

然后我可以像这样轻松地按名称选择行和列:

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

返回

    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

显然,如果我知道我想要的行/列的索引,我可以简单地这样做:

df[3:5, 1:4]

但我可能会在整个分析过程中删除行/列,以便我宁愿按名称选择而不是按索引选择。从上面的链接中,我了解到对于列,以下内容将起作用:

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

但是我怎么能同时按名称选择一系列行呢?

在这种特殊情况下,我当然可以使用grep,但是具有任意名称的列呢?

我不想使用

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

但实际切片。

【问题讨论】:

【参考方案1】:

您可以将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

【讨论】:

是的,我应该更准确(将编辑我的问题):它应该适用于任意名称;这里的那些确实很容易解析:) 好吧,我一开始读得太快了。这是你需要的吗? 太棒了!是的,这很好用。我暂时投赞成票,稍后根据其他答案的质量接受。【参考方案2】:

你可以写一个函数来给你同样的行为

'%:%' <- 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

【讨论】:

【参考方案3】:

使用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

【讨论】:

但是我需要指定我真正想要避免的行和列(我编辑了我的问题以使其更清楚);想象一下你想要选择的 100 行/列... 是的,这也有效(赞成)!您只需要修正index.c 中的拼写错误。 感谢您的关注! 这不是假设行名是按字典顺序排列的吗?情况可能并非总是如此(行名称为 ID 或其他内容) 我更喜欢以前的版本;行名和列名可以是任意的,分别使用 r 和 c 只是一个例子。

以上是关于如何通过基于名称而不是索引选择一系列列和行来对数据框进行切片?的主要内容,如果未能解决你的问题,请参考以下文章

具有多个变量的用户定义函数? / 对一系列命名列进行操作的函数(而不是按数字索引)?

如何获取一系列列作为集合?

Pandas列表的列,通过迭代(选择)三列的每个列表元素作为新列和行来创建多列[重复]

如何通过其编号而不是名称选择数据框中的列

使用一系列列合并两个 DataFrame(在 ID 上右侧,在多个 ID 上左侧)

MySQL视图的操作