【问题标题】:Creating a loop to fill an empty dataframe in R创建循环以填充 R 中的空数据框
【发布时间】:2021-01-21 20:50:27
【问题描述】:

我有一个名为 all.cols2 的数据框,我试图在其中填充空列。列标题是我的站点的名称,我正在尝试计算每个站点随时间变化的水深。这是它的样子:

       Date     Time  cor_water_depth  Levee.slope   Levee.slope.1  

1 2015-12-01 15:05:33           0.088        <NA>          <NA>          
2 2015-12-01 15:25:33           0.079        <NA>          <NA>          
3 2015-12-01 15:45:33           0.080        <NA>          <NA>          
4 2015-12-01 16:05:33           0.076        <NA>          <NA>          
5 2015-12-01 16:25:33           0.080        <NA>          <NA>          
6 2015-12-01 16:45:33           0.075        <NA>          <NA>          
7 2015-12-01 17:05:33           0.070        <NA>          <NA>
8 2015-12-01 17:25:33           0.074        <NA>          <NA>
9 2015-12-01 17:45:33           0.083        <NA>          <NA>
10 2015-12-01 18:05:33           0.105        <NA>          <NA>
11 2015-12-01 18:25:33           0.146        <NA>          <NA>
12 2015-12-01 18:45:33           0.179        <NA>          <NA>

我有另一个名为调查的数据框,它具有我用来计算每个位置的水深的相对高程。这里是:

# A tibble: 6 x 3

 Description      elev_above_sealevel rel_well_elevation
  <chr>                          <dbl>              <dbl>
1 Levee.slope                    1.78              0.909 
2 Levee.slope.1                  1.49              0.627 
3 Levee.slope.2                  1.28              0.413 
4 Levee.slope.3                  1.05              0.187 
5 Levee.slope.4                  0.913             0.0459
6 Hummock.Collar.3               0.956             0.0890

我需要从整个记录期间(即 20,000 多行)的 cor_water_depth 中减去每个站点的 rel_well_elevation。我一直在做这个一个网站。我一直在使用的代码如下所示:

survey[1,] #obtain needed relative well elevation value
all.cols2 <- mutate(all.cols2, Levee.slope = cor_water_depth - 0.909) #calculate new column values
survey[2,]
all.cols2 <- mutate(all.cols2, Levee.slope.1 = cor_water_depth - 0.627)
survey[3,]
all.cols2 <- mutate(all.cols2, Levee.slope.2 = cor_water_depth - 0.413)
survey[4,]
all.cols2 <- mutate(all.cols2, Levee.slope.3 = cor_water_depth - 0.187)

然后我对 all.cols2 中的每个空列重复上述操作。它会像这样填充列:

 Date           Time cor_water_depth Levee.slope Levee.slope.1 
1 2015-12-01 15:05:33           0.088      -0.821        -0.539        
2 2015-12-01 15:25:33           0.079      -0.830        -0.548        
3 2015-12-01 15:45:33           0.080      -0.829        -0.547        
4 2015-12-01 16:05:33           0.076      -0.833        -0.551        
5 2015-12-01 16:25:33           0.080      -0.829        -0.547        
6 2015-12-01 16:45:33           0.075      -0.834        -0.552        
7 2015-12-01 17:05:33           0.070      -0.839        -0.557
8 2015-12-01 17:25:33           0.074      -0.835        -0.553
9 2015-12-01 17:45:33           0.083      -0.826        -0.544
10 2015-12-01 18:05:33           0.105      -0.804        -0.522
11 2015-12-01 18:25:33           0.146      -0.763        -0.481
12 2015-12-01 18:45:33           0.179      -0.730        -0.448

我的实际数据集有 90 多列代表 90 多个位置,所以我想知道是否有更快的方法来做到这一点?

编辑:这个函数可以计算每个位置的水深:

depth <- function(x){
      wl <- all.cols2$cor_water_depth
      elev <- survey$rel_well_elevation
      wl - elev[x]
}

有没有办法把它放在一个循环中来填充我在 all.cols2 中的列?

【问题讨论】:

  • 如果您包含一个简单的reproducible example,其中包含可用于测试和验证可能解决方案的示例输入和所需输出,则更容易为您提供帮助。请不要发布数据图片,因为我们无法将这些图片复制/粘贴到 R 中进行测试。
  • 通常在 R 中,您不想用循环填充空数据框。第一个数据框很宽,(对于大多数分析操作)应该很长,然后您可以 merge 使用第二个数据框。

标签: r dplyr data-manipulation


【解决方案1】:

将单值列绑定到您的 data.frame 并在它们之间进行变异

像这样:

(我不能保证它会起作用,因为你的问题不是truly reproducible

## Extract rel_well... vector from survey
rel_well_elevation <- survey["rel_well_elevation"]

## Use 'description' as vector names
names(rel_well_elevation) <- survey["Description"]

## Turn the vector into a named list
rel_well_elevation <- as.list(rel_well_elevation)

## Bind your list to the data frame
## A data frame is just a list of columns,
## and the new values will be recycled to match
## the lenght of the other vectors

all.cols2 <- 
  cbind(all.cols2, rel_well_elevation)

## Now we use dplyr to mutate across every column

require("dplyr")

all.cols2 <-
  allcos2 %>% 
  ## Mutate across every new column
  mutate(across(all_of(names(rel_well_elevation)),
                function(x){
                  # subtract the new col from cor_water_depth
                  cor_water_depth - x
                }))

【讨论】:

    【解决方案2】:

    下面的循环可以解决这个问题

    ####Calculate water levels for each location
    
    
    list.sites <- list(survey$Description) 
    list.Relev <- survey$rel_well_elevation
    list.well <- well$cor_water_depth
    
    
    i=1
    all.cols2 <- well
    
    for(i in 1:length(list.Relev)){
      site <-  paste0("WaterLevel_",noquote(list.sites[[1]][i])) 
      Relev <- list.Relev[i]
      all.cols2 <- mutate(all.cols2,!!sym(site) := cor_water_depth - Relev) # the trick here was to include the !!sym(). Foudn this workaround for 'dynamic column headers' in mutate after googling for a bit! 
    }
    # checking hte # of rows and columns. Loop works. 
    # test.df is equivalent to 'survey' 
    ncol(test.df)
    nrow(test.df)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-11-06
      • 2018-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-08
      相关资源
      最近更新 更多