通过匹配来自不同列和不同行的值来创建新列python pandas

时间:2017-08-17 11:31:34

标签: python pandas dataframe

我有一个大约2000行的多列df。 df看起来像这样:

 site     le_cell  le_id    ca    ca_id
1  101       1011      1    NAN    NAN
2  101       1012      2    NAN    NAN
3  101       1013      3    NAN    NAN
4  110       1101      1     2      11
5  110       1102      2     2      12
6  110       1103      3     2      13
7  110       1104      11    2       1
8  110       1105      12    2       2
9  110       1106      13    2       3

这是问题所在。我需要创建一个名为'part_id'的新列,值为: Groupby'site',如果没有'ca'(ca = NAN),则'part_id'等于le_id(part_id = le_id)。如果有'ca',则读'ca_id'和'part_id'的值将是1,2,3.1和11 = 1,2和12 = 2,3和13 = 3。 期望的输出:

  site     le_cell  le_id    ca    ca_id  part_id
1  101       1011      1    NAN    NAN      1
2  101       1012      2    NAN    NAN      2
3  101       1013      3    NAN    NAN      3
4  110       1101      1     2      11      1
5  110       1102      2     2      12      2
6  110       1103      3     2      13      3
7  110       1104      11    2       1      1
8  110       1105      12    2       2      2
9  110       1106      13    2       3      3

简单来说,a不能只将所有le_id值从11,12,13转换为1,2,3。所以我需要通过'ca'并与'le_cell'匹配相同的'le_id'就像那个'ca_id'。

我尝试过转换为dict,但它不会很好,真的不知道如何开始。 至少,给我一些提示。

2 个答案:

答案 0 :(得分:1)

我认为您可以创建布尔掩码,然后通过numpy.where将值添加到列:

#if need check if all values per group are NaN
a = df['ca'].isnull().groupby(df['site']).all()
m = df['site'].isin(a.index[a])

#if need check if column ca is NaN
#m= df['ca'].isnull()

d = {11:1,12:2,13:3}
df['part_id'] = np.where(m, df['le_id'], df['ca_id'].replace(d))
print (df)
   site  le_cell  le_id   ca  ca_id  part_id
1   101     1011      1  NaN      0        1
2   101     1012      2  NaN      0        2
3   101     1013      3  NaN      0        3
4   110     1101      1  2.0     11        1
5   110     1102      2  2.0     12        2
6   110     1103      3  2.0     13        3
7   110     1104     11  2.0      1        1
8   110     1105     12  2.0      2        2
9   110     1106     13  2.0      3        3

答案 1 :(得分:1)

您可以定义一个映射器并使用applylambda一起根据您的条件分配值:

mapper = {1: 1,
          11: 1,
          2: 2,
          12: 2,
          3: 3,
          13: 3}

df['part_id'] = df.apply(lambda row: row.le_id if np.isnan(row.ca) else mapper[row.ca_id], axis=1)

    ca  ca_id  le_cell  le_id  site  part_id
0  NaN    NaN     1011      1   101      1.0
1  NaN    NaN     1012      2   101      2.0
2  NaN    NaN     1013      3   101      3.0
3  2.0   11.0     1101      1   110      1.0
4  2.0   12.0     1102      2   110      2.0
5  2.0   13.0     1103      3   110      3.0
6  2.0    1.0     1104     11   110      1.0
7  2.0    2.0     1105     12   110      2.0
8  2.0    3.0     1106     13   110      3.0

希望您不要介意float,但如果您这样做是转换:

df['part_id'] = df['part_id'].astype(int)