我希望使用Python 2.7在Pandas中执行一些内连接。这是我正在使用的数据集:
import pandas as pd
import numpy as np
columns = ['s_id', 'c_id', 'c_col1']
index = np.arange(46) # array of numbers for the number of samples
df = pd.DataFrame(columns=columns, index = index)
df.s_id[:15] = 144
df.s_id[15:27] = 105
df.s_id[27:46] = 52
df.c_id[:5] = 1
df.c_id[5:10] = 2
df.c_id[10:15] = 3
df.c_id[15:19] = 1
df.c_id[19:27] = 2
df.c_id[27:34] = 1
df.c_id[34:39] = 2
df.c_id[39:46] = 3
df.c_col1[:5] = ['H', 'C', 'N', 'O', 'S']
df.c_col1[5:10] = ['C', 'O','S','K','Ca']
df.c_col1[10:15] = ['H', 'O','F','Ne','Si']
df.c_col1[15:19] = ['C', 'O', 'F', 'Zn']
df.c_col1[19:27] = ['N', 'O','F','Fe','Zn','Gd','Hg','Pb']
df.c_col1[27:34] = ['H', 'He', 'Li', 'B', 'N','Al','Si']
df.c_col1[34:39] = ['N', 'F','Ne','Na','P']
df.c_col1[39:46] = ['C', 'N','O','F','K','Ca', 'Fe']
以下是数据框:
s_id c_id c_col1
0 144 1 H
1 144 1 C
2 144 1 N
3 144 1 O <--
4 144 1 S
5 144 2 C
6 144 2 O <--
7 144 2 S
8 144 2 K
9 144 2 Ca
10 144 3 H
11 144 3 O <--
12 144 3 F
13 144 3 Ne
14 144 3 Si
15 105 1 C
16 105 1 O
17 105 1 F
18 105 1 Zn
19 105 2 N
20 105 2 O
21 105 2 F
22 105 2 Fe
23 105 2 Zn
24 105 2 Gd
25 105 2 Hg
26 105 2 Pb
27 52 1 H
28 52 1 He
29 52 1 Li
30 52 1 B
31 52 1 N
32 52 1 Al
33 52 1 Si
34 52 2 N
35 52 2 F
36 52 2 Ne
37 52 2 Na
38 52 2 P
39 52 3 C
40 52 3 N
41 52 3 O
42 52 3 F
43 52 3 K
44 52 3 Ca
45 52 3 Fe
我需要在Pandas中执行以下操作:
Inner在Pandas中的元素列(c_col1)上加入。)中生成的单独数据帧。这有点难以理解,所以这里是数据框,我希望从这一步得到什么:
index s_id c_id c_col1
0 144 1 O
1 144 2 O
2 144 3 O
3 105 1 O
4 105 2 F
5 52 1 N
6 52 2 N
7 52 3 N
正如您所看到的,我在第2部分中寻找的内容如下:在每个s_id中,我正在寻找所有c_id值出现的c_col1值。恩。在s_id = 144的情况下,对于c_id = 1,2,3,仅发生O(氧)。我已经在原始数据中使用&#34;&lt; - &#34;来指向这些条目。所以,我想让数据框在c_col1列中显示O 3次,相应的c_id条目将是1,2,3。
条件:
如何用熊猫做到这一点?
答案 0 :(得分:2)
生成单独的数据帧非常简单。你想怎么存储它们?一种方法是在嵌套的dict中,外键是s_id,内键是c_id,内值是数据。你可以用一个相当长但直截了当的词典理解来做:
DF_dict = {s_id :
{c_id : df[(df.s_id == s_id) & (df.c_id == c_id)] for c_id in df[df.s_id == s_id]['c_id'].unique()}
for s_id in df.s_id.unique()}
然后例如:
In [12]: DF_dict[52][2]
Out[12]:
s_id c_id c_col1
34 52 2 N
35 52 2 F
36 52 2 Ne
37 52 2 Na
38 52 2 P
我不明白你问题的第二部分。您想要在s_id中加入数据吗?你能说出预期的产量吗?如果你想在每个s_id中做一些事情,你可能最好去探索groupby选项。也许有人理解你想要的东西,但如果你能澄清我可能能够展示一个更好的选择,跳过问题的第一部分......
##################编辑在我看来,你应该直接回答问题2,如果问题1只是你认为有必要解决问题2的一个步骤。事实上,这完全没必要。要解决第二个问题,您需要按s_id对数据进行分组,并根据您的要求转换数据。为了总结您的需求,我看到规则如下:对于按s_id分组的每个数据组,仅返回c__1数据,每个ccol_1数据的每个c_id值都相等。
您可以编写如下函数:
def c_id_overlap(df):
common_vals = [] #container for values of c_col1 that are in ever c_id subgroup
c_ids = df.c_id.unique() #get unique values of c_id
c_col1_values = set(df.c_col1) # get a set of c_col1 values
#create nested list of values. Each inner list contains the c_col1 values for each c_id
nested_c_col_vals = [list(df[df.c_id == ID]['c_col1'].unique()) for ID in c_ids]
#Iterate through the c_col1_values and see if they are in every nested list
for val in c_col1_values:
if all([True if val in elem else False for elem in nested_c_col_vals]):
common_vals.append(val)
#return a slice of the dataframe that only contains values of c_col1 that are in every
#c_id
return df[df.c_col1.isin(common_vals)]
然后将其传递给apply
上按s_id分组的数据:
df.groupby('s_id', as_index = False).apply(c_id_overlap)
给出了以下输出:
s_id c_id c_col1
0 31 52 1 N
34 52 2 N
40 52 3 N
1 16 105 1 O
17 105 1 F
18 105 1 Zn
20 105 2 O
21 105 2 F
23 105 2 Zn
2 3 144 1 O
6 144 2 O
11 144 3 O
这似乎就是你要找的。 p> ###########编辑:附加说明:
因此,apply
将每个分组数据块传递给函数,并且一旦针对每组数据完成此操作,这些部分就会粘合在一起。
因此,请考虑第一组传递s_id
== 105.函数的第一行创建一个空列表common_vals
,它将包含出现在数据的每个子组中的那些周期性元素(即相对于c_id
)的每个值。
第二行获取&#39; c_id&#39;的唯一值,在本例中为[1, 2]
,并将它们存储在名为c_ids
第三行创建一组c_col1
的值,在这种情况下会产生:
{'C', 'F', 'Fe', 'Gd', 'Hg', 'N', 'O', 'Pb', 'Zn'}
第四行创建一个嵌套列表结构nested_c_col_vals
,其中每个内部列表是与c_ids
数组中每个元素关联的唯一值的列表。在这种情况下,这看起来像这样:
[['C', 'O', 'F', 'Zn'], ['N', 'O', 'F', 'Fe', 'Zn', 'Gd', 'Hg', 'Pb']]
现在迭代c_col1_values
列表中的每个元素,并且对于每个元素,程序确定该元素是否出现在nested_c_col_vals
对象的每个内部列表中。 all
函数中的bulit确定backets之间序列中的每个项目是True
还是非零(您需要检查此项)。所以:
In [10]: all([True, True, True])
Out[10]: True
In [11]: all([True, True, True, False])
Out[11]: False
In [12]: all([True, True, True, 1])
Out[12]: True
In [13]: all([True, True, True, 0])
Out[13]: False
In [14]: all([True, 1, True, 0])
Out[14]: False
所以在这种情况下,让我们说“C&#39;是迭代的第一个元素。 all()
支持中的列表理解说,查看每个内部列表,看看元素是否在那里。如果是,则True
如果不是False
。所以在这种情况下,这解决了:
all([True, False])
当然是False
。当元素是&#39; Zn&#39;这个操作的结果是
all([True, True])
解析为True
。因此&#39; Zn&#39;被附加到common_vals
列表。
完成此过程后,common_vals
中的值为:
['O', 'F', 'Zn']
如上所述,return语句根据vaues os c_col1
是否在列表common_vals
中来简单地切片数据块。
然后对每个剩余的组重复这一过程,并将数据粘合在一起。
希望这有帮助