循环遍历data.frame的列以应用条件

问题描述 投票:0回答:5

我有一个像这样的data.frame:

        name       value1      value2     value3   
          a          0.10         0.9       0.10
          b          0.00         0.3       0.67
          c          0.01         0.1       0.10
          d          0.12         0.10      0.2
          e          0.10         0.001     0.1       

对于每列“值*”,我想,名称对应的值为0.10。换句话说,输出将是包含“name”元素的三列data.frame。我开始的想法是将“name”cbind到每个“value *”列然后进行子集但没有成功:

 for(i in 1:length(mydf)){    
      my_subset[[i]] = cbind(rownames(mydf), mydf[[i]])    
 }

列“name”是mydf的rownames。此外,我有10.000行和45列。

期望的输出:

        name       value1      value2     value3   
          a          a           NA        a
          b          NA          NA        NA
          c          NA          NA        c
          d          NA          d         NA
          e          e           NA        NA       

有人可以帮我吗?我知道有一些“应用”功能可能能够完成这项工作,但我不得不学习如何使用for循环。

先感谢您

r for-loop
5个回答
2
投票

这是使用for循环的替代方法

X <- data.frame(
    name = letters[1:5],
    value1 = c(0.10, 0.00, 0.01, 0.12, 0.10),
    value2 = c(0.90, 0.30, 0.10, 0.10, 0.001),
    value3 = c(0.10, 0.67, 0.10, 0.20, 0.10),
    stringsAsFactors = FALSE
)

示例数据:

X
  name value1 value2 value3
1    a   0.10  0.900   0.10
2    b   0.00  0.300   0.67
3    c   0.01  0.100   0.10
4    d   0.12  0.100   0.20
5    e   0.10  0.001   0.10
for (j in grep("value", names(X))) {
    X[, j] <- ifelse(X[, j] == 0.10, X[, "name"], NA)
}

结果:

X
  name value1 value2 value3
1    a      a   <NA>      a
2    b   <NA>   <NA>   <NA>
3    c   <NA>      c      c
4    d   <NA>      d   <NA>
5    e      e   <NA>      e

3
投票

这是你想要的吗?

a = structure(list(value1 = c("0.10", "0.00", "0.01", "0.12", "0.10"
), value2 = c("0.9", "0.3", "0.1", "0.10", "0.001"), value3 = c("0.10", 
"0.67", "0.10", "0.2", "0.1")), row.names = c("a", "b", "c", 
"d", "e"), class = "data.frame")

val = "0.10"
apply(a,2,function(x) rownames(a)[which(x==val)])

$`value1`
[1] "a" "e"

$value2
[1] "d"

$value3
[1] "a" "c"

2
投票

与基地R lapply

cols <- grep("^value", names(df))
df[cols] <- lapply(df[cols], function(x) ifelse(x == 0.1, df$name, NA))


df
#  name value1 value2 value3
#1    a      a   <NA>      a
#2    b   <NA>   <NA>   <NA>
#3    c   <NA>      c      c
#4    d   <NA>      d   <NA>
#5    e      e   <NA>      e

0
投票

这是base R的矢量化方法

df[-1] <- df$name[NA^(df[-1] != 0.1) * seq_len(nrow(df))]
df
#    name value1 value2 value3
#1    a      a   <NA>      a
#2    b   <NA>   <NA>   <NA>
#3    c   <NA>      c      c
#4    d   <NA>      d   <NA>
#5    e      e   <NA>      e

Benchmarks

df1 <- df[rep(seq_len(nrow(df)), 1e7), ]

df2 <- copy(df1)

system.time({
cols <- grep("^value", names(df1))
df1[cols] <- lapply(df1[cols], function(x) ifelse(x == 0.1, df1$name, NA))
})
#    user  system elapsed 
#  35.700   4.587  40.615 
system.time({
 df2[-1] <- df2$name[NA^(df2[-1] != 0.1) * seq_len(nrow(df2))]

})
#   user  system elapsed 
# 21.709   3.886  26.026 

data

df <- structure(list(name = c("a", "b", "c", "d", "e"), value1 = c(0.1, 
 0, 0.01, 0.12, 0.1), value2 = c(0.9, 0.3, 0.1, 0.1, 0.001), value3 = c(0.1, 
  0.67, 0.1, 0.2, 0.1)), class = "data.frame", row.names = c(NA, 
 -5L))

0
投票

您只需使用data.table包即可完成此操作 -

> setDT(dt)[,(setdiff(colnames(dt),"name")):=lapply(.SD,function(x) ifelse(x==.10,as.character(name),NA)),.SDcols=setdiff(colnames(dt),"name")]

> dt
   name value1 value2 value3
1:    a      a   <NA>      a
2:    b   <NA>   <NA>   <NA>
3:    c   <NA>      c      c
4:    d   <NA>      d   <NA>
5:    e      e   <NA>      e
© www.soinside.com 2019 - 2024. All rights reserved.