data.frame中的子集非0值

时间:2013-09-11 12:36:42

标签: r

我有一个如下所示的data.frame(DF):

 Col_names1      Col_values1    Col_names2     Col_values2    
     a                98             f               1           
     b                12             h              0.8         
     d                 0             mn              0            
     e               0.12            p               0                 
    ....             ....           ....            ....

我必须逐行列出每个Col_names列中Col_names的频率。首先,我只提取名称以获得以下new_DF

 Col_names1       Col_names2     
     a                f                
     b                h                 
     d                mn                  
     e                p                    
    ....             ....           

然后我使用apply函数逐行表示名称的频率:

apl = apply(new_DF, 1, table)

问题在于,即使在(例如“d”)初始DF中的相关数值为“0”时,它也给出了名称的频率。不计算这个频率。

PS:data.frame总共有500列和80行。

2 个答案:

答案 0 :(得分:1)

这种方法对你有用吗?

set.seed(1)
example <- data.frame(col_names1=sample(letters[1:13],30,replace=TRUE),
                      col_values1=sample(0:10,30,replace=TRUE),
                      col_names2=sample(letters[14:26],30,replace=TRUE),
                      values2=sample(0:10,30,replace=TRUE))
> dim(example)
[1] 30  4
> head(example)
  col_names1 col_values1 col_names2 values2
1          d           5          y       2
2          e           6          q       0
3          h           5          s       7
4          l           2          r       9
5          c           9          v       8
6          l           7          q       8


new.df <- data.frame(names=unlist(example[,grep("names",colnames(example))]),
                     values=unlist(example[,grep("values",colnames(example))]))

> dim(new.df)
[1] 60  2
> head(new.df)
            names values
col_names11     d      5
col_names12     e      6
col_names13     h      5
col_names14     l      2
col_names15     c      9
col_names16     l      7

然后您可以根据一列删除值。

new.df[new.df$values!=0,]

答案 1 :(得分:1)

一个选项是使用list(但我认为在这种情况下长数据形式可能更方便,而且您的数据不是很大)。

假设您的data.frame被称为“mydf”:

## Create a matrix to subset each pair of columns
mat <- matrix(1:4, ncol = 2, byrow = TRUE)

## use `lapply` to subset and remove the offensive rows
lapply(sequence(nrow(mat)), function(x) {
  temp <- mydf[mat[x, ]]
  temp[temp[2] != 0, ]
})
# [[1]]
#   Col_names1 Col_values1
# 1          a       98.00
# 2          b       12.00
# 4          e        0.12
# 
# [[2]]
#   Col_names2 Col_values2
# 1          f         1.0
# 2          h         0.8

在@ dayne的答案的基础上,如果你的列以常规模式命名,你可以非常有效地使用reshape来获得长格式。但是,它需要一个“id”变量(sequence(nrow(DF))应该这样做。)

示例:

### Sample data
set.seed(1)
DF <- data.frame(col_names1 = sample(letters[1:13], 30, replace=TRUE),
                 col_values1 = sample(0:10, 30, replace=TRUE),
                 col_names2 = sample(letters[14:26], 30, replace=TRUE),
                 col_values2 = sample(0:10, 30, replace=TRUE))

### Add the ID
DF <- cbind(id = 1:nrow(DF), DF)

### Reshape the data into a long form
out <- reshape(DF, direction = "long", idvar="id", 
               varying = setdiff(names(DF), "id"), sep = "")

### Subset
out2 <- out[out$col_values != 0, ]
head(out2)
#     id time col_names col_values
# 1.1  1    1         d          5
# 2.1  2    1         e          6
# 3.1  3    1         h          5
# 4.1  4    1         l          2
# 5.1  5    1         c          9
# 6.1  6    1         l          7