删除包含或不包含NAs的常量列

时间:2018-01-14 20:12:14

标签: r data.table

我试图在函数中使用许多lm个模型,我需要从data.table中自动删除常量列。因此,我希望仅保留包含两个或更多唯一值的列,不包括计数中的NA

我在SO上尝试了几种方法,但我仍然无法删除具有两个值的列:常量和NAs。

我的可重复代码:

library(data.table)
df <- data.table(x=c(1,2,3,NA,5), y=c(1,1,NA,NA,NA),z=c(NA,NA,NA,NA,NA), 
d=c(2,2,2,2,2))

> df
    x  y  z d
1:  1  1 NA 2
2:  2  1 NA 2
3:  3 NA NA 2
4: NA NA NA 2
5:  5 NA NA 2

我的目的是删除y,z和d列,因为它们是常量,包括在省略NA时只有一个唯一值的y。

我试过了:

same <- sapply(df, function(.col){ all(is.na(.col))  || all(.col[1L] == .col)})
df1 <- df[ , !same, with = FALSE]


> df1
    x  y
1:  1  1
2:  2  1
3:  3 NA
4: NA NA
5:  5 NA

如图所示,&#39; y&#39;还在那里...... 有什么帮助吗?

8 个答案:

答案 0 :(得分:8)

因为您有data.table,所以可以使用uniqueN及其na.rm参数:

df[ , lapply(.SD, function(v) if(uniqueN(v, na.rm = TRUE) > 1) v)]
#     x
# 1:  1
# 2:  2
# 3:  3
# 4: NA
# 5:  5

base替代方案可以是Filter(function(x) length(unique(x[!is.na(x)])) > 1, df)

答案 1 :(得分:3)

基础Filter中有一个功能r的简单解决方案。它会有所帮助。

library(data.table)
df <- data.table(x=c(1,2,3,NA,5), y=c(1,1,NA,NA,NA),z=c(NA,NA,NA,NA,NA), 
                 d=c(2,2,2,2,2))
# Select only columns for which SD is not 0
> Filter(function(x) sd(x, na.rm = TRUE) != 0, df)
    x
1:  1
2:  2
3:  3
4: NA
5:  5

注意:不要忘记使用na.rm = TRUE

答案 2 :(得分:1)

这是一个选项:

df[,which(df[,
       unlist(
        sapply(.SD,function(x) length(unique(x[!is.na(x)])) >1))]),
   with=FALSE]

    x
1:  1
2:  2
3:  3
4: NA
5:  5

对于 data.table 的每一列,我们计算不同NA的唯一值的数量。我们只保留具有多个值的列。

答案 3 :(得分:1)

检查方差是否为零:


pip install mysqlclient.whl

答案 4 :(得分:0)

只需更改

Map[Node,(Node,Node)]

all(is.na(.col)) || all(.col[1L] == .col)

最终代码:

all(is.na(.col) | .col[1L] == .col)

结果:

same <- sapply( df, function(.col){ all( is.na(.col) | .col[1L] == .col ) } )
df1 <- df[,!same, with=F]

答案 5 :(得分:0)

要删除constant列,

  1. 数字列: -

    constant_col = [const for const in df.columns if df[const].std() == 0]
    print (len(constant_col))
    print (constant_col)
    
  2. 分类栏: -

    constant_col = [const for const in df.columns if len(df[const].unique()) == 1]
    print (len(constant_col))
    print (constant_col)
    
  3. 然后使用drop方法删除列

答案 6 :(得分:0)

library(janitor)
df %>%
  remove_constant(na.rm = TRUE)

    x
1:  1
2:  2
3:  3
4: NA
5:  5

答案 7 :(得分:-1)

如果你的意思是DROPing这些列,这是一个解决方案:

  <tbody data-bind="foreach: policies">
            <tr>
                <td><input type="checkbox" data-bind="checked: queued" /></td>
                <td data-bind="text: policy_number"></td>
                <td data-bind="text: policy_type"></td>
                <td data-bind="text: contact.first"></td>
                <td data-bind="text: contact.last"></td>
                <td data-bind="text: contact.street"></td>
                <td data-bind="text: contact.city"></td>
                <td data-bind="text: contact.state"></td>
                <td data-bind="text: contact.zipcode"></td>
                <td data-bind="text: contact.phonenumber"></td>
            </tr>
        </tbody>
    </table>
    <a data-bind="visible: queued" class="btn btn-lg btn-primary btn-block">Generate</a>
     <!--class="clickable" data-bind="click: generate"-->
    <script type="text/javascript">
    /* global ko, $ */
    function Policy(data) {
        var self = this;
        Object.keys(data).forEach(function(prop) {
            self[prop] = data[prop];
        });

        self.generate = function() {
            window.open("{{ url_for('genreport') }}/" + qvm.letter() + '/' + self.id);
        }

    }


    function QueryViewModel(){
        var self = this;

        self.first = ko.observable('');
        self.last = ko.observable('');
        self.phone = ko.observable('');

        self.letter = ko.observable();

        self.letters = {{ letters|safe }};

        self.policies = ko.observableArray();
        self.queued = ko.observable(false);

        self.clear = function() {
            self.policies.removeAll();
            self.first('');
            self.last('');
            self.phone('');
        }

        self.search = function() {
            // postJson here
            var queryObj = {
                first: self.first(),
                last: self.last(),
                phone: self.phone()
            }

            $.postJSON("{{ url_for('report_search') }}", queryObj, function(result) {
                // first empty our policy table
                self.policies([]);

                // add results
                result.policies.forEach(function(p) {
                    self.policies.push(new Policy(p));
                });
            });
        }    

    }

    var qvm = new QueryViewModel()

    ko.applyBindings(qvm);
    </script>