NullPointerException
s - исключения, возникающие при попытке использовать ссылку, которая указывает на отсутствие местоположения в памяти (null), как если бы она ссылалась на объект. Вызов метода по нулевой ссылке или попытка получить доступ к полю нулевой ссылки вызовет функцию NullPointerException
. Они наиболее распространены, но другие способы перечислены на странице NullPointerException
javadoc.
Вероятно, самый быстрый пример кода, который я мог бы придумать для иллюстрации NullPointerException
, be:
public class Example {
public static void main(String[] args) {
Object obj = null;
obj.hashCode();
}
}
В первой строке внутри main
я явно устанавливаю ссылку Object
obj
равной null
. Это означает, что у меня есть ссылка, но она не указывает на какой-либо объект. После этого я пытаюсь обработать ссылку так, как если бы она указывала на объект, вызывая метод на нем. Это приводит к NullPointerException
, потому что нет кода для выполнения в местоположении, на которое указывает ссылка.
(Это техничность, но я думаю, что она упоминает: ссылка, которая указывает на null, равна 't то же, что и указатель C, указывающий на недопустимую ячейку памяти. Нулевой указатель буквально не указывает на в любом месте , который отличается от указаний на местоположение, которое оказывается недопустимым.)
Предполагаемый импорт:
import pandas as pd
Ответ Джона Галта - это в основном операция reduce
. Если у меня больше нескольких блоков данных, я бы поместил их в список, подобный этому (сгенерированный через списки или циклы):
dfs = [df0, df1, df2, dfN]
Предполагая, что у них есть общий столбец, например name
в вашем примере, я бы сделал следующее:
df_final = reduce(lambda left,right: pd.merge(left,right,on='name'), dfs)
Таким образом, ваш код должен работать с любым количеством файлов данных, которые вы хотите объединить.
Изменить 1 августа 2016 года : для тех, кто использует Python 3: reduce
, был перемещен в functools
. Поэтому, чтобы использовать эту функцию, вам сначала нужно будет импортировать этот модуль:
from functools import reduce
Это также можно сделать следующим образом для списка файлов данных df_list
:
df = df_list[0]
for df_ in df_list[1:]:
df = df.merge(df_, on='join_col_name')
или если данные в рамке находятся в объекте генератора (например, для уменьшения потребления памяти):
df = next(df_list)
for df_ in df_list:
df = df.merge(df_, on='join_col_name')
Для выполнения операций join не требуется мультииндекса. Нужно просто правильно установить индексный столбец для выполнения операций объединения (например, команда df.set_index('Name')
)
Операция join
по умолчанию выполняется по индексу. В вашем случае вам просто нужно указать, что столбец Name
соответствует вашему индексу. Ниже приведен пример
Может оказаться полезным [учебник .
# Simple example where dataframes index are the name on which to perform the join operations
import pandas as pd
import numpy as np
name = ['Sophia' ,'Emma' ,'Isabella' ,'Olivia' ,'Ava' ,'Emily' ,'Abigail' ,'Mia']
df1 = pd.DataFrame(np.random.randn(8, 3), columns=['A','B','C'], index=name)
df2 = pd.DataFrame(np.random.randn(8, 1), columns=['D'], index=name)
df3 = pd.DataFrame(np.random.randn(8, 2), columns=['E','F'], index=name)
df = df1.join(df2)
df = df.join(df3)
# If you a 'Name' column that is not the index of your dataframe, one can set this column to be the index
# 1) Create a column 'Name' based on the previous index
df1['Name']=df1.index
# 1) Select the index from column 'Name'
df1=df1.set_index('Name')
# If indexes are different, one may have to play with parameter how
gf1 = pd.DataFrame(np.random.randn(8, 3), columns=['A','B','C'], index=range(8))
gf2 = pd.DataFrame(np.random.randn(8, 1), columns=['D'], index=range(2,10))
gf3 = pd.DataFrame(np.random.randn(8, 2), columns=['E','F'], index=range(4,12))
gf = gf1.join(gf2, how='outer')
gf = gf.join(gf3, how='outer')
В python
3.6.3 с pandas
0.22.0 вы также можете использовать concat
до тех пор, пока вы установите в качестве индекса столбцы, которые вы хотите использовать для соединения
pd.concat(
(iDF.set_index('name') for iDF in [df1, df2, df3]),
axis=1, join='inner'
).reset_index()
где df1
, df2
и df3
определяются так же, как в ответе Джона Галта
import pandas as pd
df1 = pd.DataFrame(np.array([
['a', 5, 9],
['b', 4, 61],
['c', 24, 9]]),
columns=['name', 'attr11', 'attr12']
)
df2 = pd.DataFrame(np.array([
['a', 5, 19],
['b', 14, 16],
['c', 4, 9]]),
columns=['name', 'attr21', 'attr22']
)
df3 = pd.DataFrame(np.array([
['a', 15, 49],
['b', 4, 36],
['c', 14, 9]]),
columns=['name', 'attr31', 'attr32']
)
Ниже приведен метод слияния словаря фреймов данных, при котором имена столбцов синхронизируются со словарем. Кроме того, при необходимости он заполняет отсутствующие значения:
def MergeDfDict(dfDict, onCols, how='outer', naFill=None):
keys = dfDict.keys()
for i in range(len(keys)):
key = keys[i]
df0 = dfDict[key]
cols = list(df0.columns)
valueCols = list(filter(lambda x: x not in (onCols), cols))
df0 = df0[onCols + valueCols]
df0.columns = onCols + [(s + '_' + key) for s in valueCols]
if (i == 0):
outDf = df0
else:
outDf = pd.merge(outDf, df0, how=how, on=onCols)
if (naFill != None):
outDf = outDf.fillna(naFill)
return(outDf)
def GenDf(size):
df = pd.DataFrame({'categ1':np.random.choice(a=['a', 'b', 'c', 'd', 'e'], size=size, replace=True),
'categ2':np.random.choice(a=['A', 'B'], size=size, replace=True),
'col1':np.random.uniform(low=0.0, high=100.0, size=size),
'col2':np.random.uniform(low=0.0, high=100.0, size=size)
})
df = df.sort_values(['categ2', 'categ1', 'col1', 'col2'])
return(df)
size = 5
dfDict = {'US':GenDf(size), 'IN':GenDf(size), 'GER':GenDf(size)}
MergeDfDict(dfDict=dfDict, onCols=['categ1', 'categ2'], how='outer', naFill=0)
Существует другое решение из документации pandas (которую я не вижу здесь),
, используя .append
>>> df = pd.DataFrame([[1, 2], [3, 4]], columns=list('AB'))
A B
0 1 2
1 3 4
>>> df2 = pd.DataFrame([[5, 6], [7, 8]], columns=list('AB'))
A B
0 5 6
1 7 8
>>> df.append(df2, ignore_index=True)
A B
0 1 2
1 3 4
2 5 6
3 7 8
ignore_index=True
используется для игнорирования индекса добавленного фрейма данных, заменяя его следующим индексом, доступным в исходном.
Если есть разные имена столбцов, будет введен Nan
.
join
Метод join
построен именно для этих типов ситуаций. Вы можете присоединиться к любому числу DataFrames вместе с ним. Вызывающий DataFrame соединяется с индексом коллекции переданных DataFrames. Чтобы работать с несколькими DataFrames, вы должны поместить столбцы соединения в индекс.
Код будет выглядеть примерно так:
filenames = ['fn1', 'fn2', 'fn3', 'fn4',....]
dfs = [pd.read_csv(filename, index_col=index_col) for filename in filenames)]
dfs[0].join(dfs[1:])
С данными @ zero вы можете сделать это :
df1 = pd.DataFrame(np.array([
['a', 5, 9],
['b', 4, 61],
['c', 24, 9]]),
columns=['name', 'attr11', 'attr12'])
df2 = pd.DataFrame(np.array([
['a', 5, 19],
['b', 14, 16],
['c', 4, 9]]),
columns=['name', 'attr21', 'attr22'])
df3 = pd.DataFrame(np.array([
['a', 15, 49],
['b', 4, 36],
['c', 14, 9]]),
columns=['name', 'attr31', 'attr32'])
dfs = [df1, df2, df3]
dfs = [df.set_index('name') for df in dfs]
dfs[0].join(dfs[1:])
attr11 attr12 attr21 attr22 attr31 attr32
name
a 5 9 5 19 15 49
b 4 61 14 16 4 36
c 24 9 4 9 14 9
Вы можете попробовать это, если у вас есть 3 фрейма данных
# Merge multiple dataframes
df1 = pd.DataFrame(np.array([
['a', 5, 9],
['b', 4, 61],
['c', 24, 9]]),
columns=['name', 'attr11', 'attr12'])
df2 = pd.DataFrame(np.array([
['a', 5, 19],
['b', 14, 16],
['c', 4, 9]]),
columns=['name', 'attr21', 'attr22'])
df3 = pd.DataFrame(np.array([
['a', 15, 49],
['b', 4, 36],
['c', 14, 9]]),
columns=['name', 'attr31', 'attr32'])
pd.merge(pd.merge(df1,df2,on='name'),df3,on='name')
в качестве альтернативы, как указано cwharland
df1.merge(df2,on='name').merge(df3,on='name')
df1.merge(df2,on='name').merge(df3,on='name')
– cwharland
15 May 2014 в 13:26
name1
, name2
и name3
соответственно
– ps0604
10 April 2018 в 10:31
df1.merge(df2,left_on='name1', right_on='name2').merge(df3,left_on='name1', right_on='name3').drop(columns=['name2', 'name3']).rename(columns={'name1':'name'})
– Bokje
1 June 2018 в 08:32
reduce
был заменен наfunctools.reduce
Итакimport functools functools.reduce(.......)
– MattR 7 June 2017 в 20:34name1
,name2
иname3
соответственно. – ps0604 10 April 2018 в 10:16n-1
вызываем функцию слияния? Я думаю, в этом случае, когда число кадров данных невелико, это не имеет значения, но мне интересно, есть ли более масштабируемое решение. – eapolinario 21 June 2018 в 20:09