如何将函数应用于列表中的特定数据框

时间:2020-07-15 16:39:03

标签: r function dataframe

我有几个数据框,每个数据框包含温度数据,并放入列表中(如下所示是一些模拟数据):

df1 <- data.frame(XH_warmed_air_1m = c(60, 70, 80, 90, 100),
                  XH_ambient_air_1m = c(60, 70, 80, 90, 100))
df2 <- data.frame(XH_warmed_air_1m = c(60, 70, 80, 90, 100),
                  XH_ambient_air_1m = c(60, 70, 80, 90, 100))
df3 <- data.frame(XH_warmed_air_1m = c(0, 10, 20, 30, 40),
                  XH_ambient_air_1m = c(0, 10, 20, 30, 40))

list <- list(df1=df1, df2=df2, df3=df3)
此列表中的

df1和df2包含华氏温度数据,需要将其转换为摄氏度(df3的数据已经以摄氏度为单位)。因此,我做了一个自动将列转换为摄氏度的功能

f_to_c <- function(df){
  df[["XH_warmed_air_1m"]] <- fahrenheit.to.celsius(df[["XH_warmed_air_1m"]])
  df[["XH_ambient_air_1m"]] <- fahrenheit.to.celsius(df[["XH_ambient_air_1m"]])
  return(df)
}

我可以使用lapply将函数应用于整个列表,但这会把df3的数据转换为celsius从而弄乱了df3的数据

list <- lapply(list, f_to_c)

我只想将此功能应用于所需的数据框,下面我尝试这样做。但是,这会导致错误消息# Error in df[["XH_warmed_air_1m"]] : subscript out of bounds

list <- lapply(list$df1, f_to_c)

我可以使用什么方法将此功能仅应用于包含华氏温度的数据帧?

使用R版本3.5.1,Mac OS X 10.13.6

4 个答案:

答案 0 :(得分:2)

您没有在代码中包含fahrenheit.to.celsius函数,因此我在这里添加了它:

fahrenheit.to.celsius <- function(x) (x - 32) / 1.8

您要做的就是将函数应用于列表的子集,并将其写回到同一子集:

list[1:2] <- lapply(list[1:2], f_to_c)

list
#> $df1
#>   XH_warmed_air_1m XH_ambient_air_1m
#> 1         15.55556          15.55556
#> 2         21.11111          21.11111
#> 3         26.66667          26.66667
#> 4         32.22222          32.22222
#> 5         37.77778          37.77778
#> 
#> $df2
#>   XH_warmed_air_1m XH_ambient_air_1m
#> 1         15.55556          15.55556
#> 2         21.11111          21.11111
#> 3         26.66667          26.66667
#> 4         32.22222          32.22222
#> 5         37.77778          37.77778
#> 
#> $df3
#>   XH_warmed_air_1m XH_ambient_air_1m
#> 1                0                 0
#> 2               10                10
#> 3               20                20
#> 4               30                30
#> 5               40                40

作为脚注,有一个名为list ...的列表是一个非常糟糕的主意。

reprex package(v0.3.0)于2020-07-15创建

答案 1 :(得分:1)

我了解到,您只想将此功能应用于列表中包含华氏温度的DF。唯一可以识别数据值是摄氏度还是华氏度的值就是温度本身。因此我选择了最高温度必须低于42摄氏度的条件。

然后,您可以使用keep中的mappurrr很好地建立此条件。


library(tidyverse)

df1 <- data.frame(XH_warmed_air_1m = c(60, 70, 80, 90, 100),
                  XH_ambient_air_1m = c(60, 70, 80, 90, 100))
df2 <- data.frame(XH_warmed_air_1m = c(60, 70, 80, 90, 100),
                  XH_ambient_air_1m = c(60, 70, 80, 90, 100))
df3 <- data.frame(XH_warmed_air_1m = c(0, 10, 20, 30, 40),
                  XH_ambient_air_1m = c(0, 10, 20, 30, 40))
list <- list(df1=df1, df2=df2, df3=df3)

fahrenheit.to.celsius <- function(x) (x - 32) / 1.8

f_to_c <- function(df){
  df[["XH_warmed_air_1m"]] <- fahrenheit.to.celsius(df[["XH_warmed_air_1m"]])
  df[["XH_ambient_air_1m"]] <- fahrenheit.to.celsius(df[["XH_ambient_air_1m"]])
  return(df)
}


list %>% 
  keep(~{max(.x$XH_ambient_air_1m) > 42}) %>% 
  map(., f_to_c)
#> $df1
#>   XH_warmed_air_1m XH_ambient_air_1m
#> 1         15.55556          15.55556
#> 2         21.11111          21.11111
#> 3         26.66667          26.66667
#> 4         32.22222          32.22222
#> 5         37.77778          37.77778
#> 
#> $df2
#>   XH_warmed_air_1m XH_ambient_air_1m
#> 1         15.55556          15.55556
#> 2         21.11111          21.11111
#> 3         26.66667          26.66667
#> 4         32.22222          32.22222
#> 5         37.77778          37.77778

答案 2 :(得分:0)

另一个选项是map

library(purrr)
list[1:2] <-  map(list[1:2], f_to_c)

答案 3 :(得分:0)

您可以检查数据框是否包含F / C温度。我在这里假设,如果任何值小于或等于0,那么我们正在处理C。

list <- lapply(list, function(x) ifelse(any(x <= 0.), x, f_to_c(x)))