【问题标题】:Returning value from one column conditional on another column以另一列为条件从一列返回值
【发布时间】:2018-02-21 13:53:40
【问题描述】:

我有一个宽 data.frame 代表对行的观察和对列的时间段的观察。我在10 时间段中有两个变量AB。变量A 是二进制变量,变量B 是连续变量。

我想在数据框中创建一个新列,按行返回与第一次 A == 1 对应的 B 的值,确保忽略 NAs 并继续如果未达到 1,则为下一列(我想是 na.rm=TRUE)。

这是数据(仅使用 3 个时间段而不是 10 个,这非常罕见):

structure(list(A.1 = c(1L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 
0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L, 0L), 
A.2 = c(1L, NA, 0L, 0L, NA, 0L, NA, NA, 0L, 0L, 0L, 0L, 1L, 
0L, 0L, 0L, 0L, 0L, 0L, NA, NA, 0L, 0L, 0L, NA), A.3 = c(NA, 
NA, 1L, NA, NA, 0L, NA, NA, NA, 0L, NA, NA, NA, NA, 0L, NA, 
0L, NA, 0L, NA, NA, NA, 0L, NA, NA), B.1 = c(63L, 58L, 87L, 
60L, 67L, 58L, 67L, 50L, 77L, 57L, 57L, 65L, 55L, 65L, 61L, 
61L, 67L, 75L, 79L, 68L, 53L, 73L, 77L, 77L, 69L), B.2 = c(64L, 
NA, 88L, 63L, NA, 59L, NA, NA, 79L, 58L, 58L, 66L, 57L, 67L, 
62L, 62L, 68L, 77L, 80L, NA, NA, 74L, 78L, 78L, NA), B.3 = c(NA, 
NA, 90L, NA, NA, 60L, NA, NA, NA, 59L, NA, NA, NA, NA, 63L, 
NA, 69L, NA, 82L, NA, NA, NA, 79L, NA, NA)), .Names = c("A.1", 
"A.2", "A.3", "B.1", "B.2", "B.3"), row.names = c(1L, 3L, 4L, 
8L, 10L, 11L, 14L, 15L, 16L, 18L, 21L, 23L, 25L, 27L, 29L, 34L, 
36L, 44L, 46L, 51L, 52L, 53L, 55L, 58L, 60L), class = "data.frame")

最后一列应为第一个值返回63,为第二个值返回NA,为第三个值返回90,依此类推。

谢谢!

【问题讨论】:

  • with(df1, df1[A == 1, B ]) 这里df1 是您的数据框。我不确定您的宽数据框是什么样的。请使用dput(df1) 发布您的数据样本
  • with(df1, df1[ (!is.na(A)) & A == 1, ])
  • 您的数据中没有一个A ==1,也给我们您的预期输出,这使我们的生活变得更加轻松,并将帮助您提出有意义的示例数据
  • 抱歉,数据非常稀缺,“A”变量中的更多 1 稍后会出现。希望这可以帮助! (这方面还是新的)

标签: r dataframe apply lapply


【解决方案1】:

这是apply 的一种方式:

df1$C <-
  apply(df1,1,function(x){
    i <- match(1,head(x,length(x)/2))
    if (length(i)) tail(x,length(x)/2)[i] else NA
  })

df1
#    A.1 A.2 A.3 B.1 B.2 B.3  C
# 1    1   1  NA  63  64  NA 63
# 3    0  NA  NA  58  NA  NA NA
# 4    0   0   1  87  88  90 90
# 8    0   0  NA  60  63  NA NA
# 10   0  NA  NA  67  NA  NA NA
# 11   0   0   0  58  59  60 NA
# 14   0  NA  NA  67  NA  NA NA
# 15   0  NA  NA  50  NA  NA NA
# 16   0   0  NA  77  79  NA NA
# 18   0   0   0  57  58  59 NA
# 21   0   0  NA  57  58  NA NA
# 23   0   0  NA  65  66  NA NA
# 25   0   1  NA  55  57  NA 57
# 27   0   0  NA  65  67  NA NA
# 29   0   0   0  61  62  63 NA
# 34   0   0  NA  61  62  NA NA
# 36   0   0   0  67  68  69 NA
# 44   0   0  NA  75  77  NA NA
# 46   0   0   0  79  80  82 NA
# 51   0  NA  NA  68  NA  NA NA
# 52   0  NA  NA  53  NA  NA NA
# 53   0   0  NA  73  74  NA NA
# 55   0   0   0  77  78  79 NA
# 58   0   0  NA  77  78  NA NA
# 60   0  NA  NA  69  NA  NA NA

如果您的表中有其他列,这将不起作用,但只需将head(x,length(x)/2)) 替换为x[A_indices](例如x[3:12])和tail(x,length(x)/2)) 替换为x[B_indices](例如x[13:22]),它应该工作。

为了比较,这里有一个tidyverse 解决方案:

library(tidyverse)
Cs <- df1 %>%
  rowid_to_column %>%
  gather(,,-1) %>%
  separate(key,c("letter","number")) %>%
  spread(letter,value) %>%
  filter(A==1) %>%
  group_by(rowid) %>%
  slice(1) %>%
  select(rowid,C=B)

df1$C <- NA
df1$C[Cs$rowid] <- Cs$C

【讨论】:

  • 谢谢!这完美!为糟糕的开始道歉!
【解决方案2】:

这是你的解决方案:

for(i in 1:nrow(test)){
  new <- (((test[i, 4:6] [grepl(x=test[i, 1:3],pattern= "1")])))
  test[i, "new"] <- ifelse(dim(new)[2] == 1, new[[1]], NA)
}

请相应地调整列索引。请原谅我的代码有点乱,因为我已经很着急了,但不能停止思考你的问题。

希望我的代码可以帮助您获得所需的结果。

祝你好运,干杯,

贾廷。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-05-19
    • 2018-04-11
    • 2021-04-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多