繁体   English   中英

对于循环警告:“要替换的项目数不是替换长度的倍数”,带有两个数据框

[英]For loop warning: “number of items to replace is not a multiple of replacement length” with two dataframes

我试图通过基于另一个数据帧中的数据对我的一个数据帧中的变量进行转换来创建新矢量。

我有两个数据框df1和df2。 df1和df2具有不同的尺寸,我在df1中有20,000行,在df2中有76行。 df1是我的原始数据集。 我为Ag_ppm创建了df2,如下所示:

df2 <- df1%>%
  filter(!is.na(Ag_ppm)) %>%
  group_by(Year,Zone, SubZone) %>%
  summarise(
    n = sum(!is.na(Ag_ppm)),
    min = min(Ag_ppm),
    max = max(Ag_ppm),
    mean = mean(Ag_ppm),
    sd = sd(Ag_ppm),
    iqr = IQR(Ag_ppm),
    Q1 = quantile(Ag_ppm, 0.25),
    median = median(Ag_ppm),
    Q3 = quantile(Ag_ppm, 0.75),
    LW = min(Ag_ppm > (quantile(Ag_ppm, .25)-1.5*IQR(Ag_ppm))),
    UF = quantile(Ag_ppm, .75) + 1.5*IQR(Ag_ppm)) 

以下是每个数据帧的第一行:

head(df1, n=5)

# A tibble: 5 x 12
  Year  Zone            SubZone         Au_ppm Ag_ppm Cu_ppm Pb_ppm Zn_ppm As_ppm Sb_ppm Bi_ppm Mo_ppm
  <chr> <chr>           <chr>            <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>  <dbl>
1 1990  BugLake         BugLake          0.007    3.7     17     27     23      1      1     NA      1
2 1983  Johnny Mountain Johnny Mountain  0.01     1.6     71     63    550      4     NA     NA     NA
3 1983  Khyber Pass     Khyber Pass      0.12    11.5    275    204   8230    178      7     60     NA
4 1987  Chebry          Ridge Line Grid  0.05     2.2     35     21    105     16      6     NA     NA
5 1987  Chebry          Handel Grid      0.004    1.3     29     27    663     45      2     NA     NA

head(df2, n=5)
# A tibble: 5 x 14
# Groups:   Year, Zone [3]
  Year  Zone            SubZone         n   min   max  mean    sd   iqr    Q1 median    Q3    LW    UF
  <chr> <chr>           <chr>       <int> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>  <dbl> <dbl> <int> <dbl>
1 1981  Chebry          Handel         52   0.6   5.1 1.83  0.947 0.925  1.2    1.6   2.12     1  3.51
2 1981  Imperial Metals Handel         24   0.9   6.9 2.81  1.43  1.35   1.95   2.65  3.3      1  5.33
3 1983  Chebry          Chebry          5   0.7   3.7 1.78  1.19  0.9    1.2    1.2   2.1      1  3.45
4 1983  Chebry          Handel         17   0.1   0.7 0.318 0.163 0.2    0.2    0.3   0.4      1  0.7 
5 1983  Chebry          Handel Grid   225   0.1  16   0.892 1.33  0.7    0.3    0.6   1        1  2.05

我想使用针对df2中每个子组计算的中位数和IQR将以下方程式应用于df1中的Ag_ppm列:Z =(X-中位数)/ IQR

为此,我写道:

# Initialize Ag_std vector with NA values
Ag_std <- rep(NA, times = nrow(df1))     

# Populate Ag_std vector with standardized Ag values
Ag_std <- 
  for (i in 1:nrow(df1)) {
    if (!is.na(df1$Ag_ppm[i])) { 
        filter(df2, Zone == df1$Zone[i], Year == df1$Year[i], 
           SubZone == df1$SubZone[i]) 
        Ag_std[i] <- (df1$Ag_ppm[i] - df2$median)/df2$iqr
    }
  }

但是循环不起作用(它返回NULL向量),并且我收到此警告:

1: In Ag_std[i] <- (df1$Ag_ppm[i] - df2$median)/df2$iqr :
  number of items to replace is not a multiple of replacement length

我看过类似的问题,但找不到适合我的答案。 任何帮助将非常感激!

如果有更好的方法可以无循环地实现相同的功能(我敢肯定有,例如apply()),那么我也希望得到这样的评论。 不幸的是,我对替代方案还不够熟悉,无法快速实现它们。

由于您将df2作为单独的数据帧,因此可以joinmutate

df1 %>%
  left_join(df2, by = c("Year", "Zone", "SubZone")) %>%
  mutate(Z = (Ag_ppm - median) / iqr)

事实上,你可能会使用DF1本身产生的信息在DF2 summarise

这可以在data.table相对容易地data.table

library(data.table)

DT <- data.table(df1)

#function to apply
fun <- function(x) (x - median(x)) / diff (quantile( x, c(.25, .75)))

# create a new column with desired result
DT[, Ag_std := fun(Ag_ppm), by = list(Year, Zone, SubZone)]

此外,我认为可以通过将“过滤器”的结果分配给临时对象来修复循环

  for (i in 1:nrow(df1)) {
    if (!is.na(df1$Ag_ppm[i])) { 
        temp.var <- filter(df2, Zone == df1$Zone[i], Year == df1$Year[i], 
           SubZone == df1$SubZone[i]) 
        Ag_std[i] <- (df1$Ag_ppm[i] - temp.var$median)/temp.var$iqr
    }
  }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM