簡體   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