2

データ フレーム内の 1 つの長い行として取得した人の可変リストがあり、これらのレコードをより意味のある形式に再編成することに関心があります。

私の生データは次のようになります。

df <- data.frame(name1 = "John Doe", email1 = "John@Doe.com", phone1 = "(444) 444-4444", name2 = "Jane Doe", email2 = "Jane@Doe.com", phone2 = "(444) 444-4445", name3 = "John Smith", email3 = "John@Smith.com", phone3 = "(444) 444-4446", name4 = NA, email4 = "Jane@Smith.com", phone4 = NA, name5 = NA, email5 = NA, phone5 = NA)
df
#     name1       email1         phone1    name2       email2         phone2
# 1 John Doe John@Doe.com (444) 444-4444 Jane Doe Jane@Doe.com (444) 444-4445
#       name3         email3         phone3 name4         email4 phone4 name5
# 1 John Smith John@Smith.com (444) 444-4446    NA Jane@Smith.com     NA    NA
#  email5 phone5
# 1     NA     NA    

私はそれをこのような形式に曲げようとしています。

df_transform <- structure(list(name = structure(c(2L, 1L, 3L, NA, NA), .Label = c("Jane Doe", 
"John Doe", "John Smith"), class = "factor"), email = structure(c(3L, 
1L, 4L, 2L, NA), .Label = c("Jane@Doe.com", "Jane@Smith.com", 
"John@Doe.com", "John@Smith.com"), class = "factor"), phone = structure(c(1L, 
2L, 3L, NA, NA), .Label = c("(444) 444-4444", "(444) 444-4445", 
"(444) 444-4446"), class = "factor")), .Names = c("name", "email", 
"phone"), class = "data.frame", row.names = c(NA, -5L))
 df_transform
#         name          email          phone
# 1   John Doe   John@Doe.com (444) 444-4444
# 2   Jane Doe   Jane@Doe.com (444) 444-4445
# 3 John Smith John@Smith.com (444) 444-4446
# 4       <NA> Jane@Smith.com           <NA>
# 5       <NA>           <NA>           <NA>

reshape2常に 5 レコードであるとは限らず、1 から 99 までの任意の数になる可能性があることを付け加えておく必要がありますmelt。私が単に知らない知っている方法があると思います。

4

2 に答える 2

3

あなたは正しい軌道に乗っています、これを試してください:

library(reshape2)

# melt it down
df.melted = melt(t(df))
# get rid of the numbers at the end
df.melted$Var1 = sub('[0-9]+$', '', df.melted$Var1)

# cast it back
dcast(df.melted, (seq_len(nrow(df.melted)) - 1) %/% 3 ~ Var1)[,-1]
#           email       name          phone
#1   John@Doe.com   John Doe (444) 444-4444
#2   Jane@Doe.com   Jane Doe (444) 444-4445
#3 John@Smith.com John Smith (444) 444-4446
#4 Jane@Smith.com       <NA>           <NA>
#5           <NA>       <NA>           <NA>
于 2013-05-24T16:29:13.577 に答える
2

1) reshape()最初に、列名から数字を取り除き、短縮された列名names0. 次に、列を生成するグループに分割します(これには、と列グループgに対応する 3 つのコンポーネントがあります)。次に、(R のベースから) を使用してワイドからロングへの変換を実行し、結果の長いデータ フレームから目的の列を選択して、によって自動的に追加される列を除外します。その選択ベクトルは、結果の列を目的の方法で並べ替えるようなものです。emailnamephonereshapereshapeunique(names0)

names0 <- sub("\\d+$", "", names(df))
g <- split(names(df), names0)
reshape(df, dir = "long", varying = g, v.names = names(g))[unique(names0)]

そして最後の行はこれを与えます:

          name          email          phone
1.1   John Doe   John@Doe.com (444) 444-4444
1.2   Jane Doe   Jane@Doe.com (444) 444-4445
1.3 John Smith John@Smith.com (444) 444-4446
1.4       <NA> Jane@Smith.com           <NA>
1.5       <NA>           <NA>           <NA>

2) reshape2 パッケージ reshape2を使用したソリューションを次に示します。長い形式にrownamedfを追加します。melt次に、variable列を名前部分 ( name, email, phone) と数値サフィックス部分 ( と呼びます)に分割しますid。最後に、以前と同様に、 を使用してワイド フォームに変換dcastし、適切な列を選択します。

library(reshape2)

m <- melt(data.frame(rowname = 1:nrow(df), df), id = 1)
mt <- transform(m, 
   variable = sub("\\d+$", "", variable), 
   id = sub("^\\D+", "", variable)
)
dcast(mt, rowname + id ~ variable)[, unique(mt$variable)]

最後の行はこれを与えます:

        name          email          phone
1   John Doe   John@Doe.com (444) 444-4444
2   Jane Doe   Jane@Doe.com (444) 444-4445
3 John Smith John@Smith.com (444) 444-4446
4       <NA> Jane@Smith.com           <NA>
5       <NA>           <NA>           <NA>

3)単純なマトリックスの再形成。列名から数字のサフィックスを削除cnし、一意の残りの名前に設定します。(cn列名を表します)。次にdf、列名を追加して行を nx length(cn) 行列に再形成するだけです。

cn <- unique(sub("\\d+$", "", names(df)))
matrix(as.matrix(df), nc = length(cn), byrow = TRUE, dimnames = list(NULL, cn))

     name         email            phone           
[1,] "John Doe"   "John@Doe.com"   "(444) 444-4444"
[2,] "Jane Doe"   "Jane@Doe.com"   "(444) 444-4445"
[3,] "John Smith" "John@Smith.com" "(444) 444-4446"
[4,] NA           "Jane@Smith.com" NA              
[5,] NA           NA               NA    

4) tapplyこの問題も単純な で解決できますtapply。前names0と同じように、数値接尾辞のない列名です。 names.suffix接尾辞だけです。今使用tapply

names0 <- sub("\\d+$", "", names(df))
names.suffix <- sub("^\\D+", "", names(df))
tapply(as.matrix(df), list(names.suffix, names0), c)[, unique(names0)]

最後の行は次のとおりです。

  name         email            phone           
1 "John Doe"   "John@Doe.com"   "(444) 444-4444"
2 "Jane Doe"   "Jane@Doe.com"   "(444) 444-4445"
3 "John Smith" "John@Smith.com" "(444) 444-4446"
4 NA           "Jane@Smith.com" NA              
5 NA           NA               NA 
于 2013-05-24T17:25:33.543 に答える