2017-07-21 9 views
8

mam ten dataframe, wygląda to tak:podciągu, Pad i wklej Kolumny w Dataframe bez Loop

enter image description here

muszę wziąć pierwszy znak z kolumny na, całą wartość w , po czym ustaw na końcu licznik, który zwiększa się dla powtórzeń w kolumnie. Ten licznik musi zawsze mieć długość trzech. Wynik końcowy jest taki:

enter image description here

Więc nic tutaj, że dramatyczny, udało mi się zrobić to z następującego kodu (przygotowanie pod wrażeniem):

library(stringr) 
tk <- "" 
for (i in 1:nrow(df)){ 
    if (tk == df$an[i]){ 
    counter <- counter + 1 
    } else { 
    tk <- df$an[i] 
    counter <- 1 
    } 
    df$ap[i] <- counter 
} 

df$ap <- paste0(substr(df$at, 1, 1), df$an, str_pad(df$ap, 3, pad="0")) 

I tak nie jestem zadowolony z tej klęski. Wydaje mi się, że nie jest to bardzo "R" i bardzo bym tego nie chciał, aby ujrzeć światło dzienne. Jak mogę zrobić to bardziej "R"?

Doceniam poradę.

+1

Czy możesz opublikować wyjście 'dput (DF)' dla przykładu z pięcioma wierszami? – Frank

+1

Wszystkie te odpowiedzi pomagają mi lepiej zrozumieć prawdziwe r. Nauczę się technik dla każdego z nich. Ale kto dostaje upragnioną "odpowiedź"? Jestem skłonny po prostu iść z najbardziej upvotes, ponieważ wszystkie są świetne ... i dplyr wygrywa. – DieselBlue

Odpowiedz

8
library(stringr) 
library(dplyr) 
df1 <- df %>% 
      group_by(an) %>% 
      mutate(ap=paste0(substr(at, 1, 1), an, str_pad(row_number(), 3, pad="0"))) 

    at  an   ap 
1 NDA 023356 N023356001 
2 ANDA 023357 A023357001 
3 ANDA 023357 A023357002 
4 NDA 023357 N023357003 
5 ANDA 023398 A023398001 
3

to działa:

library(stringr)  
df = data.frame(at=c("NDA","ANDA","ANDA","NDA","ANDA"),an=c("023356","023357","023357","023357","023398"),stringsAsFactors = F) 

df$ap = paste0(substr(df$at,1,1), 
       df$an,str_pad(ave(df$an, df$an, FUN = seq_along),width=3,pad="0")) 

wyjściowa:

at  an   ap 
1 NDA 023356 N023356001 
2 ANDA 023357 A023357001 
3 ANDA 023357 A023357002 
4 NDA 023357 N023357003 
5 ANDA 023398 A023398001 

Nadzieja to pomaga!

+0

To rozwiązanie faktycznie rozwiązało inny problem, jaki miałem! dzięki @Florian! – DieselBlue

+0

Świetnie, cieszę się, że mogę pomóc! – Florian

6

w bazie R, można użyć sprintf do 0s podkładki oraz ave, aby uzyskać liczbę tak:

df$ap <- paste0(substr(df$at, 1, 1), df$an, 
       sprintf("%03.0f", as.numeric(ave(df$an, df$an, FUN=seq_along)))) 

ave wykonuje obliczenia grupowe i seq_along zlicza wiersze.

która zwraca

df 
    at  an   ap 
1 NDA 023356 N023356001 
2 ANDA 023357 A023357001 
3 ANDA 023357 A023357002 
4 NDA 023357 N023357003 
5 ANDA 023398 A023398001 
+0

OP wymienia "licznik na końcu, który zwiększa liczbę powtórzeń w kolumnie", a także grupuje według powtórzeń z ich pętlą, ale twoje podejście działa tylko z wartościami dla grupowania, a nie z powtórzeniami wartości. Prawdopodobnie ich dane są posortowane, a to, co tu mówię, nie ma dla nich znaczenia. – Frank

+1

@Frank Dzięki za heads up. Nie dostałem dodatkowej złożoności przy pierwszym czytaniu posta i nie ma go w tym przykładzie, ale w ten weekend przyjrzę się drugiemu spojrzeniu. – lmo

8

The rleid i rowid funkcji z data.table mogą być użyteczne tutaj:

# using df from @Florian's answer 
library(data.table) 
setDT(df) 

df[, v := paste0(
    substr(at, 1, 1), 
    an, 
    sprintf("%03.f", rowid(rleid(an))) 
)] 

#  at  an   v 
# 1: NDA 023356 N023356001 
# 2: ANDA 023357 A023357001 
# 3: ANDA 023357 A023357002 
# 4: NDA 023357 N023357003 
# 5: ANDA 023398 A023398001 

Jak to działa:

  • sprintf z bazy skutecznie wykonuje pracę z stringr::str_pad w OP.
  • rleid grupuje powtarzanie wartości razem.
  • rowid tworzy licznik w ramach każdej grupy.
Powiązane problemy