根据多个不同的列条目将系列分配给 pandas 数据框

Assigning a Series to a pandas Dataframe depending on multiple different column entries

我有一个系列和一个 DataFrame:

Series:
1    128
2    112
3    110

其中 Series 索引表示月份

DataFrame

   month     c1       c2
0  1         a       0
1  2         a       0
2  3         a       0
3  1         b       0
4  2         b       0
5  5         b       0
6  1         c       0
7  2         c       0
8  1         d       0
9  2         d       0

我想应用系列的值,以便月份匹配,但仅限于 c1 具有特定值的地方。

我试过使用

df = ...
series = ... 

df.loc[df['c1'] == 'a', 'c2'] = series

但这行不通,因为它没有使用月份作为索引。我怎样才能让它考虑到 DataFrame 中的月份?

Expected Result (c1 = a):

   month     c1       c2
0  1         a       128
1  2         a       112
2  3         a       110
3  1         b       0
4  2         b       0
5  5         b       0
6  1         c       0
7  2         c       0
8  1         d       0
9  2         d       0

另外,如果我用同一系列申请c1==b,预期结果是这样的(因为没有3月,只有5月)

Expected Result (c1 = b):

   month     c1       c2
0  1         a       0
1  2         a       0
2  3         a       0
3  1         b       128
4  2         b       112
5  5         b       0
6  1         c       0
7  2         c       0
8  1         d       0
9  2         d       0

为了在两侧使用 Series.map column month, if no match replace missing values by Series.fillnadowncast='int' 参数进行映射以获得更好的性能过滤器:

m = df['c1'] == 'a'
df.loc[m, 'c2'] = df.loc[m, 'month'].map(series).fillna(0, downcast='int')
print (df)
   month c1   c2
0      1  a  128
1      2  a  112
2      3  a  110
3      1  b    0
4      2  b    0
5      5  b    0
6      1  c    0
7      2  c    0
8      1  d    0
9      2  d    0


m = df['c1'] == 'b'
df.loc[m, 'c2'] = df.loc[m, 'month'].map(series).fillna(0, downcast='int')
print (df)
   month c1   c2
0      1  a    0
1      2  a    0
2      3  a    0
3      1  b  128
4      2  b  112
5      5  b    0
6      1  c    0
7      2  c    0
8      1  d    0
9      2  d    0

IIUC,使用map to convert your values from the series, and fillna处理可能缺失的值,然后赋值,它会自动从索引对齐:

df.loc[df['c1'] == 'b', 'c2'] = df['month'].map(series).fillna(0)

或者,两边切片:

mask = df['c1'] == 'b'
df.loc[mask, 'c2'] = df.loc[mask, 'month'].map(series).fillna(0)

输出:

   month c1   c2
0      1  a    0
1      2  a    0
2      3  a    0
3      1  b  128
4      2  b  112
5      5  b    0
6      1  c    0
7      2  c    0
8      1  d    0
9      2  d    0

另一种方法是将您的系列变成一个 df,并将其合并到原始 df,然后用 0 填充 nas,如下所示(并在 'c1' 之后更改 'a' : 在 join_df 中更改要加入的字母):

join_df = pd.DataFrame({'month':series.index,
                        'c1':['a']*len(series),
                        'c2':series})
df[['month', 'c1']].merge(join_df, on=['month', 'c1'], how='left').fillna(0)

输出:

   month c1     c2
0      1  a  128.0
1      2  a  112.0
2      3  a  110.0
3      1  b    0.0
4      2  b    0.0
5      5  b    0.0
6      1  c    0.0
7      2  c    0.0
8      1  d    0.0
9      2  d    0.0

对于'b',它输出:

   month c1     c2
0      1  a    0.0
1      2  a    0.0
2      3  a    0.0
3      1  b  128.0
4      2  b  112.0
5      5  b    0.0
6      1  c    0.0
7      2  c    0.0
8      1  d    0.0
9      2  d    0.0