2017-12-06 13 views
0

Rにデータフレームがあります。データフレームには複数の行と複数の列があります。 1つはトヨタ、ホンダなどの車両メーカーごとにカンマ区切りの値があります。コンマ区切りの値の頻度を計算し、各行の発生頻度の上位3つの値を出力します。ここで は、データ・セットは次のようになります:ここで列内のコンマで区切られたカテゴリの頻度カウント

Zip     Make 
12325 Toyota, Honda, Toyota, Mitsubishi, Mercedes 
85271 Toyota,Honda,Toyota,Honda,Toyota,Toyota,Volvo,Nissan,Nissan,Nissan, Nissan 
56098 Toyota,Honda,Toyota,Mitsubishi,Chevrolet,Acura,Chevrolet,Chevrolet, Honda 

私は

Output appended in the image

をしたいの出力は、誰もが一例に基づいて実際のRコードを支援することができますか?

+1

これは、これを行う方法はありません。あなたは、簡単に操作し分析を行うことができるように、あなたのデータをきちんとしたフォーマットにしたいと思っています。あなたのデータセットが現在のように分析する方法はありません。特にあなたが出てきたい方法です。 データセットの 'dput()'を最初に提供し、ここに投稿してください –

答えて

0

操作と集計を行う前に、データを整理しておく必要があります。

データセット:

df <- data.frame(Zip =c(12325, 85271, 56098), Make = c("Toyota,Honda,Toyota,Mitsubishi,Mercedes", "Toyota,Honda,Toyota,Honda,Toyota,Toyota,Volvo,Nissan,Nissan,Nissan,Nissan", "Toyota,Honda,Toyota,Mitsubishi,Chevrolet,Acura,Chevrolet,Chevrolet,Honda")) 

電源を入れ、我々はコンマで各列を分割

df$Make <- as.character(df$Make) 

インポートライブラリ

library(stringr) 
library(tidyverse) 

それを分割し、行列を作成することができるように文字にしてください異なるメイクのデータフレームに変換します。次に列に名前を付け、データフレームのZIP列を新しいクリーナーに割り当てます。

df2 <- as.data.frame(str_split_fixed(df$Make, ",", max(unlist(lapply(strsplit(df$Make, ","), length))))) 


names(df2) <- paste0("car_", 1:ncol(df2)) 

df2$zip <- df$Zip 

は点検:

> df2 
    car_1 car_2 car_3  car_4  car_5 car_6  car_7  car_8 car_9 car_10 car_11 zip 
1 Toyota Honda Toyota Mitsubishi Mercedes             12325 
2 Toyota Honda Toyota  Honda Toyota Toyota  Volvo Nissan Nissan Nissan Nissan 85271 
3 Toyota Honda Toyota Mitsubishi Chevrolet Acura Chevrolet Chevrolet Honda    56098 

今、私たちはそれを整理したいです。幅広いフォーマットから長いものに変換するために列を集めることができます。その後、空に置き換えてNAをフィルタリングします。作成した列carを削除します。その後、zipMakesummariseでグループ化し、それぞれMakeの数をzipで示します。最後に、番号順に並べます。私たちは

df3 <- df2 %>% 
    gather(car, Make, -zip) %>% 
    replace(. == "", NA) %>% 
    filter(!is.na(Make)) %>% 
    select(-car) %>% 
    group_by(zip, Make) %>% 
    summarise(number = n()) %>% 
    arrange(zip, desc(number)) 

最後は、私たちがtop3と呼ばれる新しいDFを作成することができ、そして我々は(zipMakeの)各グループからちょうど最初の3行をつかむために、それをスライスすることができます。降順に配置しているので、このデータフレームでトップ3の郵便番号を取得します。

top3 <- df3 %>% 
    slice(1:3) 
1

のスクリーンショットのように、あなたは、出力形式を主張する場合は、ここでは基本R溶液(追加なしRライブラリ)である:すべての

df <- read.table(text = 
    "Zip Make 
    12325 Toyota,Honda,Toyota,Mitsubishi,Mercedes 
    85271 Toyota,Honda,Toyota,Honda,Toyota,Toyota,Volvo,Nissan,Nissan,Nissan,Nissan 
    56098 Toyota,Honda,Toyota,Mitsubishi,Chevrolet,Acura,Chevrolet,Chevrolet,Honda", 
    header = T, stringsAsFactors = F) 

df$Frequency <- sapply(lapply(strsplit(df$Make, ","), function(x) 
    paste0(apply(as.data.frame(table(x)), 1, paste, collapse = "("), ")")), 
    paste, collapse = ","); 

df$top <- sapply(lapply(strsplit(df$Make, ","), function(x) 
    names(table(x)[order(-table(x))][1:3])), 
    paste, collapse = ","); 

df; 
# Zip 
#1 12325 
#2 85271 
#3 56098 
#                  Make 
#1         Toyota,Honda,Toyota,Mitsubishi,Mercedes 
#2 Toyota,Honda,Toyota,Honda,Toyota,Toyota,Volvo,Nissan,Nissan,Nissan,Nissan 
#3 Toyota,Honda,Toyota,Mitsubishi,Chevrolet,Acura,Chevrolet,Chevrolet,Honda 
#            Frequency     top 
#1   Honda(1),Mercedes(1),Mitsubishi(1),Toyota(2) Toyota,Honda,Mercedes 
#2     Honda(2),Nissan(4),Toyota(4),Volvo(1) Nissan,Toyota,Honda 
#3 Acura(1),Chevrolet(3),Honda(2),Mitsubishi(1),Toyota(2) Chevrolet,Honda,Toyota 
+0

最後の列を除いて同じ結果が得られました。私はOPがすべてトップ3を維持したいと思うので、テーブルの出力をスライスするだけでは十分ではないかもしれません。 – www

+0

@wwwはい、そうです。ネクタイを扱うことはもう少し作業です。コードシンプルさとOPの正確な予想出力を再現するために、コーナーを切りました。 –

+0

私は素晴らしいソリューションを提供してくれたと思います。コードシンプルさを維持することが重要であることに同意します。 – www

0

まず、@Mattのコメントを考えるにはW.より適切な方法でデータフレームを編成することについては、通常、セル内のリストを持つことが悪い設計の症状です。

# iterate over all the cells in the Make column of the dataframe 
top3 <- unlist(lapply(df$Make, function(cell) { 
    # convert the cell string to a vector 
    cars <- unlist(strsplit(cell, ',')) 
    # count how many of each different type are 
    carFreq <- unlist(lapply(unique(cars), function(c) sum(c == cars))) 
    # fix the name of carFreq 
    names(carFreq) <- unique(cars) 
    # return a string with the top 3 
    paste0(names(sort(carFreq, decreasing = TRUE)[1:3]), collapse = ', ') 
})) 

# finally put the extra column in the data frame  
df <- cbind(df, top3) 

ライブラリの必要はありません。

にもかかわらず、のは、あなたのデータフレームは、その後、DFであると仮定しましょう。

+1

ありがとうございます。私は実際にsqldfパッケージを使用しても解決できました。私の最後からコードを追加する: – user9063838

0

tidyverseを使用する溶液。 dt_finalが最終出力です。

library(tidyverse) 

# Separate the comma 
dt2 <- dt %>% separate_rows(Make) 

# Calculate the frequency 
dt3 <- dt2 %>% count(Zip, Make) 

# Prepare the Frequency column 
dt4 <- dt3 %>% 
    mutate(n = paste0("(", n, ")")) %>% 
    unite(Frequency, Make, n, sep = " ") %>% 
    group_by(Zip) %>% 
    summarise(Frequency = paste0(Frequency, collapse = ", ")) 

# Prepare the Top 3 Make column 
dt5 <- dt3 %>% 
    group_by(Zip) %>% 
    mutate(Rank = dense_rank(n)) %>% 
    filter(Rank <= 3) %>% 
    arrange(Zip, Rank, Make) %>% 
    select(Zip, Make) %>% 
    summarise(`Top 3 Make (per frequency)` = paste0(Make, collapse = ", ")) 

# Join the results 
dt_final <- reduce(list(dt, dt4, dt5), left_join, by = "Zip") 

dt_final 
#  Zip                  Make 
# 1 12325        Toyota, Honda, Toyota, Mitsubishi, Mercedes 
# 2 85271 Toyota,Honda,Toyota,Honda,Toyota,Toyota,Volvo,Nissan,Nissan,Nissan, Nissan 
# 3 56098 Toyota,Honda,Toyota,Mitsubishi,Chevrolet,Acura,Chevrolet,Chevrolet, Honda 
#               Frequency 
# 1    Honda (1), Mercedes (1), Mitsubishi (1), Toyota (2) 
# 2     Honda (2), Nissan (4), Toyota (4), Volvo (1) 
# 3 Acura (1), Chevrolet (3), Honda (2), Mitsubishi (1), Toyota (2) 
#     Top 3 Make (per frequency) 
# 1   Honda, Mercedes, Mitsubishi, Toyota 
# 2    Volvo, Honda, Nissan, Toyota 
# 3 Acura, Mitsubishi, Honda, Toyota, Chevrolet 

DATA

dt <- read.table(text = "Zip     Make 
12325 'Toyota, Honda, Toyota, Mitsubishi, Mercedes' 
       85271 'Toyota,Honda,Toyota,Honda,Toyota,Toyota,Volvo,Nissan,Nissan,Nissan, Nissan' 
       56098 'Toyota,Honda,Toyota,Mitsubishi,Chevrolet,Acura,Chevrolet,Chevrolet, Honda'", 
       header = TRUE, stringsAsFactors = FALSE) 
0

答えを共有するありがとうございました。私は実際にsqldfパッケージを使用して私の目的のためにもそれを解決することができました。 BB2はzipと連結された列を含む元のデータセットです。 strsplit(BB2 $ MakeConcat、スプリット= "")
ビュー(BB2)
D2 < - - sapply data.frame(ジップ=担当者(BB2 $ジッパー、(ここでコード

D1 <ですD1、長さ))、MakeConcat =非公開に(D1))
ビュー(D2)
D3 < - sqldf( "ZIPを選択し、ジップDESCにより、ジッパーによってD2群からCOUNT2、MakeConcatとしてMakeConcat順序を(MakeConcat)をカウント" )
ビュー(D3)
D4 < - mydf [order(D3 $ count2、D3 $ zip、decreing = TRUE)、]
D4 < - D3 [順序(D3 $ COUNT2、D3 $ジッパー、減少= TRUE)]
D4_x < - D4 [AVE(D4の$カウント、D4 $ジッパー、FUN = seq_along)< = 3]
ビュー(D4_x)
決勝< - sqldf( "ZIPによるD4_xグループからMakeConcatとしてSELECTジップ、アッパー(GROUP_CONCAT(MakeConcat))")

+0

各行を4つ分だけインデントすると、SOがこれをフォーマットします。 –

関連する問題