Спроба об’єднати 2 кадри даних, але отримати ValueError


85

Це мої два кадри даних, збережені у двох змінних:

> print(df.head())
>
          club_name  tr_jan  tr_dec  year
    0  ADO Den Haag    1368    1422  2010
    1  ADO Den Haag    1455    1477  2011
    2  ADO Den Haag    1461    1443  2012
    3  ADO Den Haag    1437    1383  2013
    4  ADO Den Haag    1386    1422  2014
> print(rankingdf.head())
>
           club_name  ranking  year
    0    ADO Den Haag    12    2010
    1    ADO Den Haag    13    2011
    2    ADO Den Haag    11    2012
    3    ADO Den Haag    14    2013
    4    ADO Den Haag    17    2014

Я намагаюся об'єднати ці два за допомогою цього коду:

new_df = df.merge(ranking_df, on=['club_name', 'year'], how='left')

Додано те, як = 'left', оскільки у моєму rank_df у мене менше точок даних, ніж у моєму стандартному df.

Очікувана поведінка така:

> print(new_df.head()) 
> 

      club_name  tr_jan  tr_dec  year    ranking
0  ADO Den Haag    1368    1422  2010    12
1  ADO Den Haag    1455    1477  2011    13
2  ADO Den Haag    1461    1443  2012    11
3  ADO Den Haag    1437    1383  2013    14
4  ADO Den Haag    1386    1422  2014    17

Але я отримую цю помилку:

ValueError: Ви намагаєтесь об’єднати стовпці об’єктів та int64. Якщо ви хочете продовжити, вам слід використовувати pd.concat

Але я не хочу використовувати concat, оскільки хочу об'єднати дерева, а не просто додати їх.

Ще одна дивна поведінка на мій погляд - це те, що мій код працює, якщо я зберігаю перший df у .csv, а потім завантажую .csv у фрейм даних.

Код для цього:

df = pd.DataFrame(data_points, columns=['club_name', 'tr_jan', 'tr_dec', 'year'])
df.to_csv('preliminary.csv')

df = pd.read_csv('preliminary.csv', index_col=0)

ranking_df = pd.DataFrame(rankings, columns=['club_name', 'ranking', 'year'])

new_df = df.merge(ranking_df, on=['club_name', 'year'], how='left')

Я думаю, що це пов’язано з параметром index_col = 0. Але я не маю ідеї виправити це без необхідності його зберігати, це не має великого значення, але це свого роду досада, що я повинен це робити.


Отримав ту саму помилку, коли я використовував об'єднання замість об'єднання.
Модем Ракеш, гоуд,

Відповіді:


116

В одному з ваших фреймів даних рік є рядком, а інший - це int64, ви можете спочатку перетворити його, а потім приєднатися (наприклад, df['year']=df['year'].astype(int)або як запропонував RafaelC df.year.astype(int))

Редагувати: Також зверніть увагу на коментар Андерсона Чжу: На той випадок, якщо у вас є Noneабо відсутні значення в одному з ваших кадрів даних, вам потрібно використовувати Int64замість int. Дивіться посилання тут .


Дякую, це спрацювало. Якимось дивно, оскільки я щороку економив як інт.
PEREZje

13
чому ні df.year.astype(int)?
rafaelc

Врешті-решт я виправив це іншим способом, просто зберегши змінні всього року у фреймі даних як цілі числа. Ніколи не думав, що це струни.
PEREZje

@RafaelC, що, мабуть, краще
Арнон Ротем-Галь-Оз

2
Про всяк випадок, якщо в одному з ваших фреймів даних немає значення None або відсутні значення, вам потрібно використовувати Int64замість int. Дивіться посилання тут .
Anderson Zhu

42

Я виявив, що обидва мої файли DFS мали однаковий стовпець типу ( str), але перемикалися з joinна mergeвирішення проблеми.


7
Те ж саме. Якщо хтось знає чому, будь ласка, напишіть нижче :)
raummensch

Те саме. Насправді дуже дивно, я лише здогадуюсь, що навіть якщо все має тип object, при виконанні панди приєднання намагається ще раз неявно оцінити типи даних ... Але злиття це вирішило і для мене.
крок

6
@raummensch та @ 15Step, у мене була та ж проблема. Причину того, чому злиття працює над рядками, але приєднання не може бути знайдено у відповіді @MatthiasFripp тут: посилання . В основному df1.join(df2)завжди зливається за допомогою індексу, df2тоді як df1.merge(df2)буде зливатися в стовпці. Отже, в основному ми намагалися об’єднати на основі рядка та цілого числа, хоча обидва стовпці були рядками ..
Ніко

3

Це трапляється, коли спільні стовпці в обох таблицях мають різний тип даних.

Приклад: У таблиці 1 ви маєте дату як рядок, тоді як у таблиці 2 - дату та час. тому перед об’єднанням нам потрібно змінити дату на загальний тип даних.


2

Відповідь @Arnon Rotem-Gal-Oz здебільшого є правильною. Але я хотів би вказати на різницю між df['year']=df['year'].astype(int)і df.year.astype(int). df.year.astype(int)повертає вигляд кадру даних і не змінює явно тип, принаймні в pandas 0.24.2. df['year']=df['year'].astype(int)явно змінити тип, оскільки це призначення. Я стверджую, що це найбезпечніший спосіб назавжди змінити тип d стовпця.

Приклад:

df = pd.DataFrame({'Weed': ['green crack', 'northern lights', 'girl scout cookies'], 'Qty':[10,15,3]}) df.dtypes

Бур’ян, Qty int64

df['Qty'].astype(str) df.dtypes

Бур’ян, Qty int64

Навіть встановлення аргументу inplace на True не допомагає часом. Я не знаю, чому це трапляється. У більшості випадків inplace = True дорівнює явному призначенню.

df['Qty'].astype(str, inplace = True) df.dtypes

Бур’ян, Qty int64

Тепер завдання,

df['Qty'] = df['Qty'].astype(str) df.dtypes

Бур’ян, Qty


1

Додатково: коли ви зберігаєте df у форматі .csv, дата-час (рік у цьому конкретному випадку) зберігається як об’єкт, тому вам потрібно перетворити його у ціле число (рік у цьому конкретному випадку) під час об’єднання. Ось чому, коли ви завантажуєте обидва df з файлів csv, ви можете легко об'єднати їх, тоді як вище помилка з'явиться, якщо один df завантажується з файлів csv, а інший - із існуючого df. Це дещо дратує, але майте просте рішення, якщо мати на увазі.


0

це просте рішення працює для мене

    final = pd.concat([df, rankingdf], axis=1, sort=False)

але вам може знадобитися спочатку скинути якийсь дублікат стовпця.


0

Спочатку перевірте тип стовпців, які потрібно об’єднати. Ви побачите, що одна з них є рядком, де інша int. Потім перетворіть його на int у такий код:

df["something"] = df["something"].astype(int)

merged = df.merge[df1, on="something"]
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.