使用平方函数在列表中选择元素

时间:2019-01-16 12:42:04

标签: r

我试图跟上R中的列表,并试图使列表中每个数据帧的每个奇数索引位置平方。请参见下面的可复制示例:

set.seed(100)
df <- data.frame(a = rnorm(5), b = rnorm(5))

oddsqr <- function(df){
  (df[seq(1, nrow(df), 2), 2])^2 #selects odd index positions from column 2
}
  

如何编写for循环,以使每个奇数索引位置的平方值都替换现有值?我尝试了下面的解决方案,但失败了,因为我试图用长度为3的向量而不是长度为5的向量替换data.frame中的现有行。

for (i in seq_along(list.df)){
  list.df[[i]][[2]][i] <- oddsqr(list.df[[i]])
}

解决方案

基于上面的示例,我已经弄清楚了如何获得答案,但是它看起来非常难以理解。如果有人可以帮助我优化它,将不胜感激:

for (k in seq_along(list.df)){
  for (i in seq_along(list.df)){
      list.df[[k]][[2]][vec[i]] <- oddsqr(list.df[[k]])[i]
  }
}

解决方案2

基于以下Markus的解决方案:在这种情况下,可以使用lapply使一切变得更加干净和快捷!

2 个答案:

答案 0 :(得分:1)

考虑lapply

out <- lapply(list.df, function(x) {
  idx <- seq(1, nrow(x), 2)
  x[idx, 2] <- x[idx, 2] ^ 2
  x
})

结果

out
#$df1
#  a  b
#1 1  1
#2 2  2
#3 3  9
#4 4  4
#5 5 25

#$df2
#  a  b
#1 1  1
#2 2  2
#3 3  9
#4 4  4
#5 5 25

使用for循环并稍微修改一下OP函数,我们可以获得相同的结果

# returns modified dataframe now and not a vector
oddsqr <- function(df){
  df[seq(1, nrow(df), 2), 2] <- df[seq(1, nrow(df), 2), 2]^2 #selects odd index positions from column 2
  df
}

for (i in seq_along(list.df)) {
  list.df[[i]] <- oddsqr(list.df[[i]])
}
list.df

数据

df <- data.frame(a = 1:5, b = 1:5)
list.df <- list(df1 = df, df2 = df)

答案 1 :(得分:0)

这是tidyverse

中的实现
library(tidyverse)
map(list.df, ~ .x %>%
                mutate(b = case_when(row_number() %% 2 == 1 ~ b^2,
                                     TRUE ~ as.numeric(b))))

数据

df <- data.frame(a = 1:5, b = 1:5)
list.df <- list(df1 = df, df2 = df)