26

以下の長いパターンに従うデータ フレームがあります。

   Name          MedName
  Name1    atenolol 25mg
  Name1     aspirin 81mg
  Name1 sildenafil 100mg
  Name2    atenolol 50mg
  Name2   enalapril 20mg

以下に取得したいと思います(列にこの方法で名前を付けることができるかどうかは気にしません。データをこの形式にするだけです):

   Name   medication1    medication2      medication3
  Name1 atenolol 25mg   aspirin 81mg sildenafil 100mg
  Name2 atenolol 50mg enalapril 20mg             NA

このサイトを通じて、私は reshape/reshape2 パッケージに精通し、これを機能させるために何度か試みましたが、これまでのところ失敗しています。

試してみるdcast(dataframe, Name ~ MedName, value.var='MedName')と、薬名のフラグである一連の列が得られます(転置される値は1または0です)例:

 Name  atenolol 25mg  aspirin 81mg
Name1              1             1
Name2              0             0 

データセットを溶かした後も試しましたがdcast(dataset, Name ~ variable)、これは次のように吐き出します(各人が持っている薬の数を数えるだけです):

 Name  MedName
Name1        3
name2        2

最後に、データを溶かしてから、idvar="Name" timevar="variable"(すべて Mednames だけです) を使用して再形成しようとしましたが、idvar に複数の一致がある場合、再形成は最初の MedName だけを取得し、休み。

reshape または別の R 関数を使用してこれを行う方法を知っている人はいますか? 基本的にデータを分割して再貼り付けするために、いくつかの for ループと条件を使用して、これをより面倒な方法で行う方法があることを認識していますが、もっと簡単な解決策があることを望んでいました。どうもありがとう!

4

8 に答える 8

18

パッケージを使用すると、これは新しいrowid関数で簡単に解決できます。

library(data.table)
dcast(setDT(d1), 
      Name ~ rowid(Name, prefix = "medication"), 
      value.var = "MedName")

与える:

   Name    medication1     medication2       medication3
1 Name1  atenolol 25mg    aspirin 81mg  sildenafil 100mg
2 Name2  atenolol 50mg  enalapril 20mg              <NA>

別の方法 (バージョン 1.9.7 より前でよく使用されていた):

dcast(setDT(d1)[, rn := 1:.N, by = Name], 
      Name ~ paste0("medication",rn), 
      value.var = "MedName")

同じ結果が得られます。


同様のアプローチですが、現在はおよびパッケージを使用しています。

library(dplyr)
library(tidyr)
d1 %>%
  group_by(Name) %>%
  mutate(rn = paste0("medication",row_number())) %>%
  spread(rn, MedName)

与える:

Source: local data frame [2 x 4]
Groups: Name [2]

    Name   medication1    medication2      medication3
  (fctr)         (chr)          (chr)            (chr)
1  Name1 atenolol 25mg   aspirin 81mg sildenafil 100mg
2  Name2 atenolol 50mg enalapril 20mg               NA
于 2016-02-07T13:58:01.190 に答える
16

データがオブジェクトにあると仮定しますdataset:

library(plyr)
## Add a medication index
data_with_index <- ddply(dataset, .(Name), mutate, 
                         index = paste0('medication', 1:length(Name)))    
dcast(data_with_index, Name ~ index, value.var = 'MedName')

##    Name   medication1    medication2      medication3
## 1 Name1 atenolol 25mg   aspirin 81mg sildenafil 100mg
## 2 Name2 atenolol 50mg enalapril 20mg             <NA>
于 2012-07-04T05:36:12.273 に答える
15

timevarを使用する前に、常に一意のものを生成できますreshape。ここでは、各「名前」に「沿って」ave関数を適用するために使用します。seq_along

test <- data.frame(
Name=c(rep("name1",3),rep("name2",2)),
MedName=c("atenolol 25mg","aspirin 81mg","sildenafil 100mg",
          "atenolol 50mg","enalapril 20mg")
)

# generate the 'timevar'
test$uniqid <- with(test, ave(as.character(Name), Name, FUN = seq_along))

# reshape!
reshape(test, idvar = "Name", timevar = "uniqid", direction = "wide")

結果:

   Name     MedName.1      MedName.2        MedName.3
1 name1 atenolol 25mg   aspirin 81mg sildenafil 100mg
4 name2 atenolol 50mg enalapril 20mg             <NA>
于 2012-07-04T06:03:28.837 に答える
5

@thelatemail の解決策はこれに似ています。時間変数を生成するときは、rleインタラクティブに作業しておらず、Name変数を動的にする必要がある場合に使用します。

# start with your example data
x <- 
    data.frame(
        Name=c(rep("name1",3),rep("name2",2)),
        MedName=c("atenolol 25mg","aspirin 81mg","sildenafil 100mg",
            "atenolol 50mg","enalapril 20mg")
    )

# pick the id variable
id <- 'Name'

# sort the data.frame by that variable
x <- x[ order( x[ , id ] ) , ]

# construct a `time` variable on the fly
x$time <- unlist( lapply( rle( as.character( x[ , id ] ) )$lengths , seq_len ) )

# `reshape` uses that new `time` column by default
y <- reshape( x , idvar = id , direction = 'wide' )

# done
y
于 2014-08-13T06:55:39.177 に答える