Копирование столбца из одного DataFrame в другое дает значения NaN?

Этот вопрос задавался очень много раз, и, похоже, он работал для других, однако я получаю значения NaN когда копирую столбец из другого DataFrame (df1 и df2 имеют одинаковую длину).

df1

        date     hour      var1
a   2017-05-01  00:00:00   456585
b   2017-05-01  01:00:00   899875
c   2017-05-01  02:00:00   569566
d   2017-05-01  03:00:00   458756
e   2017-05-01  04:00:00   231458
f   2017-05-01  05:00:00   986545

df2

      MyVar1     MyVar2 
 0  6169.719338 3688.045368
 1  5861.148007 3152.238704
 2  5797.053347 2700.469871
 3  5779.102340 2730.471948
 4  6708.219647 3181.298291
 5  8550.380343 3793.580394

Мне нужно это в моем df2

       MyVar1    MyVar2        date        hour
 0  6169.719338 3688.045368  2017-05-01  00:00:00
 1  5861.148007 3152.238704  2017-05-01  01:00:00
 2  5797.053347 2700.469871  2017-05-01  02:00:00
 3  5779.102340 2730.471948  2017-05-01  03:00:00
 4  6708.219647 3181.298291  2017-05-01  04:00:00
 5  8550.380343 3793.580394  2017-05-01  05:00:00

Я попробовал следующее,

df2['date'] = df1['date']
df2['hour'] = df1['hour']

type(df1)
>> pandas.core.frame.DataFrame

type(df2)
>> pandas.core.frame.DataFrame

Я получаю следующее,

       MyVar1    MyVar2      date       hour
 0  6169.719338 3688.045368  NaN        NaN
 1  5861.148007 3152.238704  NaN        NaN
 2  5797.053347 2700.469871  NaN        NaN

Почему это происходит? Есть еще один пост, в котором обсуждается merge, но мне просто нужно его скопировать. Любая помощь будет оценена.

Ответ 1

Виновником являются неустранимые показатели

Ваши индексы DataFrames различны (и, соответственно, индексы для каждого столбца), поэтому при попытке назначить столбец одного DataFrame другому, pandas будет пытаться выровнять индексы, и, если это не удастся, вставить NaN.

Рассмотрим следующие примеры, чтобы понять, что это значит:

# Setup
A = pd.DataFrame(index=['a', 'b', 'c']) 
B = pd.DataFrame(index=['b', 'c', 'd', 'f'])                                  
C = pd.DataFrame(index=[1, 2, 3])

# Example of alignable indexes - A & B (complete or partial overlap of indexes)
A.index B.index
      a        
      b       b   (overlap)
      c       c   (overlap)
              d
              f

# Example of unalignable indexes - A & C (no overlap at all)
A.index C.index
      a        
      b        
      c        
              1
              2
              3

Если перекрытий нет, панды не могут сопоставить даже одно значение между двумя фреймами данных, чтобы вставить результат присваивания, поэтому на выходе получается столбец, заполненный NaN.

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

df1.index.equals(df2.index)                                                                                               
# False
df1.index.intersection(df2.index).empty                                                                                     
# True

Для решения этой проблемы вы можете использовать любое из следующих решений.

Решение 1. Сброс обоих индексов DataFrames

Вы можете предпочесть эту опцию, если вы изначально не хотели иметь разные индексы или если вы не особенно заботитесь о сохранении индекса.

# Optional, if you want a RangeIndex => [0, 1, 2, ...]
# df1.index = pd.RangeIndex(len(df))
# Homogenize the index values,
df2.index = df1.index
# Assign the columns.
df2[['date', 'hour']] = df1[['date', 'hour']]

Если вы хотите сохранить существующий индекс, но в виде столбца, вы можете использовать reset_index().


Решение 2. Назначьте массивы NumPy (обход индекса по объему)

Это решение будет работать только в том случае, если длины двух фреймов данных совпадают.

# pandas >= 0.24
df2['date'] = df1['date'].to_numpy()
# pandas < 0.24
df2['date'] = df1['date'].values

Чтобы легко назначить несколько столбцов, используйте,

df2 = df2.assign(**{c: df1[c].to_numpy() for c in ('date', 'hour')})

Ответ 2

Попробуй это?

df2['date'] = df1['date'].values
df2['hour'] = df1['hour'].values