簡體   English   中英

使用因子列制作更寬的 dataframe

[英]making a wider dataframe using factor columns

好的,所以這個有點長,我有幾個巨大的數據框,我試圖擴大它們並最終合並。 我想按年份和縣合並和分組。

我有幾個專欄,其中包含我試圖傳播的因素。 本質上,我想采用因子 x、y、z 並將它們設為列、x、y 和 z。 我在下面有一個例子 此外,我有幾列數字,我想按組求和。

我試圖提供一個示例和一些可重現的代碼,希望這些就足夠了,但是如果我能做些什么來讓事情變得更容易/更清晰,請告訴我,非常感謝你的幫助!

 YR<-as.factor( c(2019,2018,2019,2019,2018,2018,2019,2019,2018))
    STATE<-as.factor( c("CA","MA","KY","KY","CA","MA","KY","KY","CA"))
    COUNTY<-as.factor( c("C1","M1","K1","K2","C1","M2","K1","K2","C1"))
    CANCER<-as.factor(c("Cervical","Lung","Prostate","Breast","Cervical","Breast","Prostate","Prostate","Lung"))
    rand_fact<-as.factor(c("rf1","rf2","rf3","fr4","fr5","rf2","rf3","fr4","fr5"))
    rand_num<-as.numeric(c(4,3,5,7,3,5,3,24,9))
    rand_chr<-as.character(c("a","d","r","e","g","y","r","e","k"))
    TEST_DR<-data.frame(YR,STATE,COUNTY,CANCER,rand_fact,rand_num,rand_chr)
    rm(YR,STATE,COUNTY,CANCER,rand_chr,rand_num,rand_fact)
    > print(TEST_DR)
        YR STATE COUNTY   CANCER rand_fact rand_num rand_chr
    1 2018    CA     C1 Cervical       fr5        3        g
    2 2018    CA     C1     Lung       fr5        9        k
    3 2018    MA     M1     Lung       rf2        3        d
    4 2018    MA     M2   Breast       rf2        5        y
    5 2019    CA     C1 Cervical       rf1        4        a
    6 2019    KY     K1 Prostate       rf3        5        r
    7 2019    KY     K1 Prostate       rf3        3        r
    8 2019    KY     K2   Breast       fr4        7        e
    9 2019    KY     K2 Prostate       fr4       24        e
    

#Idealy the output will look like below with rows grouped by YR then COUNTY

    TEST_DR<-arrange(.data = TEST_DR,YR,COUNTY)
    YR<-as.factor( c(2018,2018,2018,2019,2019,2019))
    STATE<-as.factor( c("CA","MA","MA","CA","KY","KY"))
    COUNTY<-as.factor( c("C1","M1","M2","C1","K1","K2"))
    Cervical<-as.numeric(c(1,0,0,1,0,0))
    Lung <-as.numeric(c(1,1,0,0,0,0))
    Prostate<-as.numeric(c(0,0,0,0,2,1))
    Breast<-as.numeric(c(0,0,1,0,0,1))
    
    TEST_DR2 <-data.frame(YR,STATE,COUNTY,Cervical,Lung,Prostate,Breast)
    rm(YR,STATE,COUNTY,Cervical,Lung,Prostate,Breast)
    > print(TEST_DR2)

        YR STATE COUNTY Cervical Lung Prostate Breast rand_num
    1 2018    CA     C1        1    1        0      0       12
    2 2018    MA     M1        0    1        0      0        3
    3 2018    MA     M2        0    0        0      1        5
    4 2019    CA     C1        1    0        0      0        4
    5 2019    KY     K1        0    0        2      0        8
    6 2019    KY     K2        0    0        1      1       31

這是一種使用count()和 {tidyr} spread()的方法

YR <- as.factor( c(2019,2018,2019,2019,2018,2018,2019,2019,2018))
STATE <- as.factor( c("CA","MA","KY","KY","CA","MA","KY","KY","CA"))
COUNTY <- as.factor( c("C1","M1","K1","K2","C1","M2","K1","K2","C1"))
CANCER <- as.factor(c("Cervical","Lung","Prostate","Breast","Cervical","Breast","Prostate","Prostate","Lung"))
rand_fact <- as.factor(c("rf1","rf2","rf3","fr4","fr5","rf2","rf3","fr4","fr5"))
rand_num <- as.numeric(c(4,3,5,7,3,5,3,24,9))
rand_chr <- as.character(c("a","d","r","e","g","y","r","e","k"))
TEST_DR <- data.frame(YR, STATE, COUNTY, CANCER, rand_fact, rand_num, rand_chr)
rm(YR,STATE,COUNTY,CANCER,rand_chr,rand_num,rand_fact)

library(dplyr, warn.conflicts = FALSE)
library(tidyr)

TEST_DR %>% 
  group_by(YR, STATE, COUNTY) %>%
  count(CANCER, rand_num = sum(rand_num)) %>%
  spread(CANCER, n, fill = 0)
#> # A tibble: 6 x 8
#> # Groups:   YR, STATE, COUNTY [6]
#>   YR    STATE COUNTY rand_num Breast Cervical  Lung Prostate
#>   <fct> <fct> <fct>     <dbl>  <dbl>    <dbl> <dbl>    <dbl>
#> 1 2018  CA    C1           12      0        1     1        0
#> 2 2018  MA    M1            3      0        0     1        0
#> 3 2018  MA    M2            5      1        0     0        0
#> 4 2019  CA    C1            4      0        1     0        0
#> 5 2019  KY    K1            8      0        0     0        2
#> 6 2019  KY    K2           31      1        0     0        1

reprex package (v0.3.0) 創建於 2020-12-02

對於最新的 {tidyverse} 語法糖......

TEST_DR %>% 
  group_by(YR, STATE, COUNTY) %>%
  count(CANCER, rand_num = sum(rand_num)) %>%
  pivot_wider(names_from = CANCER, values_from = n, values_fill = 0)

除了必須聚合rand_num列之外,您幾乎可以直接在其上使用dcast 以下是我將如何處理它:

library(data.table)
# Create a vector of keys that we can use for grouping and for 
# identifying the columns for the left-hand-side of the dcast formula
keys <- c("YR", "STATE", "COUNTY")
# * melt from data.table expects a data.table, so use either setDT or
#   as.data.table to convert your data.frame to a data.table
# * .N creates a count by the grouping variables. CANCER has been
#   added since we want to count the number of instances. It will
#   create a new column named "N" in the data
as.data.table(TEST_DR)[, list(rand_num, .N), c(keys, "CANCER")][
  # Sum the rand_num variable by the grouping variable
  , rand_num := sum(rand_num), keys][
    # Go from long to wide using dcast. 
    # * ... on the left-hand-side of the formula says to use all
    #   of the unspecified variables
    # * ~ CANCER says that the values from the CANCER column should
    #   become the new column names
    # * value.var = "N" says to fill in the combination of LHS and
    #   RHS with values from the N column
    , dcast(.SD, ... ~ CANCER, value.var = "N")]
#      YR STATE COUNTY rand_num Breast Cervical Lung Prostate
# 1: 2018    CA     C1       12      0        1    1        0
# 2: 2018    MA     M1        3      0        0    1        0
# 3: 2018    MA     M2        5      1        0    0        0
# 4: 2019    CA     C1        4      0        1    0        0
# 5: 2019    KY     K1        8      0        0    0        2
# 6: 2019    KY     K2       31      1        0    0        1

“data.table”命令可以通過將一個操作的結果傳遞給下一個操作來鏈接(類似於使用管道)。 例如, as.data.table(df)[, do_something][, do_something_else][, do_even_more]

暫無
暫無

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

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