R:每行只选择一个符合特定条件的元素

时间:2015-10-14 13:20:32

标签: r select dataframe

我有data frame看起来像这样

x <- data.frame("a.1" = c(NA, NA, 101, 101, NA),
                "a.2" = c(NA, NA, 101, NA, NA),
                "a.3" = c(101, NA, NA, NA, 103),
                "a.4" = c(NA, NA , NA, NA, 103))

每行包含NA&和/或某些10x值。该值对于每一行是唯一的,因此一行不能包含例如同时101103

现在我想创建一个包含每行中找到的值的列,无论它是出现一次还是多次。只有NA的每一行也应该有NA。在我的情况下,这应该是这样的

   new column
1  101
2  NA
3  101
4  101
5  103

知道如何以有效的方式实现这一目标!我的orginial数据框非常大,所以我想避免计算成本高昂的for - 循环和模糊的ifelse语句。

提前致谢

修改

@krun指出,使用rowMeans()是一个非常好的解决方案。但是,在我的原始数据集中,值101,102 ......实际上是表示某个行业的字符串。当然,我可以通过as.numeric转换它们,但我有一些带有前导零的行业指标,例如0130201等。这些零在转换为数字时会被杀死(逻辑上)因此我无法转换它们。

在这种情况下该怎么办?

2 个答案:

答案 0 :(得分:4)

我们可以使用pmax

 x$newcolumn <- do.call(pmax, c(x, list(na.rm=TRUE)))
 x$newcolumn
 #[1] 101  NA 101 101 103

或者另一个选项是rowMeans,因为一行中只有一个唯一元素。

rowMeans(x, na.rm=TRUE)

更新

如果列为character类且不想转换为numeric,则一个选项为max.col

x1[cbind(1:nrow(x1),max.col(!is.na(x1), 'first'))]
#[1] "012" NA    "012" "011" "011"

pmax方法也应该有用

do.call(pmax, c(x1, na.rm=TRUE))
#[1] "012" NA    "012" "011" "011"

数据

x1 <- data.frame(a.1 = c(NA, NA, '012', '011', NA),
            a.2 = c(NA, NA, '012', NA, NA),
            a.3 = c('012', NA, NA, NA, '011'),
            a.4 = c(NA, NA , NA, NA, '011'), stringsAsFactors=FALSE)

答案 1 :(得分:1)

好的,我找到了一个使用applylapply和`ifelse``声明的解决方案...不像我想的那样干净但是它的速度相当快而且有效

 x1 <- data.frame(a.1 = c(NA, NA, '012', '011', NA),
        a.2 = c(NA, NA, '012', NA, NA),
        a.3 = c('012', NA, NA, NA, '011'),
        a.4 = c(NA, NA , NA, NA, '011'), stringsAsFactors=FALSE)

new.column  <- x1 %>% 
   apply(1, function(i) unique(i[!is.na(i)])) %>% 
   lapply(function(i) ifelse(length(i) == 0, NA, i)) %>% 
   unlist()