Создайте новый столбец, используя непустое значение из каждой строки, используя команду apply

Я попробовал 3 компилятора: MS Visual Studio 2012, gcc481 и Intel icl 13.1. Все они предупреждают, когда вы указываете. Я обнаружил, что gcc и MS автоматически генерируют код инициализации для tmp1, даже когда они предупреждают об отсутствии инициализации. Компилятор MS генерирует нежелательный доступ к памяти: movaps xmm0,xmmword ptr [rsp]. Gcc генерирует более эффективный xorps xmm0,xmm0. Поэтому в случае gcc добавление tmp1=_mm_setzero_ps() устраняет предупреждение и создает точно такой же код, как и без него. В случае MS добавление tmp1=_mm_setzero_ps() делает код короче и, вероятно, быстрее. Только компилятор Intel достаточно умен, чтобы избежать ненужной инициализации. Ниже приведено возможное обходное решение для компиляторов MS и gcc:

    __m128 tmp1 = _mm_loadh_pi(_mm_load_ps (src), (__m64*)(src + 4));

Генерация кода:

movaps      xmm0,xmmword ptr [rcx]
movhps      xmm0,qword ptr [rcx+10h]

Он выглядит короче, но его следует сравнивать, чтобы убедиться, что он быстрее.

09/12/2013: тестовый код для различных идей подавления предупреждений:

#include <xmmintrin.h>
#include <stdint.h>
#include <stdio.h>

//---------------------------------------------------------------------------
// original code from http://download.intel.com/design/PentiumIII/sml/24504301.pdf
__m128 func1 (float *src)
    {
    __m128 tmp1;
    tmp1 = _mm_loadh_pi(_mm_loadl_pi(tmp1, (__m64*)(src)), (__m64*)(src+ 4));
    return tmp1;
    }

//---------------------------------------------------------------------------
// original code plus tmp1 initialization
__m128 func2 (float *src)
    {
    __m128 tmp1 = _mm_loadh_pi(_mm_loadl_pi (_mm_setzero_ps (), (__m64*)(src)), (__m64*)(src + 4));
    return tmp1;
    }

//---------------------------------------------------------------------------
// use redundant load to eliminate warning 
__m128 func3 (float *src)
    {
    __m128 tmp1 = _mm_loadh_pi(_mm_load_ps (src), (__m64*)(src + 4));
    return tmp1;
    }

//---------------------------------------------------------------------------

static void dump (void *data)
    {
    float *f16 = data;
    int index;

    for (index = 0; index < 4; index++)
        printf ("%g ", f16 [index]);
    printf ("\n");
    }

//---------------------------------------------------------------------------

int main (void)
    {
    float f [8] = {1, 2, 3, 4, 5, 6, 7, 8};
    __m128 tmp;

    tmp = func1 (f);
    dump (&tmp);
    tmp = func2 (f);
    dump (&tmp);
    tmp = func3 (f);
    dump (&tmp);
    return 0;
    }

команды сборки:

gcc  -O3 -Wall -Wfatal-errors sample.c -osample.exe
objdump -Mintel --disassemble sample.exe > disasm.txt

cl -Ox -Zi -W4 sample.c
dumpbin -disasm -symbols sample.exe > disasm.txt

icl -Ox -Zi sample.c                                           
dumpbin -disasm -symbols sample.exe > disasm.txt                  
0
задан Ronak Shah 17 January 2019 в 01:44
поделиться

3 ответа

Как насчет использования Reduce с dplyr::coalesce?

library(dplyr)

df <- data.frame(grp_A = c(13, NA, NA, NA, NA, 20, NA),
                 grp_B = c(NA, 59, 66, NA, NA, NA, NA),
                 grp_C = c(NA, NA, NA, 23, 42, NA, NA))

mutate(df, value = Reduce(coalesce, df))

Результат:

  grp_A grp_B grp_C value
1    13    NA    NA    13
2    NA    59    NA    59
3    NA    66    NA    66
4    NA    NA    23    23
5    NA    NA    42    42
6    20    NA    NA    20
7    NA    NA    NA    NA

Другой вариант - использовать rowSums:

df$value <- rowSums(df, na.rm = T)

df[df$value == 0, ] <- NA 
[ 1111] Кроме того, с точки зрения производительности, базовое Reduce решение представляется наиболее эффективным:

microbenchmark::microbenchmark(
  Reduce = Reduce(coalesce, df), 
  purrr = purrr::reduce(df, coalesce),
  rowMeans = rowMeans(df,na.rm=T), 
  rowSums = rowSums(df, na.rm = T), 
  cbind = df[cbind(1:nrow(df), max.col(!is.na(df)))],
  times = 1000
)

Unit: microseconds
     expr     min       lq     mean   median       uq       max neval cld
   Reduce  83.507 107.2095 145.4134 121.4320 137.8410 12190.845  1000  a 
    purrr 205.667 269.1175 357.5908 304.8540 342.4135 24316.051  1000   b
 rowMeans 129.089 159.3555 196.1438 174.4890 194.9095  5481.523  1000  a 
  rowSums 129.454 157.1680 197.2731 173.5775 196.0035  7685.874  1000  a 
    cbind 267.294 331.8385 408.3179 368.4860 410.2400  4533.050  1000   b
0
ответ дан JdeMello 17 January 2019 в 01:44
поделиться

База R rowMeans

df$new=rowMeans(df,na.rm=T)
df
  grp_A grp_B grp_C new
1    13    NA    NA  13
2    NA    59    NA  59
3    NA    66    NA  66
4    NA    NA    23  23
5    NA    NA    42  42
6    20    NA    NA  20
7    NA    NA    NA NaN
0
ответ дан Wen-Ben 17 January 2019 в 01:44
поделиться

Нет необходимости использовать apply, поскольку для каждой строки у вас будет только одно значение, отличное от NA, мы можем получить это значение, используя max.col, не беспокоясь о связях.

df$value <- df[cbind(1:nrow(df), max.col(!is.na(df)))]

df
#  grp_A grp_B grp_C value
#1    13    NA    NA    13
#2    NA    59    NA    59
#3    NA    66    NA    66
#4    NA    NA    23    23
#5    NA    NA    42    42
#6    20    NA    NA    20
#7    NA    NA    NA    NA

max.col дает нам индекс номера столбца, который имеет максимальное значение для каждой строки, и, поскольку мы переносим его в !is.na, он даст нам индекс TRUE.

max.col(!is.na(df))
#[1] 1 2 2 3 3 1 2

Причина, по которой вы apply не сработали, заключается в том, что в вашем последнем ряду было все NA с, и x[!is.na(x)] не сработал. Если вы удалите эту строку и запустите свою функцию, она будет работать

apply(df[-7, ], 1,function(x) x[!is.na(x)])
# 1  2  3  4  5  6 
#13 59 66 23 42 20 

Мы также можем узнать значение max для каждой строки, удалив NA, но это вернет -Inf для строк со всеми NA с

apply(df, 1,max, na.rm = TRUE)
#[1]   13   59   66   23   42   20 -Inf
0
ответ дан Ronak Shah 17 January 2019 в 01:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: