突变前n行而不丢弃其他行

时间:2018-10-09 01:03:31

标签: r dplyr tibble

我下面有以下data.frame。我想创建一个新列w(以权重计)。对于每个给定日期具有n个最高收益的行业,w应该等于1 / n,而对于其他行业,group_by(date)应该等于0。我可以top_n(3, wt = return)并使用mutate(w = 1/n)来过滤排名靠前的行业,然后过滤mutate,但是我如何w而不丢弃structure(list(date = structure(c(16556, 16556, 16556, 16556, 16556, 16556, 16556, 16556, 16556, 16556, 16587, 16587, 16587, 16587, 16587, 16587, 16587, 16587, 16587, 16587, 16617, 16617, 16617, 16617, 16617, 16617, 16617, 16617, 16617, 16617), class = "Date"), industry = c("Hlth", "Txtls", "BusEq", "Fin", "ElcEq", "Food", "Beer", "Books", "Cnstr", "Carry", "Clths", "Txtls", "Fin", "Games", "Cnstr", "Meals", "Hlth", "Hshld", "Telcm", "Rtail", "Smoke", "Games", "Clths", "Rtail", "Servs", "Meals", "Food", "Hlth", "Beer", "Trans"), return = c(4.89, 4.37, 4.02, 2.99, 2.91, 2.03, 2, 1.95, 1.86, 1.75, 4.17, 4.09, 1.33, 1.26, 0.42, 0.29, 0.08, -0.11, -0.45, -0.48, 9.59, 6, 5.97, 5.78, 5.3, 4.15, 4.04, 3.67, 3.51, 3.27)), row.names = c(NA, -30L ), class = c("tbl_df", "tbl", "data.frame")) # A tibble: 30 x 3 date industry return <date> <chr> <dbl> 1 2015-05-01 Hlth 4.89 2 2015-05-01 Txtls 4.37 3 2015-05-01 BusEq 4.02 4 2015-05-01 Fin 2.99 5 2015-05-01 ElcEq 2.91 6 2015-05-01 Food 2.03 7 2015-05-01 Beer 2 8 2015-05-01 Books 1.95 9 2015-05-01 Cnstr 1.86 10 2015-05-01 Carry 1.75 # ... with 20 more rows = 0的其他行业?

n

编辑:您将如何处理关系?假设并列第三名。第三名的权重应在第三名和第四名之间分配(假设只有2个并列),权重为(1 / n)/ 2。第一名和第二名的权重保持在1 / n。

编辑:假设A2 =3。每个A1的前3个w值应获得权重structure(list(A1 = structure(c(1L, 1L, 1L, 1L, 1L, 2L, 2L, 2L, 2L), .Label = c("A", "B"), class = "factor"), A2 = c(1, 3, 3, 4, 5, 6, 7, 8, 8)), row.names = c(NA, -9L), class = "data.frame") 的1/3 如果没有联系。如果并列第3名(T3),则我们有(第1,第2,T3,T3),我希望权重分别为1 / 3、1 / 3、1 / 6、1 / 6,以保持总和重量为1。但这仅排在第三位。 (1st,T2,T2)的权重应为1 / 3、1 / 3、1 / 3。 (T1,T1,T2,T2)的权重应为1 / 3、1 / 3、1 / 6、1 / 6等。

df

> df A1 A2 w 1 A 1 0 2 A 3 0.1666 3 A 3 0.1666 4 A 4 0.3333 5 A 5 0.3333 6 B 6 0 7 B 7 0.3333 8 B 8 0.3333 9 B 8 0.3333 的输出应为:

@Override
public void onResponse(final Call<Category> call, final Response<Category> response) {
    if (response.isSuccessful()) {

    } else {
        try {
            String errorBody = response.errorBody().string();

            JSONObject jsonObject = new JSONObject(errorBody.trim());

            jsonObject = jsonObject.getJSONObject("error");

            jsonObject = jsonObject.getJSONObject("message");

            Iterator<String> keys = jsonObject.keys();
            String errors = "";
            while (keys.hasNext()) {
                String key = keys.next();
                JSONArray arr = jsonObject.getJSONArray(key);
                for (int i = 0; i < arr.length(); i++) {
                    errors += key + " : " + arr.getString(i) + "\n";
                }
            }
            Common.errorLog("ERRORXV", errors);
        } catch (JSONException e) {
            e.printStackTrace();
        }
    }
}

2 个答案:

答案 0 :(得分:2)

我们可以使用ifelse创建一个条件。在按“日期”分组之后,arrange根据“日期”以数据集的形式排列,然后按降序返回“返回”,然后通过创建条件来创建“ w”,如果row_number()小于'n',然后将'return'除以'n',否则返回0

n <- 3
df1 %>%
   group_by(date) %>%
   arrange(date, -return) %>% 
   mutate(w = ifelse(row_number() <= n, return/n, 0))

如果我们使用的是top_n,请在过滤后的数据集中创建“ w”列,并与原始列连接

df1 %>% 
  group_by(date) %>% 
  top_n(return, n = 3) %>% 
  mutate(w = return/n()) %>% 
  right_join(df1)  %>% 
  mutate(w = replace_na(w, 0))

答案 1 :(得分:2)

我们可以按date分组,然后sort return变量获得最后3个输入项(前3个),然后返回return/n或0。

library(dplyr)
n <- 3
df %>%
  group_by(date) %>%
  mutate(w = ifelse(return %in% tail(sort(return), n), return/n, 0))


# date       industry return     w
#   <date>     <chr>     <dbl> <dbl>
# 1 2015-05-01 Hlth       4.89  1.63
# 2 2015-05-01 Txtls      4.37  1.46
# 3 2015-05-01 BusEq      4.02  1.34
# 4 2015-05-01 Fin        2.99  0   
# 5 2015-05-01 ElcEq      2.91  0   
# 6 2015-05-01 Food       2.03  0   
# 7 2015-05-01 Beer       2     0   
#....

使用ave

等于相同逻辑的基数R
ave(df$return, df$date, FUN = function(x) ifelse(x %in% tail(sort(x), n), x/n, 0))

编辑

如评论中所述,在平局中,OP要返回(1 / n)/ 2或除以我们拥有的平局数。

为此,我创建了一个新的更简单的数据框,可以轻松了解正在发生的情况。

df <- data.frame(A1 = rep(c("A", "B"),c(5, 4)), A2 = 1:9)
df$A2[2] <- 3

如果我们使用当前提供的代码

df %>%
   group_by(A1) %>%
   mutate(w = ifelse(A2 %in% tail(sort(A2), n), A2/n, 0))

  # A tibble: 9 x 3
  # Groups:   A1 [2]
#  A1       A2     w
# <fct> <int> <dbl>
#1 A         1  0   
#2 A         3  1   
#3 A         3  1   
#4 A         4  1.33
#5 A         5  1.67
#6 B         6  0   
#7 B         7  2.33
#8 B         8  2.67
#9 B         9  3   

这不是我们想要的。为避免这种情况,我们可以再次按A2进行分组,并且仅对w!=0的行除以A2的出现次数。

df %>%
  group_by(A1) %>%
  mutate(w = ifelse(A2 %in% tail(sort(A2), n), A2/n, 0)) %>%
  group_by(A2) %>%
  mutate(w1 = ifelse(w != 0, w/n(), w)) %>%
  ungroup()

# A1       A2     w    w1
#  <fct> <dbl> <dbl> <dbl>
#1 A         1  0     0   
#2 A         3  1     0.5 
#3 A         3  1     0.5 
#4 A         4  1.33  1.33
#5 A         5  1.67  1.67
#6 B         6  0     0   
#7 B         7  2.33  2.33
#8 B         8  2.67  2.67
#9 B         9  3     3   

另一个编辑

结果证明,我们仅想将w除以当前的最后一组。此外,每组中所有w的总和应为1。对于更新后的数据集,我们可以这样做

n <- 3

temp_df <- df %>%
            group_by(A1) %>%
            top_n(n, A2)


 temp_df %>%
     arrange(A1, A2) %>%
     mutate(w = ifelse(A2 == A2[1], 
    (1 - (1/n * sum(A2 != A2[1])))/sum(A2 == A2[1]), 1/n)) %>%
     bind_rows(anti_join(df, temp_df) %>%
                      mutate(w = 0)
    ) %>%
     arrange(A1, A2)


# A1       A2     w
#  <fct> <dbl> <dbl>
#1 A         1 0    
#2 A         3 0.167
#3 A         3 0.167
#4 A         4 0.333
#5 A         5 0.333
#6 B         6 0    
#7 B         7 0.333
#8 B         8 0.333
#9 B         8 0.333

让我们尝试另一个变体,我们将组的所有值保持不变。

df1 = df
df1$A2[6:9] <- 10


 temp_df <- df1 %>%
             group_by(A1) %>%
             top_n(n, A2)


  temp_df %>%
       arrange(A1, A2) %>%
       mutate(w = ifelse(A2 == A2[1], 
      (1 - (1/n * sum(A2 != A2[1])))/sum(A2 == A2[1]), 1/n)) %>%
       bind_rows(anti_join(df1, temp_df) %>%
                      mutate(w = 0)
       ) %>%
       arrange(A1, A2)


#  A1       A2     w
#  <fct> <dbl> <dbl>
#1 A         1 0    
#2 A         3 0.167
#3 A         3 0.167
#4 A         4 0.333
#5 A         5 0.333
#6 B        10 0.25 
#7 B        10 0.25 
#8 B        10 0.25 
#9 B        10 0.25 

逻辑是我们使用A2选择前3个top_n值及其组。使用anti_join,我们获得不在前3名中的所有行,并将固定权重w分配为0。对于前3名中包含的行,我们获得最后一组行并将其分配将权重分配给非最后一组后剩余的权重。