我有一组包含键,值对(作为列)的数据帧,每个数据帧都有一个键的子集。我想将它们全部合并到一个初始数据帧的单个值列中,其中包含来自相同密钥空间的密钥(需要保留其他列)。
例如,给定:
DF:
key a
0 1 A1
1 20 A2
2 33 A3
3 44 A4
DF2:
key value
0 1 V21
1 20 NaN
2 33 V23
3 44 NaN
4 55 V25
DF3:
key value
0 1 NaN
1 20 V32
我能做到:
df['value'] = ''
df2.dropna(inplace=True)
df3.dropna(inplace=True)
df.loc[df.key.isin(df2.key), 'value'] = df2.value
df.loc[df.key.isin(df3.key), 'value'] = df3.value
并得到我想要的结果:
key a value
0 1 A1 V21
1 20 A2 V32
2 33 A3 V23
3 44 A4
键是int64,值是object(str)。
问题在于,当我在更大的df数据帧上使用此方案时,结果是值列设置为NaN(在Pandas 0.13& 0.14上)
例如:(此处提供的数据:df.csv& common.csv)
# read data - both pre-sorted by key
df = pandas.read_csv('df.csv') # ~110MB / ~3M rows
common = pandas.read_csv('common.csv') # 83 rows
all(common.key.isin(df.key)) # True - all keys in common are in df
df['value']='' # new col of empty strings
df.loc[df.key.isin(common.key), 'value'] = common.value # set select df values (?)
any(common.value.isin(df.value)) # False - no values from common are in df (!)
all(pandas.isnull(df.value) | (df.value=='') ) # True - all either '' or null/NaN
感谢有关如何达到预期效果的任何帮助。
正如@Jeff指出的那样,这不是Pandas的错误,而是预期的行为。将Pandas对象(例如DataFrame)分配给''一个DataFrame(例如,如上所述由.loc返回),Pandas试图对齐'这两个指数。也就是说,它通过Pandas索引将RHS上的行分配给LHS上的行。
在上面的例子中,RHS有一个简单的整数顺序索引 - 行号,而LHS索引是来自df的所选行号的子集( - 即df也有一个顺序整数索引,其中切片选择一个子集)。对于LHS上RHS上没有匹配索引的行,Pandas会分配NA。
优雅的解决方案是将密钥列的内容索引为df和common索引。然后,分配将按计划进行 - 根据密钥的值将行从RHS分配给LHS。这更自然,避免了需要预先排序或子集。
@ ct-zhu的答案之所以有效,是因为访问RHS的.values属性会返回一个Numpy数组,该数组没有Panda风格索引的概念。当Pandas在RHS上收到这样一个对象时,它会在没有尝试对齐索引的情况下进行分配( - 因为我的例子预先安排两个通过排序处于相同的顺序,所以这是有效的)
答案 0 :(得分:1)
根据您刚才描述的内容,它应该是merge
的经典案例吗?对于您的真实案例数据:
In [6]:
print pd.merge(df, common, left_on='key', right_on='key')
key a datetime value
0 3559045188 455.22 2013-01-03 02:18:00 0584e46e2ccefa0c
1 3559045189 378.23 2013-01-03 02:19:00 df15f61e8d2dbbd4
2 3559045191 13.49 2013-01-03 04:46:00 bc75d05dae4a1aaf
3 3559045192 7.69 2013-01-03 04:48:00 41db9e3f3c9996e0
4 3559045398 641.10 2013-01-02 22:45:00 4933d72213672819
5 3559045401 548.41 2013-01-02 22:49:00 f698ef75efda0af8
6 3559045412 6.22 2013-01-02 23:12:00 3d48cc4c1d0b6f26
7 3559045414 54.97 2013-01-02 23:19:00 a9b2b5b33be185a1
8 3559045417 275.95 2013-01-02 23:22:00 1a59cfcf32351d81
9 3559045418 407.95 2013-01-02 23:22:00 af81dac601f02f36
10 3559045419 10.00 2013-01-02 23:23:00 849a2fa3e46a0f2e
... ... ... ...
[83 rows x 4 columns]
应该是评论,但我想显示结果数据框
另外,要将df2
和df3
(显示在上半部分或您的问题中)合并在一起,请使用pd.concat((df2, df3)).dropna()
。如果您有重复密钥,则需要.drop_duplicate()
,但它依赖于您计划保留的值。
您只需再添加一个values
In [77]:
DF=df.copy()
DF['value']=np.nan
DF.ix[df.key.isin(common.key),'value']=common.ix[common.key.isin(DF.key), 'value'].values
#Assume their are both sorted and common may contain keys df doesn't.
print DF.dropna().head(10)
key a datetime value
2364554 3559045188 455.22 2013-01-03 02:18:00 0584e46e2ccefa0c
2364555 3559045189 378.23 2013-01-03 02:19:00 df15f61e8d2dbbd4
2364557 3559045191 13.49 2013-01-03 04:46:00 bc75d05dae4a1aaf
2364558 3559045192 7.69 2013-01-03 04:48:00 41db9e3f3c9996e0
2364764 3559045398 641.10 2013-01-02 22:45:00 4933d72213672819
2364767 3559045401 548.41 2013-01-02 22:49:00 f698ef75efda0af8
2364778 3559045412 6.22 2013-01-02 23:12:00 3d48cc4c1d0b6f26
2364780 3559045414 54.97 2013-01-02 23:19:00 a9b2b5b33be185a1
2364783 3559045417 275.95 2013-01-02 23:22:00 1a59cfcf32351d81
2364784 3559045418 407.95 2013-01-02 23:22:00 af81dac601f02f36
[10 rows x 4 columns]
这可能是个错误。我不确定。
但是,一次添加一个common
的效率非常低,因为isin
需要花费大量时间来处理非常大的df
数据帧。我的机器上需要大约3秒钟。