【问题标题】:Choosing an item from several columns depending on a value in another column根据另一列中的值从多列中选择一个项目
【发布时间】:2015-03-26 21:16:08
【问题描述】:

我在 R 中的数据框有一点问题。这是我的数据框的头。

                         ID              X1 X2 X3     state
1 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     2
2 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     3
3 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     2
4 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     3
5 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     1
6 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     3

我想添加一个新列,其中包含 X1、X2、X3 列的数量,但这取决于状态列。所以我想,如果我的状态是1,我从X1列添加到列号,如果我的状态是2,从X2添加到列号,如果我的状态是3,从X3添加到列号。所以,它看起来像这样:

                         ID              X1 X2 X3     state age
1 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     2     56
2 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     3     57
3 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     2     55
4 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     3     57
5 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     1     69
6 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     3     70

我该怎么做?我已经尝试过 ifelse 和子集,但它不起作用:(

【问题讨论】:

  • 之前肯定有人问过这个问题。 (这是一个非常简单的索引任务。)您是否在 SO 或 Google 上进行过任何搜索?
  • 如果你的数据叫data,做data$age <- data[cbind(seq_len(nrow(data)), data$state + 1L)]
  • @BondedDust 你是否有一个快速的欺骗来结束这个?
  • 我试了一下。我认为提问者应该这样做。我将编辑标题,使其更具描述性。您应该发表您的评论作为答案。我确定有使用双列矩阵索引矩阵但可能还没有用于数据帧的工作示例?
  • @BondedDust 我也找不到。无论哪种方式,我的评论已经包含在下面的答案中。我的名字前没有@,我也看不到你们的cmets。

标签: r indexing dataframe


【解决方案1】:

假设 'dat' 是数据框的名称:

dat$age <- dat[ c("X1","X2", "X3" )][ cbind( seq_len(nrow(dat)), dat$state) ]

使用两列矩阵作为“[”的单个参数,这是基本的 R 索引策略之一。如果查找工作是通过索引到具有不同行数或列数且可能重复的表中完成的,那么您可以使用matchfindInterval 来构建行向量或列向量。和@DavidArenburg 一样,我发现ifelse 很笨拙,尤其是在选项数量可能增加的情况下。

【讨论】:

    【解决方案2】:

    ifelse 在这种情况下可以正常工作。尝试类似:

    dat <- read.table(text = "
    ID              X1 X2 X3     state
    1 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     2
    2 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     3
    3 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     2
    4 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     3
    5 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     1
    6 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     3")
    
    dat$age <- with(dat, ifelse(state == 1, X1, ifelse(state == 2, X2, X3)))
    
    print(dat)
    #                                      ID X1 X2 X3 state age
    #1 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     2  56
    #2 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     3  57
    #3 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     2  55
    #4 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     3  57
    #5 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     1  69
    #6 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     3  70
    

    编辑如果你想使用索引,以下可能是一个选项

    dat$age2 <- dat[cbind(1:nrow(dat), dat$state + 1)]
    print(dat)
    #                                      ID X1 X2 X3 state age age2
    #1 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     2  56   56
    #2 {026560B0-E0BB-4479-832D-2F5EFFAD9E9F} 56 56 57     3  57   57
    #3 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     2  55   55
    #4 {04E6B096-A3CC-4C82-9E01-69BB3D6A0CEF} 55 55 57     3  57   57
    #5 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     1  69   69
    #6 {089E7170-E221-46D9-AE2B-3CD7FB1FEE0B} 69 70 70     3  70   70
    

    【讨论】:

    • 嗯...我不推荐双 ifelse,因为它可以通过索引轻松解决。
    • @DavidArenburg 我认为单个嵌套的ifelse 没有问题。而且我发现索引不太具有表现力——至少是我能想出的索引。编辑:我现在看到的和你一样。 +1 并不需要比玩具数据集更多的东西。
    • ifeslehas its issues。我猜嵌套的更糟糕。
    • 这里有一个问题使用策略进行赋值:stackoverflow.com/questions/10894402/…
    猜你喜欢
    • 1970-01-01
    • 2022-01-22
    • 1970-01-01
    • 1970-01-01
    • 2012-01-30
    • 1970-01-01
    • 2012-05-29
    • 1970-01-01
    • 2022-09-29
    相关资源
    最近更新 更多