2017-09-03 14 views
1

데이터 프레임이 있고 두 개의 열에서 양방향 비상 계획 테이블을 출력하고 싶습니다. 그들은 둘 다 "너무 적다", "적당하다"또는 "너무 많이"라는 가치를 가지고 있습니다.양방향 우연 테이블 R

내가 따로 둘 다에 대한

df %>% 
    filter(!is.na(col1)) %>% 
    group_by(col1) %>% 
    summarise(count = n()) 

를 입력하고이 같은 것을 얻을 해요 :

 Too Little About Right Too Much Total 
col1 19259  9539   2816  31614 
col2 20619  9374   2262  32255 
Total 39878  18913   5078  63869 

I :

col1  count 
<fctr>  <int> 
Too Little 19259   
About Right 9539    
Too Much 2816  

는 내가 달성하고자하는 것은 이것이다 테이블 함수를 사용하려고 시도했습니다.

addmargins(table(df$col1, df$col2)) 

는하지만 결과는 내가

   Too Little About Right Too Much Sum 
    Too Little  13770  4424  740 18934 
    About Right  4901  3706  700 9307 
    Too Much   1250   800  679 2729 
    Sum    19921  8930  2119 30970 
+0

그래서 당신이 – Wen

+1

안녕 환영 SO에 원하는 넣어 것으로 예상된다 무엇, 그것은 (A [mimimal하지만 완전한]에서 질문을하는 것이 중요합니다 https://stackoverflow.com/help/ mcve) 양식. 또한 항상 예제 데이터를 포함하려고 시도하십시오. (지금 당장은 아무도 없지만'df'를 볼 수 있습니다.) 아마도 최소한의 예제만으로도 충분할 것입니다. – Nate

답변

3

내가 (?tabulate 참조) table의 기초입니다 시도, tabulate 줄 것 원하는 것을하지 않습니다. 다음

set.seed(123) 
vals <- LETTERS[1:3] 
df <- as.data.frame(replicate(3, sample(vals, 5, T))) 
df <- data.frame(lapply(df, "levels<-", vals)) 

을 부여 예를 들어, 당신은

m <- t(sapply(df, tabulate, nbins = length(vals))) 
colnames(m) <- vals 
addmargins(m) 
#  A B C Sum 
# V1 1 1 3 5 
# V2 1 3 1 5 
# V3 1 2 2 5 
# Sum 3 6 6 15 

또는 (@thelatemail를 통해)을 할 수있는 단지

addmargins(t(sapply(df, table))) 
#  A B C Sum 
# V1 1 1 3 5 
# V2 1 3 1 5 
# V3 1 2 2 5 
# Sum 3 6 6 15 
우리는 다음 rbind 루프에서 테이블을 사용할 수
+1

왜 특별히'tabulate'가 필요한지 모르겠습니다. – thelatemail

+0

@thelatemail 사실, 고마워. 내가 추가 했어. (zx8754의 해결책과 너무 비슷할 지 모르지만 ...) – lukeA

+0

아니,'sapply '하는 것은 목록을 만드는 것보다 간단하다 – thelatemail

2

:

# Using dummy data from @lukeA's answer 

addmargins(do.call(rbind, lapply(df1, table))) 
#  A B C Sum 
# V1 1 1 3 5 
# V2 1 3 1 5 
# V3 1 2 2 5 
# Sum 3 6 6 15 

벤치마킹

# bigger data 
set.seed(123) 
vals <- LETTERS[1:20] 
df1 <- as.data.frame(replicate(20, sample(vals, 100000, T))) 
df1 <- data.frame(lapply(df1, "levels<-", vals)) 


microbenchmark::microbenchmark(
    lukeA = { 
    m1 <- t(sapply(df1, tabulate, nbins = length(vals))) 
    colnames(m1) <- vals 
    m1 <- addmargins(m1) 
    }, 
    # as vals only used for luke's solution, keep it in. 
    lukeA_1 = { 
    vals <- LETTERS[1:20] 
    m2 <- t(sapply(df1, tabulate, nbins = length(vals))) 
    colnames(m2) <- vals 
    m2 <- addmargins(m2) 
    }, 
    thelatemail = {m3 <- addmargins(t(sapply(df1, table)))}, 
    zx8754 = {m4 <- addmargins(do.call(rbind, lapply(df1, table)))} 
) 
# Unit: milliseconds 
#  expr  min  lq  mean median  uq  max neval 
#  lukeA 2.349969 2.371922 2.518447 2.473839 2.558653 3.363738 100 
#  lukeA_1 2.351680 2.377196 2.523473 2.473839 2.542831 3.459242 100 
# thelatemail 38.316506 42.054136 43.785777 42.674912 44.234193 90.287809 100 
#  zx8754 38.695101 41.979728 44.933602 42.762006 44.244314 110.834292 100 
+1

벤치 마크는 vals '항상 미리 알 수있는 것은 아니기 때문에 (적어도 적어도 알려진 것으로 가정해서는 안됩니다.) 따라서 vals <- unique (df1 [, 1)']도 척해야합니다 – thelatemail

+0

@ thelatemail 사실, 아마도 'vals <- unique (unlist (df1))'이어야하지만, OP의 예제에서, 그들은 미리 값을 알고 있습니다. – zx8754