簡體   English   中英

根據其他列的條件創建一個新列

[英]Create a new column based on the conditions of other columns

原始數據如下所示,

Year   Price    Volume   P1    P2    P3   V1    V2    V3
2009    46       125     25    50    75   200   400   600
2009    65       800     25    50    75   200   400   600
2010    20       560     30    55    90   250   500   800
2010    15       990     30    55    90   250   500   800
2011    89       350     35    70    120  250   500   800
2012    23       100     35    70    120  250   500   800
...     ...      ...     ...   ...   ...  ...   ...   ...

我嘗試創建一個名為“ Portfolio”的新列。 如果Price和Volume分別小於P1和V1,則Portfolio等於11。然后,如果Price小於P1但Volume小於V2,Portfolio等於12,依此類推。 價格和數量都有3個斷點。 因此,創建了16個投資組合,分別命名為11、12、13、14、21、22、23、24,...,44。 結果如下表所示,

Year   Price    Volume   P1    P2    P3   V1    V2    V3   Portfolio
2009    46       125     25    50    75   200   400   600    21
2009    65       800     25    50    75   200   400   600    34
2010    20       560     30    55    90   250   500   800    13
2010    15       990     30    55    90   250   500   800    14
2011    89       350     35    70    120  250   500   800    32
2012    23       100     35    70    120  250   500   800    11
...     ...      ...     ...   ...   ...  ...   ...   ...    ...

您能幫我解決這個問題嗎? 我嘗試過if(){}和其他if(){}函數。 但是,我沒有得到第二張表的結果。 這就是為什么我在這里發布原始數據。 非常感謝。

我嘗試的代碼如下:

if ((Price<P1)&&(Volume<V1)){data$Portfolio=11}
else if ((Price<P1)&&(Volume<V2)){data$Portfolio=12}
else if((Price<P1)&&(Volume<V3)){data$Portfolio=13}
else if(Price<P1){data$Portfolio=14}
else if((Price<P2)&&(Volume<V1)){Fin_Ret$port=21}
...
else if(Price>P3){data$Portfolio=44}

輸出是

> if ((Price<P1)&&(Volume<V1)){data$Portfolio=11}
> else if ((Price<P1)&&(Volume<V2)){data$Portfolio=12}
Error: unexpected 'else' in "else"
...

當我嘗試用“&”代替“ &&”時,結果顯示,

> if ((mkvalt<MV20)&(BM<BM20)){Fin_Ret$port=11}
Warning message:
In if ((mkvalt < MV20) & (BM < BM20)) { :
the condition has length > 1 and only the first element will be used

我很困惑,也許我不了解R中的基本知識。

您可以使用:

df$Portfolio[(df$Price<df$P1)&(df$Volume<df$V1)] <- 11
df$Portfolio[(df$Price<df$P1)&(df$Volume<df$V2) & is.na(df$Portfolio)] <- 12

或使用dplyr :: mutate

library(dplyr)
df <- df %>% 
        mutate(Portfolio=ifelse((Price<P1)&(Volume<V1),11,NA)) %>% 
        mutate(Portfolio=ifelse((Price<P1)&(Volume<V2)& is.na(Portfolio),12,Portfolio))

在您提供的代碼中,

else if(Price<P1){data$Portfolio=14}
else if((Price<P2)&&(Volume<V1)){Fin_Ret$port=21}
...
else if(Price>P3){data$Portfolio=44}

卸下if以后else的最后一行。 您應該能夠獲得預期的結果。

這是使用findIntervaldata.table一種簡潔方法。 根據觀察結果, Portfolio ID由兩位數字組成,其中第一位數字僅由價格類別確定,第二位數字僅由數量類別確定。

library(data.table)
dt[, Portfolio := paste0(findInterval(Price, c(-Inf, P1, P2, P3)), 
                         findInterval(Volume, c(-Inf, V1, V2, V3))),
   by = .(P1, P2, P3, V1, V2, V3)]

print(dt)
#   Year Price Volume P1 P2  P3  V1  V2  V3 Portfolio
#1: 2009    46    125 25 50  75 200 400 600        21
#2: 2009    65    800 25 50  75 200 400 600        34
#3: 2010    20    560 30 55  90 250 500 800        13
#4: 2010    15    990 30 55  90 250 500 800        14
#5: 2011    89    350 35 70 120 250 500 800        32
#6: 2012    23    100 35 70 120 250 500 800        11

在默認情況下, findInterval使用右打開間隔,該間隔符合OP代碼中的條件(Price<P1)等。

數據

使其成為可復制的示例

dt <- fread("Year   Price    Volume   P1    P2    P3   V1    V2    V3
            2009    46       125     25    50    75   200   400   600
            2009    65       800     25    50    75   200   400   600
            2010    20       560     30    55    90   250   500   800
            2010    15       990     30    55    90   250   500   800
            2011    89       350     35    70    120  250   500   800
            2012    23       100     35    70    120  250   500   800")

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM