【问题标题】:How to loop a function over columns in many dataframes in r如何在r中的许多数据帧中的列上循环函数
【发布时间】:2019-11-13 05:29:40
【问题描述】:

我有许多数据帧 (96),其中包含 0 和 1 的列。如果数据帧的任何一列中有多个“1”,我想用相等的分数替换 1,以便该列中的值之和为 1,如下面的代码所示。

v1 <- c(0, 1, 0, 1, 1, 0)
v2 <- c(0, 0, 1, 0, 0, 0)
v3 <- c(0, 0, 1, 1, 0, 0)
df1 <- data.frame(v1, v2, v3)
df2 <-data.frame(v3, v3, v1)
df3 <- data.frame(v1, v3, v1)
new.df1 <- t(apply(df1, 2, FUN = function(x) {
  if(sum(x==1, na.rm=TRUE) ==2)  replace(x, x==1, 0.5)
  else if (sum(x==1, na.rm=TRUE)==3) replace( x, x==1, 1/3) 
  else x}))

new.df2 <- t(apply(df2, 2, FUN = function(x) {
  if(sum(x==1, na.rm=TRUE) ==2)  replace(x, x==1, 0.5)
  else if (sum(x==1, na.rm=TRUE)==3) replace( x, x==1, 1/3) 
  else x}))

new.df3 <- t(apply(df3, 2, FUN = function(x) {
  if(sum(x==1, na.rm=TRUE) ==2)  replace(x, x==1, 0.5)
  else if (sum(x==1, na.rm=TRUE)==3) replace( x, x==1, 1/3) 
  else x}))

我可以像上面的例子一样用蛮力创造我想要的东西,但必须有更好(更简洁)的方法。非常感谢您的帮助。

【问题讨论】:

标签: r loops dataframe lapply


【解决方案1】:

与另一个答案类似,但更模块化和改进的函数版本:

## Put your data frames in a list
# df_list = list(df1, df2, df3)
df_list = mget(ls(pattern = "df[0-9]"))

## Write a function to modify one column
replace_ones = function(x) {
  sx = sum(x == 1, na.rm = TRUE)
  if(sx > 1) {
    x = replace(x, x == 1, 1 / sx)
  }
  return(x)
}

## Wrap it to modify a data frame:
replace_ones_df = function(df) {
  df[] = lapply(df, replace_ones)
  return(df)
}

## Apply the function to all columns of all data frames:
result_list = lapply(df_list, replace_ones_df)
# $df1
#          v1 v2  v3
# 1 0.0000000  0 0.0
# 2 0.3333333  0 0.0
# 3 0.0000000  1 0.5
# 4 0.3333333  0 0.5
# 5 0.3333333  0 0.0
# 6 0.0000000  0 0.0
# 
# $df2
#    v3 v3.1        v1
# 1 0.0  0.0 0.0000000
# 2 0.0  0.0 0.3333333
# 3 0.5  0.5 0.0000000
# 4 0.5  0.5 0.3333333
# 5 0.0  0.0 0.3333333
# 6 0.0  0.0 0.0000000
# 
# $df3
#          v1  v3      v1.1
# 1 0.0000000 0.0 0.0000000
# 2 0.3333333 0.0 0.3333333
# 3 0.0000000 0.5 0.0000000
# 4 0.3333333 0.5 0.3333333
# 5 0.3333333 0.0 0.3333333
# 6 0.0000000 0.0 0.0000000

【讨论】:

  • 谢谢@Gregor。使用 lapply,如何指定函数是在行还是列上运行?如果您想将该函数应用于 data.frame 的行而不是列,您将如何修改代码?
  • lapply 跨列运行。如果你想遍历行,我建议使用matrix 而不是数据框,使用apply 而不是lapply。 (您可以在数据框上使用apply,但它只是先在内部将其转换为矩阵)
【解决方案2】:

将您的代码存储在一个函数中,将您的数据帧存储在一个列表中,然后使用 lapply 使用您的函数循环遍历每个列表元素。

 recalc <- function(df) {
        t(apply(df, 2, FUN = function(x) {
            if(sum(x==1, na.rm=TRUE) ==2)  replace(x, x==1, 0.5)
            else if (sum(x==1, na.rm=TRUE)==3) replace( x, x==1, 1/3) 
            else x}))
    } 


lapply(dflist, function(df) recalc(df))

[[1]]
   [,1]      [,2] [,3]      [,4]      [,5] [,6]
v1    0 0.3333333  0.0 0.3333333 0.3333333    0
v2    0 0.0000000  1.0 0.0000000 0.0000000    0
v3    0 0.0000000  0.5 0.5000000 0.0000000    0

[[2]]
     [,1]      [,2] [,3]      [,4]      [,5] [,6]
v3      0 0.0000000  0.5 0.5000000 0.0000000    0
v3.1    0 0.0000000  0.5 0.5000000 0.0000000    0
v1      0 0.3333333  0.0 0.3333333 0.3333333    0

[[3]]
     [,1]      [,2] [,3]      [,4]      [,5] [,6]
v1      0 0.3333333  0.0 0.3333333 0.3333333    0
v3      0 0.0000000  0.5 0.5000000 0.0000000    0
v1.1    0 0.3333333  0.0 0.3333333 0.3333333    0

【讨论】:

  • 要获取列表中的所有全局环境数据帧,请使用eapplymgetFilter(is.data.frame, eapply(.GlobalEnv, identity))Filter(is.data.frame, mget(x=ls(), envir=.GlobalEnv))。或按名称,例如 df 前缀 mget(ls(pattern="df")).
【解决方案3】:

不要手动计算二进制列中 1 的数量并使用 if/else,而是将放在 list 中的数据集与列总和 (colSums) 相除

lapply(mget(paste0("df", 1:3)), function(x) x/colSums(x)[col(x)])
#$df1
#         v1 v2  v3
#1 0.0000000  0 0.0
#2 0.3333333  0 0.0
#3 0.0000000  1 0.5
#4 0.3333333  0 0.5
#5 0.3333333  0 0.0
#6 0.0000000  0 0.0

#$df2
#   v3 v3.1        v1
#1 0.0  0.0 0.0000000
#2 0.0  0.0 0.3333333
#3 0.5  0.5 0.0000000
#4 0.5  0.5 0.3333333
#5 0.0  0.0 0.3333333
#6 0.0  0.0 0.0000000

#$df3
#         v1  v3      v1.1
#1 0.0000000 0.0 0.0000000
#2 0.3333333 0.0 0.3333333
#3 0.0000000 0.5 0.0000000
#4 0.3333333 0.5 0.3333333
#5 0.3333333 0.0 0.3333333
#6 0.0000000 0.0 0.0000000

【讨论】:

    猜你喜欢
    • 2021-11-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多